diff options
Diffstat (limited to 'tools')
18 files changed, 5656 insertions, 4781 deletions
diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp index 08697ab72d..432f358627 100644 --- a/tools/doc/doc_data.cpp +++ b/tools/doc/doc_data.cpp @@ -917,9 +917,9 @@ Error DocData::save(const String& p_path) { String qualifiers; if (m.qualifiers!="") - qualifiers+="qualifiers=\""+m.qualifiers.xml_escape()+"\""; + qualifiers+=" qualifiers=\""+m.qualifiers.xml_escape()+"\""; - _write_string(f,2,"<method name=\""+m.name+"\" "+qualifiers+" >"); + _write_string(f,2,"<method name=\""+m.name+"\""+qualifiers+">"); if (m.return_type!="") { diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index 7d2871fd10..b13473e61c 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -842,6 +842,17 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func boot_splash=splash; } } + StringName custom_cursor; + { + String splash=Globals::get_singleton()->get("display/custom_mouse_cursor"); //avoid splash from being converted + splash=splash.strip_edges(); + if (splash!=String()) { + if (!splash.begins_with("res://")) + splash="res://"+splash; + splash=splash.simplify_path(); + custom_cursor=splash; + } + } @@ -853,7 +864,7 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func String src=files[i]; Vector<uint8_t> buf; - if (src==boot_splash) + if (src==boot_splash || src==custom_cursor) buf = get_exported_file_default(src); //bootsplash must be kept if used else buf = get_exported_file(src); @@ -1409,12 +1420,12 @@ EditorImportExport::ImageAction EditorImportExport::get_export_image_action() co return image_action; } -void EditorImportExport::set_export_image_shrink(int p_shrink) { +void EditorImportExport::set_export_image_shrink(float p_shrink) { image_shrink=p_shrink; } -int EditorImportExport::get_export_image_shrink() const{ +float EditorImportExport::get_export_image_shrink() const{ return image_shrink; } @@ -1485,12 +1496,12 @@ bool EditorImportExport::image_export_group_get_make_atlas(const StringName& p_e return image_groups[p_export_group].make_atlas; } -void EditorImportExport::image_export_group_set_shrink(const StringName& p_export_group,int p_amount){ +void EditorImportExport::image_export_group_set_shrink(const StringName& p_export_group,float p_amount){ ERR_FAIL_COND(!image_groups.has(p_export_group)); image_groups[p_export_group].shrink=p_amount; } -int EditorImportExport::image_export_group_get_shrink(const StringName& p_export_group) const{ +float EditorImportExport::image_export_group_get_shrink(const StringName& p_export_group) const{ ERR_FAIL_COND_V(!image_groups.has(p_export_group),1); return image_groups[p_export_group].shrink; diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h index 9de6509605..245adffbfd 100644 --- a/tools/editor/editor_import_export.h +++ b/tools/editor/editor_import_export.h @@ -252,7 +252,7 @@ protected: ImageAction action; bool make_atlas; float lossy_quality; - int shrink; + float shrink; }; Vector<Ref<EditorExportPlugin> > export_plugins; @@ -260,7 +260,7 @@ protected: Map<String,int> by_idx; ImageAction image_action; float image_action_compress_quality; - int image_shrink; + float image_shrink; Set<String> image_formats; ExportFilter export_filter; @@ -310,8 +310,8 @@ public: void set_export_image_action(ImageAction p_action); ImageAction get_export_image_action() const; - void set_export_image_shrink(int p_shrink); - int get_export_image_shrink() const; + void set_export_image_shrink(float p_shrink); + float get_export_image_shrink() const; void set_export_image_quality(float p_quality); float get_export_image_quality() const; @@ -326,8 +326,8 @@ public: ImageAction image_export_group_get_image_action(const StringName& p_export_group) const; void image_export_group_set_make_atlas(const StringName& p_export_group,bool p_make); bool image_export_group_get_make_atlas(const StringName& p_export_group) const; - void image_export_group_set_shrink(const StringName& p_export_group,int p_amount); - int image_export_group_get_shrink(const StringName& p_export_group) const; + void image_export_group_set_shrink(const StringName& p_export_group,float p_amount); + float image_export_group_get_shrink(const StringName& p_export_group) const; void image_export_group_set_lossy_quality(const StringName& p_export_group,float p_quality); float image_export_group_get_lossy_quality(const StringName& p_export_group) const; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 03d1dfb743..4f5755bd3d 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -58,6 +58,7 @@ // plugins #include "plugins/sprite_frames_editor_plugin.h" +#include "plugins/sprite_region_editor_plugin.h" #include "plugins/canvas_item_editor_plugin.h" #include "plugins/spatial_editor_plugin.h" #include "plugins/sample_editor_plugin.h" @@ -93,7 +94,7 @@ #include "plugins/light_occluder_2d_editor_plugin.h" #include "plugins/color_ramp_editor_plugin.h" #include "plugins/collision_shape_2d_editor_plugin.h" -#include "os/input.h" +#include "main/input_default.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" @@ -4404,11 +4405,15 @@ EditorNode::EditorNode() { EditorHelp::generate_doc(); //before any editor classes are crated - if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) { - //only if no touchscreen ui hint, set emulation - InputDefault *id = Input::get_singleton()->cast_to<InputDefault>(); - if (id) + InputDefault *id = Input::get_singleton()->cast_to<InputDefault>(); + + if (id) { + + if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) { + //only if no touchscreen ui hint, set emulation id->set_emulate_touch(false); //just disable just in case + } + id->set_custom_mouse_cursor(RES()); } @@ -5471,6 +5476,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( TileSetEditorPlugin(this) ) ); add_editor_plugin( memnew( TileMapEditorPlugin(this) ) ); add_editor_plugin( memnew( SpriteFramesEditorPlugin(this) ) ); + add_editor_plugin( memnew( SpriteRegionEditorPlugin(this) ) ); add_editor_plugin( memnew( Particles2DEditorPlugin(this) ) ); add_editor_plugin( memnew( Path2DEditorPlugin(this) ) ); add_editor_plugin( memnew( PathEditorPlugin(this) ) ); diff --git a/tools/editor/icons/icon_audio_stream_opus.png b/tools/editor/icons/icon_audio_stream_opus.png Binary files differnew file mode 100644 index 0000000000..69b0c83b4d --- /dev/null +++ b/tools/editor/icons/icon_audio_stream_opus.png diff --git a/tools/editor/icons/icon_grid.png b/tools/editor/icons/icon_grid.png Binary files differnew file mode 100644 index 0000000000..dcdd86c9b5 --- /dev/null +++ b/tools/editor/icons/icon_grid.png diff --git a/tools/editor/icons/icon_region_edit.png b/tools/editor/icons/icon_region_edit.png Binary files differnew file mode 100644 index 0000000000..824607f2cc --- /dev/null +++ b/tools/editor/icons/icon_region_edit.png diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 436725f6fb..c0887ab40a 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -828,7 +828,7 @@ Error EditorTextureImportPlugin::import(const String& p_path, const Ref<Resource } -Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &texture,int format, float quality,int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,int shrink) { +Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &texture,int format, float quality,int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink) { if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS || format==IMAGE_FORMAT_COMPRESS_DISK_LOSSY) { @@ -866,7 +866,7 @@ Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &textur int orig_w=image.get_width(); int orig_h=image.get_height(); - image.resize(orig_w/shrink,orig_h/shrink); + image.resize(orig_w/shrink,orig_h/shrink,Image::INTERPOLATE_CUBIC); texture->create_from_image(image,tex_flags); texture->set_size_override(Size2(orig_w,orig_h)); @@ -926,7 +926,7 @@ Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &textur int orig_h=image.get_height(); if (shrink>1) { - image.resize(orig_w/shrink,orig_h/shrink); + image.resize(orig_w/shrink,orig_h/shrink,Image::INTERPOLATE_CUBIC); texture->create_from_image(image,tex_flags); texture->set_size_override(Size2(orig_w,orig_h)); } @@ -987,7 +987,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER; print_line("path: "+p_path+" flags: "+itos(tex_flags)); - int shrink=1; + float shrink=1; if (from->has_option("shrink")) shrink=from->get_option("shrink"); diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h index 02d09d9e17..78383d1d77 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.h +++ b/tools/editor/io_plugins/editor_texture_import_plugin.h @@ -70,7 +70,7 @@ private: static EditorTextureImportPlugin *singleton[MODE_MAX]; //used by other importers such as mesh - Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,int shrink); + Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink); void compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller); public: diff --git a/tools/editor/plugins/path_editor_plugin.cpp b/tools/editor/plugins/path_editor_plugin.cpp index 4af22e956f..f4bdf50fe9 100644 --- a/tools/editor/plugins/path_editor_plugin.cpp +++ b/tools/editor/plugins/path_editor_plugin.cpp @@ -1,597 +1,597 @@ -/*************************************************************************/
-/* path_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "path_editor_plugin.h"
-#include "spatial_editor_plugin.h"
-#include "scene/resources/curve.h"
-#include "os/keyboard.h"
-
-String PathSpatialGizmo::get_handle_name(int p_idx) const {
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return "";
-
- if (p_idx<c->get_point_count()) {
-
- return "Curve Point #"+itos(p_idx);
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
- String n = "Curve Point #"+itos(idx);
- if (t==0)
- n+=" In";
- else
- n+=" Out";
-
- return n;
-
-
-}
-Variant PathSpatialGizmo::get_handle_value(int p_idx) const{
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return Variant();
-
- if (p_idx<c->get_point_count()) {
-
- original=c->get_point_pos(p_idx);
- return original;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 ofs;
- if (t==0)
- ofs=c->get_point_in(idx);
- else
- ofs= c->get_point_out(idx);
-
- original=ofs+c->get_point_pos(idx);
-
- return ofs;
-
-}
-void PathSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- Transform gt = path->get_global_transform();
- Transform gi = gt.affine_inverse();
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- if (p_idx<c->get_point_count()) {
-
- Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2));
-
- Vector3 inters;
-
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- Vector3 local = gi.xform(inters);
- c->set_point_pos(p_idx,local);
- }
-
- return;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 base = c->get_point_pos(idx);
-
- Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2));
-
- Vector3 inters;
-
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- Vector3 local = gi.xform(inters)-base;
- if (t==0) {
- c->set_point_in(idx,local);
- } else {
- c->set_point_out(idx,local);
- }
- }
-
-}
-
-void PathSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
-
- if (p_idx<c->get_point_count()) {
-
- if (p_cancel) {
-
- c->set_point_pos(p_idx,p_restore);
- return;
- }
- ur->create_action("Set Curve Point Pos");
- ur->add_do_method(c.ptr(),"set_point_pos",p_idx,c->get_point_pos(p_idx));
- ur->add_undo_method(c.ptr(),"set_point_pos",p_idx,p_restore);
- ur->commit_action();
-
- return;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 ofs;
-
- if (p_cancel) {
-
-
-
- return;
- }
-
-
-
- if (t==0) {
-
- if (p_cancel) {
-
- c->set_point_in(p_idx,p_restore);
- return;
- }
- ur->create_action("Set Curve In Pos");
- ur->add_do_method(c.ptr(),"set_point_in",idx,c->get_point_in(idx));
- ur->add_undo_method(c.ptr(),"set_point_in",idx,p_restore);
- ur->commit_action();
-
-
- } else {
- if (p_cancel) {
-
- c->set_point_out(idx,p_restore);
- return;
- }
- ur->create_action("Set Curve Out Pos");
- ur->add_do_method(c.ptr(),"set_point_out",idx,c->get_point_out(idx));
- ur->add_undo_method(c.ptr(),"set_point_out",idx,p_restore);
- ur->commit_action();
-
- }
-
-}
-
-
-void PathSpatialGizmo::redraw(){
-
- clear();
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- Vector3Array v3a=c->tesselate();
- //Vector3Array v3a=c->get_baked_points();
-
- int v3s = v3a.size();
- if (v3s==0)
- return;
- Vector<Vector3> v3p;
- Vector3Array::Read r = v3a.read();
-
- for(int i=0;i<v3s-1;i++) {
-
- v3p.push_back(r[i]);
- v3p.push_back(r[i+1]);
- //v3p.push_back(r[i]);
- //v3p.push_back(r[i]+Vector3(0,0.2,0));
- }
-
- add_lines(v3p,PathEditorPlugin::singleton->path_material);
- add_collision_segments(v3p);
-
- if (PathEditorPlugin::singleton->get_edited_path()==path) {
- v3p.clear();
- Vector<Vector3> handles;
- Vector<Vector3> sec_handles;
-
- for(int i=0;i<c->get_point_count();i++) {
-
- Vector3 p = c->get_point_pos(i);
- handles.push_back(p);
- if (i>0) {
- v3p.push_back(p);
- v3p.push_back(p+c->get_point_in(i));
- sec_handles.push_back(p+c->get_point_in(i));
- }
-
- if (i<c->get_point_count()-1) {
- v3p.push_back(p);
- v3p.push_back(p+c->get_point_out(i));
- sec_handles.push_back(p+c->get_point_out(i));
- }
- }
-
- add_lines(v3p,PathEditorPlugin::singleton->path_thin_material);
- add_handles(handles);
- add_handles(sec_handles,false,true);
- }
-
-}
-
-PathSpatialGizmo::PathSpatialGizmo(Path* p_path){
-
- path=p_path;
- set_spatial_node(p_path);
-
-
-
-}
-
-bool PathEditorPlugin::create_spatial_gizmo(Spatial* p_spatial) {
-
- if (p_spatial->cast_to<Path>()) {
-
-
- Ref<PathSpatialGizmo> psg = memnew( PathSpatialGizmo(p_spatial->cast_to<Path>()));
- p_spatial->set_gizmo(psg);
- return true;
- }
-
- return false;
-}
-
-bool PathEditorPlugin::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) {
-
- if (!path)
- return false;
- Ref<Curve3D> c=path->get_curve();
- if (c.is_null())
- return false;
- Transform gt = path->get_global_transform();
- Transform it = gt.affine_inverse();
-
- static const int click_dist = 10; //should make global
-
-
- if (p_event.type==InputEvent::MOUSE_BUTTON) {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
- Point2 mbpos(mb.x,mb.y);
-
- if (mb.pressed && mb.button_index==BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb.mod.control))) {
- //click into curve, break it down
- Vector3Array v3a = c->tesselate();
- int idx=0;
- int rc=v3a.size();
- int closest_seg=-1;
- Vector3 closest_seg_point;
- float closest_d=1e20;
-
- if (rc>=2) {
- Vector3Array::Read r = v3a.read();
-
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(0))).distance_to(mbpos)<click_dist)
- return false; //nope, existing
-
-
- for(int i=0;i<c->get_point_count()-1;i++) {
- //find the offset and point index of the place to break up
- int j=idx;
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(i+1))).distance_to(mbpos)<click_dist)
- return false; //nope, existing
-
-
- while(j<rc && c->get_point_pos(i+1)!=r[j]) {
-
- Vector3 from =r[j];
- Vector3 to =r[j+1];
- real_t cdist = from.distance_to(to);
- from=gt.xform(from);
- to=gt.xform(to);
- if (cdist>0) {
- Vector2 s[2];
- s[0] = p_camera->unproject_position(from);
- s[1] = p_camera->unproject_position(to);
- Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos,s);
- float d = inters.distance_to(mbpos);
-
- if (d<10 && d<closest_d) {
-
-
- closest_d=d;
- closest_seg=i;
- Vector3 ray_from=p_camera->project_ray_origin(mbpos);
- Vector3 ray_dir=p_camera->project_ray_normal(mbpos);
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(ray_from,ray_from+ray_dir*4096,from,to,ra,rb);
-
- closest_seg_point=it.xform(rb);
- }
-
- }
- j++;
-
- }
- if (idx==j)
- idx++; //force next
- else
- idx=j; //swap
-
-
- if (j==rc)
- break;
- }
- }
-
- UndoRedo *ur = editor->get_undo_redo();
- if (closest_seg!=-1) {
- //subdivide
-
- ur->create_action("Split Path");
- ur->add_do_method(c.ptr(),"add_point",closest_seg_point,Vector3(),Vector3(),closest_seg+1);
- ur->add_undo_method(c.ptr(),"remove_point",closest_seg+1);
- ur->commit_action();;
- return true;
-
- } else {
-
- Vector3 org;
- if (c->get_point_count()==0)
- org=path->get_transform().get_origin();
- else
- org=gt.xform(c->get_point_pos(c->get_point_count()));
- Plane p(org,p_camera->get_transform().basis.get_axis(2));
- Vector3 ray_from=p_camera->project_ray_origin(mbpos);
- Vector3 ray_dir=p_camera->project_ray_normal(mbpos);
-
- Vector3 inters;
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- ur->create_action("Add Point to Curve");
- ur->add_do_method(c.ptr(),"add_point",it.xform(inters),Vector3(),Vector3(),-1);
- ur->add_undo_method(c.ptr(),"remove_point",c->get_point_count());
- ur->commit_action();;
- return true;
- }
-
- //add new at pos
- }
-
- } else if (mb.pressed && ((mb.button_index==BUTTON_LEFT && curve_del->is_pressed()) || (mb.button_index==BUTTON_RIGHT && curve_edit->is_pressed()))) {
-
- int erase_idx=-1;
- for(int i=0;i<c->get_point_count();i++) {
- //find the offset and point index of the place to break up
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos)<click_dist) {
-
- erase_idx=i;
- break;
- }
- }
-
- if (erase_idx!=-1) {
-
- UndoRedo *ur = editor->get_undo_redo();
- ur->create_action("Remove Path Point");
- ur->add_do_method(c.ptr(),"remove_point",erase_idx);
- ur->add_undo_method(c.ptr(),"add_point",c->get_point_pos(erase_idx),c->get_point_in(erase_idx),c->get_point_out(erase_idx),erase_idx);
- ur->commit_action();
- return true;
- }
- }
-
- }
-
- return false;
-}
-
-
-void PathEditorPlugin::edit(Object *p_object) {
-
- if (p_object) {
- path=p_object->cast_to<Path>();
- if (path) {
-
- if (path->get_curve().is_valid()) {
- path->get_curve()->emit_signal("changed");
- }
- }
- } else {
- Path *pre=path;
- path=NULL;
- if (pre) {
- pre->get_curve()->emit_signal("changed");
- }
- }
-// collision_polygon_editor->edit(p_object->cast_to<Node>());
-}
-
-bool PathEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_type("Path");
-}
-
-void PathEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
- curve_create->show();
- curve_edit->show();
- curve_del->show();
- curve_close->show();
- sep->show();
- } else {
-
- curve_create->hide();
- curve_edit->hide();
- curve_del->hide();
- curve_close->hide();
- sep->hide();
-
- {
- Path *pre=path;
- path=NULL;
- if (pre && pre->get_curve().is_valid()) {
- pre->get_curve()->emit_signal("changed");
- }
- }
- }
-
-}
-
-void PathEditorPlugin::_mode_changed(int p_idx) {
-
- curve_create->set_pressed(p_idx==0);
- curve_edit->set_pressed(p_idx==1);
- curve_del->set_pressed(p_idx==2);
-}
-
-void PathEditorPlugin::_close_curve() {
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return ;
- if (c->get_point_count()<2)
- return;
- c->add_point(c->get_point_pos(0),c->get_point_in(0),c->get_point_out(0));
-
-}
-
-void PathEditorPlugin::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- curve_create->connect("pressed",this,"_mode_changed",make_binds(0));
- curve_edit->connect("pressed",this,"_mode_changed",make_binds(1));
- curve_del->connect("pressed",this,"_mode_changed",make_binds(2));
- curve_close->connect("pressed",this,"_close_curve");
- }
-}
-
-void PathEditorPlugin::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("_mode_changed"),&PathEditorPlugin::_mode_changed);
- ObjectTypeDB::bind_method(_MD("_close_curve"),&PathEditorPlugin::_close_curve);
-}
-
-PathEditorPlugin* PathEditorPlugin::singleton=NULL;
-
-
-PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) {
-
- path=NULL;
- editor=p_node;
- singleton=this;
-
- path_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
- path_material->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.8) );
- path_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- path_material->set_line_width(3);
- path_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- path_material->set_flag(Material::FLAG_UNSHADED,true);
-
- path_thin_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
- path_thin_material->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.4) );
- path_thin_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- path_thin_material->set_line_width(1);
- path_thin_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- path_thin_material->set_flag(Material::FLAG_UNSHADED,true);
-
- SpatialEditor::get_singleton()->add_gizmo_plugin(this);
-
- sep = memnew( VSeparator);
- sep->hide();
- SpatialEditor::get_singleton()->add_control_to_menu_panel(sep);
- curve_edit = memnew( ToolButton );
- curve_edit->set_icon(SpatialEditor::get_singleton()->get_icon("CurveEdit","EditorIcons"));
- curve_edit->set_toggle_mode(true);
- curve_edit->hide();
- curve_edit->set_focus_mode(Control::FOCUS_NONE);
- curve_edit->set_tooltip("Select Points\nShift+Drag: Select Control Points\n"+keycode_get_string(KEY_MASK_CMD)+"Click: Add Point\nRight Click: Delete Point.");
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_edit);
- curve_create = memnew( ToolButton );
- curve_create->set_icon(SpatialEditor::get_singleton()->get_icon("CurveCreate","EditorIcons"));
- curve_create->set_toggle_mode(true);
- curve_create->hide();
- curve_create->set_focus_mode(Control::FOCUS_NONE);
- curve_create->set_tooltip("Add Point (in empty space)\nSplit Segment (in curve).");
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_create);
- curve_del = memnew( ToolButton );
- curve_del->set_icon(SpatialEditor::get_singleton()->get_icon("CurveDelete","EditorIcons"));
- curve_del->set_toggle_mode(true);
- curve_del->hide();
- curve_del->set_focus_mode(Control::FOCUS_NONE);
- curve_del->set_tooltip("Delete Point.");
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_del);
- curve_close = memnew( ToolButton );
- curve_close->set_icon(SpatialEditor::get_singleton()->get_icon("CurveClose","EditorIcons"));
- curve_close->hide();
- curve_close->set_focus_mode(Control::FOCUS_NONE);
- curve_close->set_tooltip("Close Curve");
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close);
-
-
-
- curve_edit->set_pressed(true);
- /*
- collision_polygon_editor = memnew( PathEditor(p_node) );
- editor->get_viewport()->add_child(collision_polygon_editor);
-
- collision_polygon_editor->set_margin(MARGIN_LEFT,200);
- collision_polygon_editor->set_margin(MARGIN_RIGHT,230);
- collision_polygon_editor->set_margin(MARGIN_TOP,0);
- collision_polygon_editor->set_margin(MARGIN_BOTTOM,10);
-
-
- collision_polygon_editor->hide();
- */
-
-
-}
-
-
-PathEditorPlugin::~PathEditorPlugin()
-{
-}
-
+/*************************************************************************/ +/* path_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "path_editor_plugin.h" +#include "spatial_editor_plugin.h" +#include "scene/resources/curve.h" +#include "os/keyboard.h" + +String PathSpatialGizmo::get_handle_name(int p_idx) const { + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return ""; + + if (p_idx<c->get_point_count()) { + + return "Curve Point #"+itos(p_idx); + } + + p_idx=p_idx-c->get_point_count()+1; + + int idx=p_idx/2; + int t=p_idx%2; + String n = "Curve Point #"+itos(idx); + if (t==0) + n+=" In"; + else + n+=" Out"; + + return n; + + +} +Variant PathSpatialGizmo::get_handle_value(int p_idx) const{ + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return Variant(); + + if (p_idx<c->get_point_count()) { + + original=c->get_point_pos(p_idx); + return original; + } + + p_idx=p_idx-c->get_point_count()+1; + + int idx=p_idx/2; + int t=p_idx%2; + + Vector3 ofs; + if (t==0) + ofs=c->get_point_in(idx); + else + ofs= c->get_point_out(idx); + + original=ofs+c->get_point_pos(idx); + + return ofs; + +} +void PathSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){ + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return; + + Transform gt = path->get_global_transform(); + Transform gi = gt.affine_inverse(); + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + if (p_idx<c->get_point_count()) { + + Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2)); + + Vector3 inters; + + if (p.intersects_ray(ray_from,ray_dir,&inters)) { + + Vector3 local = gi.xform(inters); + c->set_point_pos(p_idx,local); + } + + return; + } + + p_idx=p_idx-c->get_point_count()+1; + + int idx=p_idx/2; + int t=p_idx%2; + + Vector3 base = c->get_point_pos(idx); + + Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2)); + + Vector3 inters; + + if (p.intersects_ray(ray_from,ray_dir,&inters)) { + + Vector3 local = gi.xform(inters)-base; + if (t==0) { + c->set_point_in(idx,local); + } else { + c->set_point_out(idx,local); + } + } + +} + +void PathSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){ + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return; + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + + if (p_idx<c->get_point_count()) { + + if (p_cancel) { + + c->set_point_pos(p_idx,p_restore); + return; + } + ur->create_action("Set Curve Point Pos"); + ur->add_do_method(c.ptr(),"set_point_pos",p_idx,c->get_point_pos(p_idx)); + ur->add_undo_method(c.ptr(),"set_point_pos",p_idx,p_restore); + ur->commit_action(); + + return; + } + + p_idx=p_idx-c->get_point_count()+1; + + int idx=p_idx/2; + int t=p_idx%2; + + Vector3 ofs; + + if (p_cancel) { + + + + return; + } + + + + if (t==0) { + + if (p_cancel) { + + c->set_point_in(p_idx,p_restore); + return; + } + ur->create_action("Set Curve In Pos"); + ur->add_do_method(c.ptr(),"set_point_in",idx,c->get_point_in(idx)); + ur->add_undo_method(c.ptr(),"set_point_in",idx,p_restore); + ur->commit_action(); + + + } else { + if (p_cancel) { + + c->set_point_out(idx,p_restore); + return; + } + ur->create_action("Set Curve Out Pos"); + ur->add_do_method(c.ptr(),"set_point_out",idx,c->get_point_out(idx)); + ur->add_undo_method(c.ptr(),"set_point_out",idx,p_restore); + ur->commit_action(); + + } + +} + + +void PathSpatialGizmo::redraw(){ + + clear(); + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return; + + Vector3Array v3a=c->tesselate(); + //Vector3Array v3a=c->get_baked_points(); + + int v3s = v3a.size(); + if (v3s==0) + return; + Vector<Vector3> v3p; + Vector3Array::Read r = v3a.read(); + + for(int i=0;i<v3s-1;i++) { + + v3p.push_back(r[i]); + v3p.push_back(r[i+1]); + //v3p.push_back(r[i]); + //v3p.push_back(r[i]+Vector3(0,0.2,0)); + } + + add_lines(v3p,PathEditorPlugin::singleton->path_material); + add_collision_segments(v3p); + + if (PathEditorPlugin::singleton->get_edited_path()==path) { + v3p.clear(); + Vector<Vector3> handles; + Vector<Vector3> sec_handles; + + for(int i=0;i<c->get_point_count();i++) { + + Vector3 p = c->get_point_pos(i); + handles.push_back(p); + if (i>0) { + v3p.push_back(p); + v3p.push_back(p+c->get_point_in(i)); + sec_handles.push_back(p+c->get_point_in(i)); + } + + if (i<c->get_point_count()-1) { + v3p.push_back(p); + v3p.push_back(p+c->get_point_out(i)); + sec_handles.push_back(p+c->get_point_out(i)); + } + } + + add_lines(v3p,PathEditorPlugin::singleton->path_thin_material); + add_handles(handles); + add_handles(sec_handles,false,true); + } + +} + +PathSpatialGizmo::PathSpatialGizmo(Path* p_path){ + + path=p_path; + set_spatial_node(p_path); + + + +} + +bool PathEditorPlugin::create_spatial_gizmo(Spatial* p_spatial) { + + if (p_spatial->cast_to<Path>()) { + + + Ref<PathSpatialGizmo> psg = memnew( PathSpatialGizmo(p_spatial->cast_to<Path>())); + p_spatial->set_gizmo(psg); + return true; + } + + return false; +} + +bool PathEditorPlugin::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) { + + if (!path) + return false; + Ref<Curve3D> c=path->get_curve(); + if (c.is_null()) + return false; + Transform gt = path->get_global_transform(); + Transform it = gt.affine_inverse(); + + static const int click_dist = 10; //should make global + + + if (p_event.type==InputEvent::MOUSE_BUTTON) { + + const InputEventMouseButton &mb=p_event.mouse_button; + Point2 mbpos(mb.x,mb.y); + + if (mb.pressed && mb.button_index==BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb.mod.control))) { + //click into curve, break it down + Vector3Array v3a = c->tesselate(); + int idx=0; + int rc=v3a.size(); + int closest_seg=-1; + Vector3 closest_seg_point; + float closest_d=1e20; + + if (rc>=2) { + Vector3Array::Read r = v3a.read(); + + if (p_camera->unproject_position(gt.xform(c->get_point_pos(0))).distance_to(mbpos)<click_dist) + return false; //nope, existing + + + for(int i=0;i<c->get_point_count()-1;i++) { + //find the offset and point index of the place to break up + int j=idx; + if (p_camera->unproject_position(gt.xform(c->get_point_pos(i+1))).distance_to(mbpos)<click_dist) + return false; //nope, existing + + + while(j<rc && c->get_point_pos(i+1)!=r[j]) { + + Vector3 from =r[j]; + Vector3 to =r[j+1]; + real_t cdist = from.distance_to(to); + from=gt.xform(from); + to=gt.xform(to); + if (cdist>0) { + Vector2 s[2]; + s[0] = p_camera->unproject_position(from); + s[1] = p_camera->unproject_position(to); + Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos,s); + float d = inters.distance_to(mbpos); + + if (d<10 && d<closest_d) { + + + closest_d=d; + closest_seg=i; + Vector3 ray_from=p_camera->project_ray_origin(mbpos); + Vector3 ray_dir=p_camera->project_ray_normal(mbpos); + + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(ray_from,ray_from+ray_dir*4096,from,to,ra,rb); + + closest_seg_point=it.xform(rb); + } + + } + j++; + + } + if (idx==j) + idx++; //force next + else + idx=j; //swap + + + if (j==rc) + break; + } + } + + UndoRedo *ur = editor->get_undo_redo(); + if (closest_seg!=-1) { + //subdivide + + ur->create_action("Split Path"); + ur->add_do_method(c.ptr(),"add_point",closest_seg_point,Vector3(),Vector3(),closest_seg+1); + ur->add_undo_method(c.ptr(),"remove_point",closest_seg+1); + ur->commit_action();; + return true; + + } else { + + Vector3 org; + if (c->get_point_count()==0) + org=path->get_transform().get_origin(); + else + org=gt.xform(c->get_point_pos(c->get_point_count())); + Plane p(org,p_camera->get_transform().basis.get_axis(2)); + Vector3 ray_from=p_camera->project_ray_origin(mbpos); + Vector3 ray_dir=p_camera->project_ray_normal(mbpos); + + Vector3 inters; + if (p.intersects_ray(ray_from,ray_dir,&inters)) { + + ur->create_action("Add Point to Curve"); + ur->add_do_method(c.ptr(),"add_point",it.xform(inters),Vector3(),Vector3(),-1); + ur->add_undo_method(c.ptr(),"remove_point",c->get_point_count()); + ur->commit_action();; + return true; + } + + //add new at pos + } + + } else if (mb.pressed && ((mb.button_index==BUTTON_LEFT && curve_del->is_pressed()) || (mb.button_index==BUTTON_RIGHT && curve_edit->is_pressed()))) { + + int erase_idx=-1; + for(int i=0;i<c->get_point_count();i++) { + //find the offset and point index of the place to break up + if (p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos)<click_dist) { + + erase_idx=i; + break; + } + } + + if (erase_idx!=-1) { + + UndoRedo *ur = editor->get_undo_redo(); + ur->create_action("Remove Path Point"); + ur->add_do_method(c.ptr(),"remove_point",erase_idx); + ur->add_undo_method(c.ptr(),"add_point",c->get_point_pos(erase_idx),c->get_point_in(erase_idx),c->get_point_out(erase_idx),erase_idx); + ur->commit_action(); + return true; + } + } + + } + + return false; +} + + +void PathEditorPlugin::edit(Object *p_object) { + + if (p_object) { + path=p_object->cast_to<Path>(); + if (path) { + + if (path->get_curve().is_valid()) { + path->get_curve()->emit_signal("changed"); + } + } + } else { + Path *pre=path; + path=NULL; + if (pre) { + pre->get_curve()->emit_signal("changed"); + } + } +// collision_polygon_editor->edit(p_object->cast_to<Node>()); +} + +bool PathEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("Path"); +} + +void PathEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + + curve_create->show(); + curve_edit->show(); + curve_del->show(); + curve_close->show(); + sep->show(); + } else { + + curve_create->hide(); + curve_edit->hide(); + curve_del->hide(); + curve_close->hide(); + sep->hide(); + + { + Path *pre=path; + path=NULL; + if (pre && pre->get_curve().is_valid()) { + pre->get_curve()->emit_signal("changed"); + } + } + } + +} + +void PathEditorPlugin::_mode_changed(int p_idx) { + + curve_create->set_pressed(p_idx==0); + curve_edit->set_pressed(p_idx==1); + curve_del->set_pressed(p_idx==2); +} + +void PathEditorPlugin::_close_curve() { + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return ; + if (c->get_point_count()<2) + return; + c->add_point(c->get_point_pos(0),c->get_point_in(0),c->get_point_out(0)); + +} + +void PathEditorPlugin::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_TREE) { + + curve_create->connect("pressed",this,"_mode_changed",make_binds(0)); + curve_edit->connect("pressed",this,"_mode_changed",make_binds(1)); + curve_del->connect("pressed",this,"_mode_changed",make_binds(2)); + curve_close->connect("pressed",this,"_close_curve"); + } +} + +void PathEditorPlugin::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_mode_changed"),&PathEditorPlugin::_mode_changed); + ObjectTypeDB::bind_method(_MD("_close_curve"),&PathEditorPlugin::_close_curve); +} + +PathEditorPlugin* PathEditorPlugin::singleton=NULL; + + +PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { + + path=NULL; + editor=p_node; + singleton=this; + + path_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + path_material->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.8) ); + path_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + path_material->set_line_width(3); + path_material->set_flag(Material::FLAG_DOUBLE_SIDED,true); + path_material->set_flag(Material::FLAG_UNSHADED,true); + + path_thin_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + path_thin_material->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.4) ); + path_thin_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + path_thin_material->set_line_width(1); + path_thin_material->set_flag(Material::FLAG_DOUBLE_SIDED,true); + path_thin_material->set_flag(Material::FLAG_UNSHADED,true); + + SpatialEditor::get_singleton()->add_gizmo_plugin(this); + + sep = memnew( VSeparator); + sep->hide(); + SpatialEditor::get_singleton()->add_control_to_menu_panel(sep); + curve_edit = memnew( ToolButton ); + curve_edit->set_icon(SpatialEditor::get_singleton()->get_icon("CurveEdit","EditorIcons")); + curve_edit->set_toggle_mode(true); + curve_edit->hide(); + curve_edit->set_focus_mode(Control::FOCUS_NONE); + curve_edit->set_tooltip("Select Points\nShift+Drag: Select Control Points\n"+keycode_get_string(KEY_MASK_CMD)+"Click: Add Point\nRight Click: Delete Point."); + SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_edit); + curve_create = memnew( ToolButton ); + curve_create->set_icon(SpatialEditor::get_singleton()->get_icon("CurveCreate","EditorIcons")); + curve_create->set_toggle_mode(true); + curve_create->hide(); + curve_create->set_focus_mode(Control::FOCUS_NONE); + curve_create->set_tooltip("Add Point (in empty space)\nSplit Segment (in curve)."); + SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_create); + curve_del = memnew( ToolButton ); + curve_del->set_icon(SpatialEditor::get_singleton()->get_icon("CurveDelete","EditorIcons")); + curve_del->set_toggle_mode(true); + curve_del->hide(); + curve_del->set_focus_mode(Control::FOCUS_NONE); + curve_del->set_tooltip("Delete Point."); + SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_del); + curve_close = memnew( ToolButton ); + curve_close->set_icon(SpatialEditor::get_singleton()->get_icon("CurveClose","EditorIcons")); + curve_close->hide(); + curve_close->set_focus_mode(Control::FOCUS_NONE); + curve_close->set_tooltip("Close Curve"); + SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close); + + + + curve_edit->set_pressed(true); + /* + collision_polygon_editor = memnew( PathEditor(p_node) ); + editor->get_viewport()->add_child(collision_polygon_editor); + + collision_polygon_editor->set_margin(MARGIN_LEFT,200); + collision_polygon_editor->set_margin(MARGIN_RIGHT,230); + collision_polygon_editor->set_margin(MARGIN_TOP,0); + collision_polygon_editor->set_margin(MARGIN_BOTTOM,10); + + + collision_polygon_editor->hide(); + */ + + +} + + +PathEditorPlugin::~PathEditorPlugin() +{ +} + diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.cpp b/tools/editor/plugins/polygon_2d_editor_plugin.cpp index d25880fdff..3029dcf2ab 100644 --- a/tools/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/polygon_2d_editor_plugin.cpp @@ -50,6 +50,9 @@ void Polygon2DEditor::_notification(int p_what) { uv_button[UV_MODE_ROTATE]->set_icon(get_icon("ToolRotate","EditorIcons")); uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale","EditorIcons")); + b_snap_grid->set_icon( get_icon("Grid", "EditorIcons")); + b_snap_enable->set_icon( get_icon("Snap", "EditorIcons")); + uv_icon_zoom->set_texture( get_icon("Zoom", "EditorIcons")); } break; case NOTIFICATION_FIXED_PROCESS: { @@ -158,6 +161,41 @@ void Polygon2DEditor::_menu_option(int p_option) { } } +void Polygon2DEditor::_set_use_snap(bool p_use) +{ + use_snap=p_use; +} + +void Polygon2DEditor::_set_show_grid(bool p_show) +{ + snap_show_grid=p_show; + uv_edit_draw->update(); +} + +void Polygon2DEditor::_set_snap_off_x(float p_val) +{ + snap_offset.x=p_val; + uv_edit_draw->update(); +} + +void Polygon2DEditor::_set_snap_off_y(float p_val) +{ + snap_offset.y=p_val; + uv_edit_draw->update(); +} + +void Polygon2DEditor::_set_snap_step_x(float p_val) +{ + snap_step.x=p_val; + uv_edit_draw->update(); +} + +void Polygon2DEditor::_set_snap_step_y(float p_val) +{ + snap_step.y=p_val; + uv_edit_draw->update(); +} + void Polygon2DEditor::_wip_close() { undo_redo->create_action("Create Poly"); @@ -494,7 +532,7 @@ void Polygon2DEditor::_uv_input(const InputEvent& p_input) { Vector2 tuv=mtx.xform(uv_prev[i]); if (tuv.distance_to(Vector2(mb.x,mb.y))<8) { - + uv_drag_from=tuv; uv_drag_index=i; } } @@ -545,7 +583,7 @@ void Polygon2DEditor::_uv_input(const InputEvent& p_input) { } else if (uv_drag) { - Vector2 uv_drag_to(mm.x,mm.y); + Vector2 uv_drag_to=snap_point(Vector2(mm.x,mm.y)); Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from); @@ -649,6 +687,33 @@ void Polygon2DEditor::_uv_draw() { uv_edit_draw->draw_texture(base_tex,Point2()); VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(),Matrix32()); + if (snap_show_grid) { + Size2 s = uv_edit_draw->get_size(); + int last_cell; + + if (snap_step.x!=0) { + for(int i=0;i<s.width;i++) { + int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + uv_edit_draw->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3)); + last_cell=cell; + } + } + + if (snap_step.y!=0) { + for(int i=0;i<s.height;i++) { + int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + uv_edit_draw->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3)); + last_cell=cell; + } + } + } + DVector<Vector2> uvs = node->get_uv(); Ref<Texture> handle = get_icon("EditorHandle","EditorIcons"); @@ -720,8 +785,27 @@ void Polygon2DEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_uv_input"),&Polygon2DEditor::_uv_input); ObjectTypeDB::bind_method(_MD("_uv_scroll_changed"),&Polygon2DEditor::_uv_scroll_changed); ObjectTypeDB::bind_method(_MD("_node_removed"),&Polygon2DEditor::_node_removed); + ObjectTypeDB::bind_method(_MD("_set_use_snap"),&Polygon2DEditor::_set_use_snap); + ObjectTypeDB::bind_method(_MD("_set_show_grid"),&Polygon2DEditor::_set_show_grid); + ObjectTypeDB::bind_method(_MD("_set_snap_off_x"),&Polygon2DEditor::_set_snap_off_x); + ObjectTypeDB::bind_method(_MD("_set_snap_off_y"),&Polygon2DEditor::_set_snap_off_y); + ObjectTypeDB::bind_method(_MD("_set_snap_step_x"),&Polygon2DEditor::_set_snap_step_x); + ObjectTypeDB::bind_method(_MD("_set_snap_step_y"),&Polygon2DEditor::_set_snap_step_y); + +} +inline float _snap_scalar(float p_offset, float p_step, float p_target) { + return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target; +} + +Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const { + if (use_snap) { + p_target.x = _snap_scalar(snap_offset.x*uv_draw_zoom-uv_draw_ofs.x, snap_step.x*uv_draw_zoom, p_target.x); + p_target.y = _snap_scalar(snap_offset.y*uv_draw_zoom-uv_draw_ofs.y, snap_step.y*uv_draw_zoom, p_target.y); + } + + return p_target; } Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { @@ -731,6 +815,10 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { editor=p_editor; undo_redo = editor->get_undo_redo(); + snap_step=Vector2(10,10); + use_snap=false; + snap_show_grid=false; + add_child( memnew( VSeparator )); button_create = memnew( ToolButton ); add_child(button_create); @@ -800,9 +888,72 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { uv_menu->get_popup()->add_separator(); uv_menu->get_popup()->add_item("Clear UV",UVEDIT_UV_CLEAR); uv_menu->get_popup()->connect("item_pressed",this,"_menu_option"); + + uv_mode_hb->add_child( memnew( VSeparator )); + + b_snap_enable = memnew( ToolButton ); + uv_mode_hb->add_child(b_snap_enable); + b_snap_enable->set_text("Snap"); + b_snap_enable->set_focus_mode(FOCUS_NONE); + b_snap_enable->set_toggle_mode(true); + b_snap_enable->set_pressed(use_snap); + b_snap_enable->set_tooltip("Enable Snap"); + b_snap_enable->connect("toggled",this,"_set_use_snap"); + + b_snap_grid = memnew( ToolButton ); + uv_mode_hb->add_child(b_snap_grid); + b_snap_grid->set_text("Grid"); + b_snap_grid->set_focus_mode(FOCUS_NONE); + b_snap_grid->set_toggle_mode(true); + b_snap_grid->set_pressed(snap_show_grid); + b_snap_grid->set_tooltip("Show Grid"); + b_snap_grid->connect("toggled",this,"_set_show_grid"); + + uv_mode_hb->add_child( memnew( VSeparator )); + uv_mode_hb->add_child( memnew( Label("Grid Offset:") ) ); + + SpinBox *sb_off_x = memnew( SpinBox ); + sb_off_x->set_min(-256); + sb_off_x->set_max(256); + sb_off_x->set_step(1); + sb_off_x->set_val(snap_offset.x); + sb_off_x->set_suffix("px"); + sb_off_x->connect("value_changed", this, "_set_snap_off_x"); + uv_mode_hb->add_child(sb_off_x); + + SpinBox *sb_off_y = memnew( SpinBox ); + sb_off_y->set_min(-256); + sb_off_y->set_max(256); + sb_off_y->set_step(1); + sb_off_y->set_val(snap_offset.y); + sb_off_y->set_suffix("px"); + sb_off_y->connect("value_changed", this, "_set_snap_off_y"); + uv_mode_hb->add_child(sb_off_y); + + uv_mode_hb->add_child( memnew( VSeparator )); + uv_mode_hb->add_child( memnew( Label("Grid Step:") ) ); + + SpinBox *sb_step_x = memnew( SpinBox ); + sb_step_x->set_min(-256); + sb_step_x->set_max(256); + sb_step_x->set_step(1); + sb_step_x->set_val(snap_step.x); + sb_step_x->set_suffix("px"); + sb_step_x->connect("value_changed", this, "_set_snap_step_x"); + uv_mode_hb->add_child(sb_step_x); + + SpinBox *sb_step_y = memnew( SpinBox ); + sb_step_y->set_min(-256); + sb_step_y->set_max(256); + sb_step_y->set_step(1); + sb_step_y->set_val(snap_step.y); + sb_step_y->set_suffix("px"); + sb_step_y->connect("value_changed", this, "_set_snap_step_y"); + uv_mode_hb->add_child(sb_step_y); + uv_mode_hb->add_child( memnew( VSeparator )); uv_icon_zoom = memnew( TextureFrame ); - uv_main_hb->add_child( uv_icon_zoom ); + uv_mode_hb->add_child( uv_icon_zoom ); uv_zoom = memnew( HSlider ); uv_zoom->set_min(0.01); uv_zoom->set_max(4); diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.h b/tools/editor/plugins/polygon_2d_editor_plugin.h index 8f807cb7e8..0939c44264 100644 --- a/tools/editor/plugins/polygon_2d_editor_plugin.h +++ b/tools/editor/plugins/polygon_2d_editor_plugin.h @@ -41,6 +41,8 @@ class Polygon2DEditor : public HBoxContainer { UVMode uv_mode; AcceptDialog *uv_edit; ToolButton *uv_button[4]; + ToolButton *b_snap_enable; + ToolButton *b_snap_grid; Control *uv_edit_draw; HSlider *uv_zoom; SpinBox *uv_zoom_value; @@ -78,6 +80,11 @@ class Polygon2DEditor : public HBoxContainer { Vector<Vector2> wip; bool wip_active; + bool use_snap; + bool snap_show_grid; + Vector2 snap_offset; + Vector2 snap_step; + void _uv_scroll_changed(float); void _uv_input(const InputEvent& p_input); void _uv_draw(); @@ -86,10 +93,20 @@ class Polygon2DEditor : public HBoxContainer { void _canvas_draw(); void _menu_option(int p_option); + void _set_use_snap(bool p_use); + void _set_show_grid(bool p_show); + void _set_snap_off_x(float p_val); + void _set_snap_off_y(float p_val); + void _set_snap_step_x(float p_val); + void _set_snap_step_y(float p_val); + protected: void _notification(int p_what); void _node_removed(Node *p_node); static void _bind_methods(); + + Vector2 snap_point(Vector2 p_target) const; + public: bool forward_input_event(const InputEvent& p_event); diff --git a/tools/editor/plugins/sprite_region_editor_plugin.cpp b/tools/editor/plugins/sprite_region_editor_plugin.cpp new file mode 100644 index 0000000000..35c53cf562 --- /dev/null +++ b/tools/editor/plugins/sprite_region_editor_plugin.cpp @@ -0,0 +1,565 @@ +/*************************************************************************/ +/* sprite_region_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Author: Mariano Suligoy */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "sprite_region_editor_plugin.h" +#include "scene/gui/check_box.h" +#include "os/input.h" +#include "os/keyboard.h" + +void SpriteRegionEditor::_region_draw() +{ + Ref<Texture> base_tex = node->get_texture(); + if (base_tex.is_null()) + return; + + Matrix32 mtx; + mtx.elements[2]=-draw_ofs; + mtx.scale_basis(Vector2(draw_zoom,draw_zoom)); + + VS::get_singleton()->canvas_item_set_clip(edit_draw->get_canvas_item(),true); + VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(),mtx); + edit_draw->draw_texture(base_tex,Point2()); + VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(),Matrix32()); + + if (snap_show_grid) { + Size2 s = edit_draw->get_size(); + int last_cell; + + if (snap_step.x!=0) { + for(int i=0;i<s.width;i++) { + int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + edit_draw->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3)); + last_cell=cell; + } + } + + if (snap_step.y!=0) { + for(int i=0;i<s.height;i++) { + int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + edit_draw->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3)); + last_cell=cell; + } + } + } + + Ref<Texture> select_handle = get_icon("EditorHandle","EditorIcons"); + + Rect2 scroll_rect(Point2(),mtx.basis_xform(base_tex->get_size())); + scroll_rect.expand_to(mtx.basis_xform(edit_draw->get_size())); + + Vector2 endpoints[4]={ + mtx.basis_xform(rect.pos), + mtx.basis_xform(rect.pos+Vector2(rect.size.x,0)), + mtx.basis_xform(rect.pos+rect.size), + mtx.basis_xform(rect.pos+Vector2(0,rect.size.y)) + }; + + for(int i=0;i<4;i++) { + + int prev = (i+3)%4; + int next = (i+1)%4; + + Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized(); + ofs*=1.4144*(select_handle->get_size().width/2); + + edit_draw->draw_line(endpoints[i]-draw_ofs, endpoints[next]-draw_ofs, Color(0.9,0.5,0.5), 2); + + edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs); + + ofs = (endpoints[next]-endpoints[i])/2; + ofs += (endpoints[next]-endpoints[i]).tangent().normalized()*(select_handle->get_size().width/2); + + edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs); + + scroll_rect.expand_to(endpoints[i]); + } + + scroll_rect=scroll_rect.grow(200); + updating_scroll=true; + hscroll->set_min(scroll_rect.pos.x); + hscroll->set_max(scroll_rect.pos.x+scroll_rect.size.x); + hscroll->set_page(edit_draw->get_size().x); + hscroll->set_val(draw_ofs.x); + hscroll->set_step(0.001); + + vscroll->set_min(scroll_rect.pos.y); + vscroll->set_max(scroll_rect.pos.y+scroll_rect.size.y); + vscroll->set_page(edit_draw->get_size().y); + vscroll->set_val(draw_ofs.y); + vscroll->set_step(0.001); + updating_scroll=false; +} + +void SpriteRegionEditor::_region_input(const InputEvent& p_input) +{ + Matrix32 mtx; + mtx.elements[2]=-draw_ofs; + mtx.scale_basis(Vector2(draw_zoom,draw_zoom)); + + Vector2 endpoints[8]={ + mtx.xform(rect.pos)+Vector2(-4,-4), + mtx.xform(rect.pos+Vector2(rect.size.x/2,0))+Vector2(0,-4), + mtx.xform(rect.pos+Vector2(rect.size.x,0))+Vector2(4,-4), + mtx.xform(rect.pos+Vector2(rect.size.x,rect.size.y/2))+Vector2(4,0), + mtx.xform(rect.pos+rect.size)+Vector2(4,4), + mtx.xform(rect.pos+Vector2(rect.size.x/2,rect.size.y))+Vector2(0,4), + mtx.xform(rect.pos+Vector2(0,rect.size.y))+Vector2(-4,4), + mtx.xform(rect.pos+Vector2(0,rect.size.y/2))+Vector2(-4,0) + }; + + if (p_input.type==InputEvent::MOUSE_BUTTON) { + + + const InputEventMouseButton &mb=p_input.mouse_button; + + if (mb.button_index==BUTTON_LEFT) { + + + if (mb.pressed) { + + drag_from=mtx.affine_inverse().xform(Vector2(mb.x,mb.y)); + drag_from=snap_point(drag_from); + drag=true; + rect_prev=node->get_region_rect(); + + drag_index=-1; + for(int i=0;i<8;i++) { + + Vector2 tuv=endpoints[i]; + if (tuv.distance_to(Vector2(mb.x,mb.y))<8) { + drag_index=i; + creating = false; + } + } + + if (drag_index==-1) { + creating = true; + rect = Rect2(drag_from,Size2()); + } + + } else if (drag) { + + undo_redo->create_action("Set region_rect"); + undo_redo->add_do_method(node,"set_region_rect",node->get_region_rect()); + undo_redo->add_undo_method(node,"set_region_rect",rect_prev); + undo_redo->add_do_method(edit_draw,"update"); + undo_redo->add_undo_method(edit_draw,"update"); + undo_redo->commit_action(); + + drag=false; + } + + } else if (mb.button_index==BUTTON_RIGHT && mb.pressed) { + + if (drag) { + drag=false; + node->set_region_rect(rect_prev); + rect=rect_prev; + edit_draw->update(); + } + + } else if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed) { + + zoom->set_val( zoom->get_val()/0.9 ); + } else if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed) { + + zoom->set_val( zoom->get_val()*0.9); + } + + } else if (p_input.type==InputEvent::MOUSE_MOTION) { + + const InputEventMouseMotion &mm=p_input.mouse_motion; + + if (mm.button_mask&BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + + Vector2 draged(mm.relative_x,mm.relative_y); + hscroll->set_val( hscroll->get_val()-draged.x ); + vscroll->set_val( vscroll->get_val()-draged.y ); + + } else if (drag) { + + Vector2 new_pos = mtx.affine_inverse().xform(Vector2(mm.x,mm.y)); + new_pos = snap_point(new_pos); + + if (creating) { + rect = Rect2(drag_from,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + edit_draw->update(); + return; + } + + switch(drag_index) { + case 0: { + Vector2 p=rect_prev.pos+rect_prev.size; + rect = Rect2(p,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 1: { + Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y); + rect = Rect2(p,Size2(rect_prev.size.x,0)); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 2: { + Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y); + rect = Rect2(p,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 3: { + Vector2 p=rect_prev.pos; + rect = Rect2(p,Size2(0,rect_prev.size.y)); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 4: { + Vector2 p=rect_prev.pos; + rect = Rect2(p,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 5: { + Vector2 p=rect_prev.pos; + rect = Rect2(p,Size2(rect_prev.size.x,0)); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 6: { + Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0); + rect = Rect2(p,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 7: { + Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0); + rect = Rect2(p,Size2(0,rect_prev.size.y)); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + + } + edit_draw->update(); + } + + } +} + +void SpriteRegionEditor::_scroll_changed(float) +{ + if (updating_scroll) + return; + + draw_ofs.x=hscroll->get_val(); + draw_ofs.y=vscroll->get_val(); + draw_zoom=zoom->get_val(); + print_line("_scroll_changed"); + edit_draw->update(); +} + +void SpriteRegionEditor::_set_use_snap(bool p_use) +{ + use_snap=p_use; +} + +void SpriteRegionEditor::_set_show_grid(bool p_show) +{ + snap_show_grid=p_show; + edit_draw->update(); +} + +void SpriteRegionEditor::_set_snap_off_x(float p_val) +{ + snap_offset.x=p_val; + edit_draw->update(); +} + +void SpriteRegionEditor::_set_snap_off_y(float p_val) +{ + snap_offset.y=p_val; + edit_draw->update(); +} + +void SpriteRegionEditor::_set_snap_step_x(float p_val) +{ + snap_step.x=p_val; + edit_draw->update(); +} + +void SpriteRegionEditor::_set_snap_step_y(float p_val) +{ + snap_step.y=p_val; + edit_draw->update(); +} + +void SpriteRegionEditor::_notification(int p_what) +{ + switch(p_what) { + + case NOTIFICATION_READY: { + edit_node->set_icon( get_icon("RegionEdit","EditorIcons")); + b_snap_grid->set_icon( get_icon("Grid", "EditorIcons")); + b_snap_enable->set_icon( get_icon("Snap", "EditorIcons")); + icon_zoom->set_texture( get_icon("Zoom", "EditorIcons")); + } break; + } +} + +void SpriteRegionEditor::_node_removed(Node *p_node) +{ + if(p_node==node) { + node=NULL; + hide(); + } +} + +void SpriteRegionEditor::_bind_methods() +{ + ObjectTypeDB::bind_method(_MD("_edit_node"),&SpriteRegionEditor::_edit_node); + ObjectTypeDB::bind_method(_MD("_region_draw"),&SpriteRegionEditor::_region_draw); + ObjectTypeDB::bind_method(_MD("_region_input"),&SpriteRegionEditor::_region_input); + ObjectTypeDB::bind_method(_MD("_scroll_changed"),&SpriteRegionEditor::_scroll_changed); + ObjectTypeDB::bind_method(_MD("_node_removed"),&SpriteRegionEditor::_node_removed); + ObjectTypeDB::bind_method(_MD("_set_use_snap"),&SpriteRegionEditor::_set_use_snap); + ObjectTypeDB::bind_method(_MD("_set_show_grid"),&SpriteRegionEditor::_set_show_grid); + ObjectTypeDB::bind_method(_MD("_set_snap_off_x"),&SpriteRegionEditor::_set_snap_off_x); + ObjectTypeDB::bind_method(_MD("_set_snap_off_y"),&SpriteRegionEditor::_set_snap_off_y); + ObjectTypeDB::bind_method(_MD("_set_snap_step_x"),&SpriteRegionEditor::_set_snap_step_x); + ObjectTypeDB::bind_method(_MD("_set_snap_step_y"),&SpriteRegionEditor::_set_snap_step_y); +} + +void SpriteRegionEditor::edit(Node *p_sprite) +{ + if (p_sprite) { + node=p_sprite->cast_to<Sprite>(); + node->connect("exit_tree",this,"_node_removed",varray(),CONNECT_ONESHOT); + } else { + if (node) + node->disconnect("exit_tree",this,"_node_removed"); + node=NULL; + } + +} +void SpriteRegionEditor::_edit_node() +{ + if (node->get_texture().is_null()) { + + error->set_text("No texture in this sprite.\nSet a texture to be able to edit Region."); + error->popup_centered_minsize(); + return; + } + + rect=node->get_region_rect(); + dlg_editor->popup_centered_ratio(0.85); +} + +inline float _snap_scalar(float p_offset, float p_step, float p_target) { + return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target; +} + +Vector2 SpriteRegionEditor::snap_point(Vector2 p_target) const { + if (use_snap) { + p_target.x = _snap_scalar(snap_offset.x, snap_step.x, p_target.x); + p_target.y = _snap_scalar(snap_offset.y, snap_step.y, p_target.y); + } + p_target = p_target.snapped(Size2(1, 1)); + + return p_target; +} + +SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor) +{ + node=NULL; + editor=p_editor; + undo_redo = editor->get_undo_redo(); + + snap_step=Vector2(10,10); + use_snap=false; + snap_show_grid=false; + + add_child( memnew( VSeparator )); + edit_node = memnew( ToolButton ); + add_child(edit_node); + edit_node->connect("pressed",this,"_edit_node"); + + dlg_editor = memnew( AcceptDialog ); + add_child(dlg_editor); + dlg_editor->set_title("Sprite Region Editor"); + dlg_editor->set_self_opacity(0.9); + + VBoxContainer *main_vb = memnew( VBoxContainer ); + dlg_editor->add_child(main_vb); + dlg_editor->set_child_rect(main_vb); + HBoxContainer *hb_tools = memnew( HBoxContainer ); + main_vb->add_child(hb_tools); + + b_snap_enable = memnew( ToolButton ); + hb_tools->add_child(b_snap_enable); + b_snap_enable->set_text("Snap"); + b_snap_enable->set_focus_mode(FOCUS_NONE); + b_snap_enable->set_toggle_mode(true); + b_snap_enable->set_pressed(use_snap); + b_snap_enable->set_tooltip("Enable Snap"); + b_snap_enable->connect("toggled",this,"_set_use_snap"); + + b_snap_grid = memnew( ToolButton ); + hb_tools->add_child(b_snap_grid); + b_snap_grid->set_text("Grid"); + b_snap_grid->set_focus_mode(FOCUS_NONE); + b_snap_grid->set_toggle_mode(true); + b_snap_grid->set_pressed(snap_show_grid); + b_snap_grid->set_tooltip("Show Grid"); + b_snap_grid->connect("toggled",this,"_set_show_grid"); + + hb_tools->add_child( memnew( VSeparator )); + hb_tools->add_child( memnew( Label("Grid Offset:") ) ); + + SpinBox *sb_off_x = memnew( SpinBox ); + sb_off_x->set_min(-256); + sb_off_x->set_max(256); + sb_off_x->set_step(1); + sb_off_x->set_val(snap_offset.x); + sb_off_x->set_suffix("px"); + sb_off_x->connect("value_changed", this, "_set_snap_off_x"); + hb_tools->add_child(sb_off_x); + + SpinBox *sb_off_y = memnew( SpinBox ); + sb_off_y->set_min(-256); + sb_off_y->set_max(256); + sb_off_y->set_step(1); + sb_off_y->set_val(snap_offset.y); + sb_off_y->set_suffix("px"); + sb_off_y->connect("value_changed", this, "_set_snap_off_y"); + hb_tools->add_child(sb_off_y); + + hb_tools->add_child( memnew( VSeparator )); + hb_tools->add_child( memnew( Label("Grid Step:") ) ); + + SpinBox *sb_step_x = memnew( SpinBox ); + sb_step_x->set_min(-256); + sb_step_x->set_max(256); + sb_step_x->set_step(1); + sb_step_x->set_val(snap_step.x); + sb_step_x->set_suffix("px"); + sb_step_x->connect("value_changed", this, "_set_snap_step_x"); + hb_tools->add_child(sb_step_x); + + SpinBox *sb_step_y = memnew( SpinBox ); + sb_step_y->set_min(-256); + sb_step_y->set_max(256); + sb_step_y->set_step(1); + sb_step_y->set_val(snap_step.y); + sb_step_y->set_suffix("px"); + sb_step_y->connect("value_changed", this, "_set_snap_step_y"); + hb_tools->add_child(sb_step_y); + +// MARIANOGNU::TODO: Add more tools? + + HBoxContainer *main_hb = memnew( HBoxContainer ); + main_vb->add_child(main_hb); + edit_draw = memnew( Control ); + main_hb->add_child(edit_draw); + main_hb->set_v_size_flags(SIZE_EXPAND_FILL); + edit_draw->set_h_size_flags(SIZE_EXPAND_FILL); + + + hb_tools->add_child( memnew( VSeparator )); + icon_zoom = memnew( TextureFrame ); + hb_tools->add_child(icon_zoom); + + zoom = memnew( HSlider ); + zoom->set_min(0.01); + zoom->set_max(4); + zoom->set_val(1); + zoom->set_step(0.01); + hb_tools->add_child(zoom); + zoom->set_custom_minimum_size(Size2(200,0)); + zoom_value = memnew( SpinBox ); + zoom->share(zoom_value); + zoom_value->set_custom_minimum_size(Size2(50,0)); + hb_tools->add_child(zoom_value); + zoom->connect("value_changed",this,"_scroll_changed"); + + + + vscroll = memnew( VScrollBar); + main_hb->add_child(vscroll); + vscroll->connect("value_changed",this,"_scroll_changed"); + hscroll = memnew( HScrollBar ); + main_vb->add_child(hscroll); + hscroll->connect("value_changed",this,"_scroll_changed"); + + edit_draw->connect("draw",this,"_region_draw"); + edit_draw->connect("input_event",this,"_region_input"); + draw_zoom=1.0; + updating_scroll=false; + + error = memnew( AcceptDialog); + add_child(error); + +} + +void SpriteRegionEditorPlugin::edit(Object *p_node) +{ + region_editor->edit(p_node->cast_to<Node>()); +} + +bool SpriteRegionEditorPlugin::handles(Object *p_node) const +{ + return p_node->is_type("Sprite"); +} + +void SpriteRegionEditorPlugin::make_visible(bool p_visible) +{ + if (p_visible) { + region_editor->show(); + } else { + region_editor->hide(); + region_editor->edit(NULL); + } +} + +SpriteRegionEditorPlugin::SpriteRegionEditorPlugin(EditorNode *p_node) +{ + editor = p_node; + region_editor= memnew ( SpriteRegionEditor(p_node) ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(region_editor); + + region_editor->hide(); +} + diff --git a/tools/editor/plugins/sprite_region_editor_plugin.h b/tools/editor/plugins/sprite_region_editor_plugin.h new file mode 100644 index 0000000000..cf69395f40 --- /dev/null +++ b/tools/editor/plugins/sprite_region_editor_plugin.h @@ -0,0 +1,125 @@ +/*************************************************************************/ +/* sprite_region_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Author: Mariano Suligoy */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SPRITE_REGION_EDITOR_PLUGIN_H +#define SPRITE_REGION_EDITOR_PLUGIN_H + +#include "canvas_item_editor_plugin.h" +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/2d/sprite.h" + +class SpriteRegionEditor : public HBoxContainer { + + OBJ_TYPE(SpriteRegionEditor, HBoxContainer ); + + ToolButton *edit_node; +// Button *use_region; + ToolButton *b_snap_enable; + ToolButton *b_snap_grid; + TextureFrame *icon_zoom; + HSlider *zoom; + SpinBox *zoom_value; + Control *edit_draw; + + VScrollBar *vscroll; + HScrollBar *hscroll; + + Sprite *node; + EditorNode *editor; + AcceptDialog *dlg_editor; + UndoRedo* undo_redo; + + Vector2 draw_ofs; + float draw_zoom; + bool updating_scroll; + + bool use_snap; + bool snap_show_grid; + Vector2 snap_offset; + Vector2 snap_step; + + Rect2 rect; + Rect2 rect_prev; + bool drag; + bool creating; + Vector2 drag_from; + int drag_index; + + AcceptDialog *error; + + void _set_use_snap(bool p_use); + void _set_show_grid(bool p_show); + void _set_snap_off_x(float p_val); + void _set_snap_off_y(float p_val); + void _set_snap_step_x(float p_val); + void _set_snap_step_y(float p_val); + +protected: + + void _notification(int p_what); + void _node_removed(Node *p_node); + static void _bind_methods(); + + Vector2 snap_point(Vector2 p_target) const; + +public: + + void edit(); + void _edit_node(); + void _region_draw(); + void _region_input(const InputEvent &p_input); + void _scroll_changed(float); + + void edit(Node *p_sprite); + SpriteRegionEditor(EditorNode* p_editor); + +}; + +class SpriteRegionEditorPlugin : public EditorPlugin +{ + + OBJ_TYPE( SpriteRegionEditorPlugin, EditorPlugin ); + + SpriteRegionEditor *region_editor; + EditorNode *editor; +public: + + virtual String get_name() const { return "Sprite"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + SpriteRegionEditorPlugin(EditorNode *p_node); +}; + +#endif // SPRITE_REGION_EDITOR_PLUGIN_H diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index 9f871fd3ab..6003b976aa 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -1156,7 +1156,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { image_shrink = memnew( SpinBox ); image_shrink->set_min(1); image_shrink->set_max(8); - image_shrink->set_step(1); + image_shrink->set_step(0.1); image_vb->add_margin_child("Shrink All Images:",image_shrink); sections->add_child(image_vb); @@ -1237,7 +1237,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { group_shrink->set_min(1); group_shrink->set_max(8); group_shrink->set_val(1); - group_shrink->set_step(1); + group_shrink->set_step(0.001); group_options->add_margin_child("Shrink By:",group_shrink); group_shrink->connect("value_changed",this,"_group_changed"); diff --git a/tools/editor/spatial_editor_gizmos.cpp b/tools/editor/spatial_editor_gizmos.cpp index 521a10bbd0..4dc9c4f43e 100644 --- a/tools/editor/spatial_editor_gizmos.cpp +++ b/tools/editor/spatial_editor_gizmos.cpp @@ -1,3191 +1,3191 @@ -/*************************************************************************/
-/* spatial_editor_gizmos.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "spatial_editor_gizmos.h"
-#include "geometry.h"
-#include "scene/3d/camera.h"
-#include "scene/resources/surface_tool.h"
-#include "scene/resources/sphere_shape.h"
-#include "scene/resources/box_shape.h"
-#include "scene/resources/capsule_shape.h"
-#include "scene/resources/ray_shape.h"
-#include "scene/resources/convex_polygon_shape.h"
-#include "scene/resources/plane_shape.h"
-#include "quick_hull.h"
-
-// Keep small children away from this file.
-// It's so ugly it will eat them alive
-
-#define HANDLE_HALF_SIZE 0.05
-
-void SpatialGizmoTool::clear() {
-
- for(int i=0;i<instances.size();i++) {
-
- if (instances[i].instance.is_valid())
- VS::get_singleton()->free(instances[i].instance);
-
-
- }
-
- billboard_handle=false;
- collision_segments.clear();
- collision_mesh=Ref<TriangleMesh>();
- instances.clear();
- handles.clear();
- secondary_handles.clear();
-}
-
-void SpatialGizmoTool::Instance::create_instance(Spatial *p_base) {
-
- instance = VS::get_singleton()->instance_create2(mesh->get_rid(),p_base->get_world()->get_scenario());
- VS::get_singleton()->instance_attach_object_instance_ID(instance,p_base->get_instance_ID());
- if (billboard)
- VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_BILLBOARD,true);
- if (unscaled)
- VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_DEPH_SCALE,true);
- if (skeleton.is_valid())
- VS::get_singleton()->instance_attach_skeleton(instance,skeleton);
- if (extra_margin)
- VS::get_singleton()->instance_set_extra_visibility_margin(instance,1);
- VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_CAST_SHADOW,false);
- VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_RECEIVE_SHADOWS,false);
- VS::get_singleton()->instance_set_layer_mask(instance,1<<SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26
-}
-
-
-
-void SpatialGizmoTool::add_mesh(const Ref<Mesh>& p_mesh,bool p_billboard, const RID &p_skeleton) {
-
- ERR_FAIL_COND(!spatial_node);
- Instance ins;
-
- ins.billboard=p_billboard;
- ins.mesh=p_mesh;
- ins.skeleton=p_skeleton;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
- }
-
- instances.push_back(ins);
-
-}
-
-void SpatialGizmoTool::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material,bool p_billboard){
-
- ERR_FAIL_COND(!spatial_node);
- Instance ins;
-
- Ref<Mesh> mesh = memnew( Mesh );
- Array a;
- a.resize(Mesh::ARRAY_MAX);
-
- a[Mesh::ARRAY_VERTEX]=p_lines;
-
- DVector<Color> color;
- color.resize(p_lines.size());
- {
- DVector<Color>::Write w = color.write();
- for(int i=0;i<p_lines.size();i++) {
- if (is_selected())
- w[i]=Color(1,1,1,0.6);
- else
- w[i]=Color(1,1,1,0.25);
- }
-
- }
-
- a[Mesh::ARRAY_COLOR]=color;
-
-
- mesh->add_surface(Mesh::PRIMITIVE_LINES,a);
- mesh->surface_set_material(0,p_material);
-
- if (p_billboard) {
- float md=0;
- for(int i=0;i<p_lines.size();i++) {
-
- md=MAX(0,p_lines[i].length());
-
- }
- if (md) {
- mesh->set_custom_aabb(AABB(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
- }
- }
-
- ins.billboard=p_billboard;
- ins.mesh=mesh;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
- }
-
- instances.push_back(ins);
-
-}
-
-void SpatialGizmoTool::add_unscaled_billboard(const Ref<Material>& p_material,float p_scale) {
-
- ERR_FAIL_COND(!spatial_node);
- Instance ins;
-
- Vector<Vector3 > vs;
- Vector<Vector2 > uv;
-
- vs.push_back(Vector3(-p_scale,p_scale,0));
- vs.push_back(Vector3(p_scale,p_scale,0));
- vs.push_back(Vector3(p_scale,-p_scale,0));
- vs.push_back(Vector3(-p_scale,-p_scale,0));
-
- uv.push_back(Vector2(1,0));
- uv.push_back(Vector2(0,0));
- uv.push_back(Vector2(0,1));
- uv.push_back(Vector2(1,1));
-
- Ref<Mesh> mesh = memnew( Mesh );
- Array a;
- a.resize(Mesh::ARRAY_MAX);
- a[Mesh::ARRAY_VERTEX]=vs;
- a[Mesh::ARRAY_TEX_UV]=uv;
- mesh->add_surface(Mesh::PRIMITIVE_TRIANGLE_FAN,a);
- mesh->surface_set_material(0,p_material);
-
- if (true) {
- float md=0;
- for(int i=0;i<vs.size();i++) {
-
- md=MAX(0,vs[i].length());
-
- }
- if (md) {
- mesh->set_custom_aabb(AABB(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
- }
- }
-
- ins.mesh=mesh;
- ins.unscaled=true;
- ins.billboard=true;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
- }
-
- instances.push_back(ins);
-
-
-}
-
-void SpatialGizmoTool::add_collision_triangles(const Ref<TriangleMesh>& p_tmesh) {
-
- collision_mesh=p_tmesh;
-}
-
-void SpatialGizmoTool::add_collision_segments(const Vector<Vector3> &p_lines) {
-
- int from=collision_segments.size();
- collision_segments.resize(from+p_lines.size());
- for(int i=0;i<p_lines.size();i++) {
-
- collision_segments[from+i]=p_lines[i];
- }
-}
-
-
-void SpatialGizmoTool::add_handles(const Vector<Vector3> &p_handles, bool p_billboard,bool p_secondary){
-
- billboard_handle=p_billboard;
-
- if (!is_selected())
- return;
-
- ERR_FAIL_COND(!spatial_node);
-
- ERR_FAIL_COND(!spatial_node);
- Instance ins;
-
-
- Ref<Mesh> mesh = memnew( Mesh );
-#if 1
-
- Array a;
- a.resize(VS::ARRAY_MAX);
- a[VS::ARRAY_VERTEX]=p_handles;
- DVector<Color> colors;
- {
- colors.resize(p_handles.size());
- DVector<Color>::Write w=colors.write();
- for(int i=0;i<p_handles.size();i++) {
-
- Color col(1,1,1,1);
- if (SpatialEditor::get_singleton()->get_over_gizmo_handle()!=i)
- col=Color(0.9,0.9,0.9,0.9);
- w[i]=col;
- }
-
- }
- a[VS::ARRAY_COLOR]=colors;
- mesh->add_surface(Mesh::PRIMITIVE_POINTS,a);
- mesh->surface_set_material(0,SpatialEditorGizmos::singleton->handle2_material);
-
- if (p_billboard) {
- float md=0;
- for(int i=0;i<p_handles.size();i++) {
-
- md=MAX(0,p_handles[i].length());
-
- }
- if (md) {
- mesh->set_custom_aabb(AABB(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
- }
- }
-
-
-
-#else
- for(int ih=0;ih<p_handles.size();ih++) {
-
-
- Vector<Vector3> vertices;
- Vector<Vector3> normals;
-
- int vtx_idx=0;
-#define ADD_VTX(m_idx);\
- vertices.push_back( (face_points[m_idx]*HANDLE_HALF_SIZE+p_handles[ih]) );\
- normals.push_back( normal_points[m_idx] );\
- vtx_idx++;\
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
- Vector3 normal_points[4];
- float uv_points[8]={0,0,0,1,1,1,1,0};
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- normal_points[j]=Vector3();
- normal_points[j][i%3]=(i>=3?-1:1);
- }
- //tri 1
- ADD_VTX(0);
- ADD_VTX(1);
- ADD_VTX(2);
- //tri 2
- ADD_VTX(2);
- ADD_VTX(3);
- ADD_VTX(0);
-
- }
-
-
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[VisualServer::ARRAY_NORMAL]= normals ;
- d[VisualServer::ARRAY_VERTEX]= vertices ;
-
- mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d);
- mesh->surface_set_material(ih,SpatialEditorGizmos::singleton->handle_material);
-
-
- }
-#endif
- ins.mesh=mesh;
- ins.billboard=p_billboard;
- ins.extra_margin=true;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
- }
- instances.push_back(ins);
- if (!p_secondary) {
- int chs=handles.size();
- handles.resize(chs+p_handles.size());
- for(int i=0;i<p_handles.size();i++) {
- handles[i+chs]=p_handles[i];
- }
- } else {
-
- int chs=secondary_handles.size();
- secondary_handles.resize(chs+p_handles.size());
- for(int i=0;i<p_handles.size();i++) {
- secondary_handles[i+chs]=p_handles[i];
- }
-
- }
-
-}
-
-
-void SpatialGizmoTool::set_spatial_node(Spatial *p_node){
-
- spatial_node=p_node;
-
-}
-
-bool SpatialGizmoTool::intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum) {
-
- ERR_FAIL_COND_V(!spatial_node,false);
- ERR_FAIL_COND_V(!valid,false);
-
- if (collision_segments.size()) {
-
- const Plane *p=p_frustum.ptr();
- int fc=p_frustum.size();
-
- int vc=collision_segments.size();
- const Vector3* vptr=collision_segments.ptr();
- Transform t = spatial_node->get_global_transform();
-
- for(int i=0;i<vc/2;i++) {
-
-
- Vector3 a=t.xform(vptr[i*2+0]);
- Vector3 b=t.xform(vptr[i*2+1]);
-
- bool any_out=false;
- for(int j=0;j<fc;j++) {
-
- if (p[j].distance_to(a) > 0 && p[j].distance_to(b) >0) {
-
- any_out=true;
- break;
- }
- }
-
- if (!any_out)
- return true;
- }
-
- return false;
- }
-
- return false;
-}
-
-
-bool SpatialGizmoTool::intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle,bool p_sec_first) {
-
- ERR_FAIL_COND_V(!spatial_node,false);
- ERR_FAIL_COND_V(!valid,false);
-
- if (r_gizmo_handle) {
-
- Transform t = spatial_node->get_global_transform();
- t.orthonormalize();
- if (billboard_handle) {
- t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
- }
- Transform ti=t.affine_inverse();
-
- Vector3 ray_from=ti.xform(p_camera->project_ray_origin(p_point));
- Vector3 ray_dir=t.basis.xform_inv(p_camera->project_ray_normal(p_point)).normalized();
- Vector3 ray_to = ray_from+ray_dir*4096;
-
- float min_d=1e20;
- int idx=-1;
-
- for(int i=0;i<secondary_handles.size();i++) {
-#if 1
-
-
- Vector3 hpos = t.xform(secondary_handles[i]);
- Vector2 p = p_camera->unproject_position(hpos);
- if (p.distance_to(p_point)<SpatialEditorGizmos::singleton->handle_t->get_width()*0.6) {
-
-
- real_t dp = p_camera->get_transform().origin.distance_to(hpos);
- if (dp<min_d) {
-
- r_pos=t.xform(hpos);
- r_normal=p_camera->get_transform().basis.get_axis(2);
- min_d=dp;
- idx=i+handles.size();
-
- }
-
- }
-
-#else
- AABB aabb;
- aabb.pos=Vector3(-1,-1,-1)*HANDLE_HALF_SIZE;
- aabb.size=aabb.pos*-2;
- aabb.pos+=secondary_handles[i];
-
-
- Vector3 rpos,rnorm;
-
- if (aabb.intersects_segment(ray_from,ray_to,&rpos,&rnorm)) {
-
- real_t dp = ray_dir.dot(rpos);
- if (dp<min_d) {
-
- r_pos=t.xform(rpos);
- r_normal=ti.basis.xform_inv(rnorm).normalized();
- min_d=dp;
- idx=i+handles.size();
-
- }
- }
-#endif
- }
-
- if (p_sec_first && idx!=-1) {
-
- *r_gizmo_handle=idx;
- return true;
- }
-
- min_d=1e20;
-
- for(int i=0;i<handles.size();i++) {
-
-#if 1
-
-
- Vector3 hpos = t.xform(handles[i]);
- Vector2 p = p_camera->unproject_position(hpos);
- if (p.distance_to(p_point)<SpatialEditorGizmos::singleton->handle_t->get_width()*0.6) {
-
-
- real_t dp = p_camera->get_transform().origin.distance_to(hpos);
- if (dp<min_d) {
-
- r_pos=t.xform(hpos);
- r_normal=p_camera->get_transform().basis.get_axis(2);
- min_d=dp;
- idx=i;
-
- }
-
- }
-
-#else
-
- AABB aabb;
- aabb.pos=Vector3(-1,-1,-1)*HANDLE_HALF_SIZE;
- aabb.size=aabb.pos*-2;
- aabb.pos+=handles[i];
-
-
- Vector3 rpos,rnorm;
-
- if (aabb.intersects_segment(ray_from,ray_to,&rpos,&rnorm)) {
-
- real_t dp = ray_dir.dot(rpos);
- if (dp<min_d) {
-
- r_pos=t.xform(rpos);
- r_normal=ti.basis.xform_inv(rnorm).normalized();
- min_d=dp;
- idx=i;
-
- }
- }
-#endif
- }
-
- if (idx>=0) {
- *r_gizmo_handle=idx;
- return true;
- }
-
-
- }
-
- if (collision_segments.size()) {
-
- Plane camp(p_camera->get_transform().origin,(-p_camera->get_transform().basis.get_axis(2)).normalized());
-
- int vc=collision_segments.size();
- const Vector3* vptr=collision_segments.ptr();
- Transform t = spatial_node->get_global_transform();
- if (billboard_handle) {
- t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
- }
-
- Vector3 cp;
- float cpd=1e20;
-
- for(int i=0;i<vc/2;i++) {
-
-
- Vector3 a=t.xform(vptr[i*2+0]);
- Vector3 b=t.xform(vptr[i*2+1]);
- Vector2 s[2];
- s[0] = p_camera->unproject_position(a);
- s[1] = p_camera->unproject_position(b);
-
-
- Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point,s);
-
- float pd = p.distance_to(p_point);
-
- if (pd<cpd) {
-
-
- float d = s[0].distance_to(s[1]);
- Vector3 tcp;
- if (d>0) {
-
- float d2=s[0].distance_to(p)/d;
- tcp = a+(b-a)*d2;
-
- } else {
- tcp=a;
-
- }
-
- if (camp.distance_to(tcp)<p_camera->get_znear())
- continue;
- cp=tcp;
- cpd=pd;
- }
- }
-
- if (cpd<8) {
-
- r_pos=cp;
- r_normal=-p_camera->project_ray_normal(p_point);
- return true;
- }
-
- return false;
- }
-
-
- if (collision_mesh.is_valid()) {
- Transform gt = spatial_node->get_global_transform();
-
- if (billboard_handle) {
- gt.set_look_at(gt.origin,gt.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
- }
-
- Transform ai=gt.affine_inverse();
- Vector3 ray_from = ai.xform(p_camera->project_ray_origin(p_point));
- Vector3 ray_dir=ai.basis.xform(p_camera->project_ray_normal(p_point)).normalized();
- Vector3 rpos,rnorm;
-
-#if 1
-
-
-
- if (collision_mesh->intersect_ray(ray_from,ray_dir,rpos,rnorm)) {
-
- r_pos=gt.xform(rpos);
- r_normal=gt.basis.xform(rnorm).normalized();
- return true;
- }
-#else
-
- if (collision_mesh->intersect_segment(ray_from,ray_from+ray_dir*4906.0,rpos,rnorm)) {
-
- r_pos=gt.xform(rpos);
- r_normal=gt.basis.xform(rnorm).normalized();
- return true;
- }
-
-#endif
- }
-
- return false;
-
-}
-
-
-
-void SpatialGizmoTool::create() {
-
- ERR_FAIL_COND(!spatial_node);
- ERR_FAIL_COND(valid);
- valid=true;
-
- for(int i=0;i<instances.size();i++) {
-
- instances[i].create_instance(spatial_node);
- }
-
- transform();
-
-}
-
-void SpatialGizmoTool::transform(){
-
- ERR_FAIL_COND(!spatial_node);
- ERR_FAIL_COND(!valid);
- for(int i=0;i<instances.size();i++) {
- VS::get_singleton()->instance_set_transform(instances[i].instance,spatial_node->get_global_transform());
- }
-
-}
-
-
-void SpatialGizmoTool::free(){
-
- ERR_FAIL_COND(!spatial_node);
- ERR_FAIL_COND(!valid);
-
- for(int i=0;i<instances.size();i++) {
-
- if (instances[i].instance.is_valid())
- VS::get_singleton()->free(instances[i].instance);
- instances[i].instance=RID();
- }
-
- valid=false;
-
-
-}
-
-
-
-SpatialGizmoTool::SpatialGizmoTool() {
- valid=false;
- billboard_handle=false;
-
-}
-
-SpatialGizmoTool::~SpatialGizmoTool(){
-
- clear();
-}
-
-Vector3 SpatialGizmoTool::get_handle_pos(int p_idx) const {
-
- ERR_FAIL_INDEX_V(p_idx,handles.size(),Vector3());
-
- return handles[p_idx];
-
-}
-
-//// light gizmo
-
-
-String LightSpatialGizmo::get_handle_name(int p_idx) const {
-
- if (p_idx==0)
- return "Radius";
- else
- return "Aperture";
-}
-
-
-Variant LightSpatialGizmo::get_handle_value(int p_idx) const{
-
- if (p_idx==0)
- return light->get_parameter(Light::PARAM_RADIUS);
- if (p_idx==1)
- return light->get_parameter(Light::PARAM_SPOT_ANGLE);
-
- return Variant();
-}
-
-
-static float _find_closest_angle_to_half_pi_arc(const Vector3& p_from, const Vector3& p_to, float p_arc_radius,const Transform& p_arc_xform) {
-
- //bleh, discrete is simpler
- static const int arc_test_points=64;
- float min_d = 1e20;
- Vector3 min_p;
-
-
- for(int i=0;i<arc_test_points;i++) {
-
- float a = i*Math_PI*0.5/arc_test_points;
- float an = (i+1)*Math_PI*0.5/arc_test_points;
- Vector3 p=Vector3( Math::cos(a), 0, -Math::sin(a) )*p_arc_radius;
- Vector3 n=Vector3( Math::cos(an), 0,- Math::sin(an) )*p_arc_radius;
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(p,n,p_from,p_to,ra,rb);
-
- float d = ra.distance_to(rb);
- if (d<min_d) {
- min_d=d;
- min_p=ra;
- }
-
- }
-
- //min_p = p_arc_xform.affine_inverse().xform(min_p);
- float a = Vector2(min_p.x,-min_p.z).atan2();
- return a*180.0/Math_PI;
-}
-
-
-void LightSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point) {
-
- Transform gt = light->get_global_transform();
- gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 s[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
- if (p_idx==0) {
-
- if (light->cast_to<SpotLight>()) {
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,-4096),s[0],s[1],ra,rb);
-
- float d = -ra.z;
- if (d<0)
- d=0;
-
- light->set_parameter(Light::PARAM_RADIUS,d);
- } else if (light->cast_to<OmniLight>()) {
-
- Plane cp=Plane( gt.origin, p_camera->get_transform().basis.get_axis(2));
-
- Vector3 inters;
- if (cp.intersects_ray(ray_from,ray_dir,&inters)) {
-
- float r = inters.distance_to(gt.origin);
- light->set_parameter(Light::PARAM_RADIUS,r);
- }
-
- }
-
- } else if (p_idx==1) {
-
- float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],light->get_parameter(Light::PARAM_RADIUS),gt);
- light->set_parameter(Light::PARAM_SPOT_ANGLE,CLAMP(a,0.01,89.99));
- }
-}
-
-void LightSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- if (p_cancel) {
-
- light->set_parameter(p_idx==0?Light::PARAM_RADIUS:Light::PARAM_SPOT_ANGLE,p_restore);
-
- } else if (p_idx==0) {
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Light Radius");
- ur->add_do_method(light,"set_parameter",Light::PARAM_RADIUS,light->get_parameter(Light::PARAM_RADIUS));
- ur->add_undo_method(light,"set_parameter",Light::PARAM_RADIUS,p_restore);
- ur->commit_action();
- } else if (p_idx==1) {
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Light Radius");
- ur->add_do_method(light,"set_parameter",Light::PARAM_SPOT_ANGLE,light->get_parameter(Light::PARAM_SPOT_ANGLE));
- ur->add_undo_method(light,"set_parameter",Light::PARAM_SPOT_ANGLE,p_restore);
- ur->commit_action();
-
- }
-}
-
-
-
-void LightSpatialGizmo::redraw() {
-
-
- if (light->cast_to<DirectionalLight>()) {
-
-
-
- const int arrow_points=5;
- Vector3 arrow[arrow_points]={
- Vector3(0,0,2),
- Vector3(1,1,2),
- Vector3(1,1,-1),
- Vector3(2,2,-1),
- Vector3(0,0,-3)
- };
-
- int arrow_sides=4;
-
- Vector<Vector3> lines;
-
-
- for(int i = 0; i < arrow_sides ; i++) {
-
-
- Matrix3 ma(Vector3(0,0,1),Math_PI*2*float(i)/arrow_sides);
- Matrix3 mb(Vector3(0,0,1),Math_PI*2*float(i+1)/arrow_sides);
-
-
- for(int j=1;j<arrow_points-1;j++) {
-
- if (j!=2) {
- lines.push_back(ma.xform(arrow[j]));
- lines.push_back(ma.xform(arrow[j+1]));
- }
- if (j<arrow_points-1) {
- lines.push_back(ma.xform(arrow[j]));
- lines.push_back(mb.xform(arrow[j]));
- }
-
- }
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->light_material);
- add_collision_segments(lines);
- add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_directional_icon,0.05);
-
- }
-
- if (light->cast_to<OmniLight>()) {
-
- clear();
-
-
- OmniLight *on = light->cast_to<OmniLight>();
-
- float r = on->get_parameter(Light::PARAM_RADIUS);
-
- Vector<Vector3> points;
-
- for(int i=0;i<=360;i++) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
- points.push_back(Vector3(a.x,a.y,0));
- points.push_back(Vector3(b.x,b.y,0));
-
- }
-
- add_lines(points,SpatialEditorGizmos::singleton->light_material,true);
- add_collision_segments(points);
-
- add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon,0.05);
-
- Vector<Vector3> handles;
- handles.push_back(Vector3(r,0,0));
- add_handles(handles,true);
-
-
- }
-
-
- if (light->cast_to<SpotLight>()) {
-
- clear();
-
- Vector<Vector3> points;
- SpotLight *on = light->cast_to<SpotLight>();
-
- float r = on->get_parameter(Light::PARAM_RADIUS);
- float w = r*Math::sin(Math::deg2rad(on->get_parameter(Light::PARAM_SPOT_ANGLE)));
- float d = r*Math::cos(Math::deg2rad(on->get_parameter(Light::PARAM_SPOT_ANGLE)));
-
-
-
- for(int i=0;i<360;i++) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
-
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
- points.push_back(Vector3(a.x,a.y,-d));
- points.push_back(Vector3(b.x,b.y,-d));
-
- if (i%90==0) {
-
- points.push_back(Vector3(a.x,a.y,-d));
- points.push_back(Vector3());
-
- }
-
-
- }
-
- points.push_back(Vector3(0,0,-r));
- points.push_back(Vector3());
-
- add_lines(points,SpatialEditorGizmos::singleton->light_material);
-
- Vector<Vector3> handles;
- handles.push_back(Vector3(0,0,-r));
-
- Vector<Vector3> collision_segments;
-
- for(int i=0;i<64;i++) {
-
- float ra=i*Math_PI*2.0/64.0;
- float rb=(i+1)*Math_PI*2.0/64.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
-
- collision_segments.push_back(Vector3(a.x,a.y,-d));
- collision_segments.push_back(Vector3(b.x,b.y,-d));
-
- if (i%16==0) {
-
- collision_segments.push_back(Vector3(a.x,a.y,-d));
- collision_segments.push_back(Vector3());
-
- }
-
- if (i==16) {
-
- handles.push_back(Vector3(a.x,a.y,-d));
- }
-
- }
-
- collision_segments.push_back(Vector3(0,0,-r));
- collision_segments.push_back(Vector3());
-
-
- add_handles(handles);
- add_collision_segments(collision_segments);
- add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon,0.05);
-
- }
-
-}
-
-LightSpatialGizmo::LightSpatialGizmo(Light* p_light){
-
- light=p_light;
- set_spatial_node(p_light);
-
-}
-
-//////
-
-String CameraSpatialGizmo::get_handle_name(int p_idx) const {
-
- if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
- return "FOV";
- } else {
- return "Size";
- }
-}
-Variant CameraSpatialGizmo::get_handle_value(int p_idx) const{
-
- if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
- return camera->get_fov();
- } else {
-
- return camera->get_size();
- }
-}
-void CameraSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
- Transform gt = camera->get_global_transform();
- gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 s[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
-
- if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
- Transform gt=camera->get_global_transform();
- float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],1.0,gt);
- camera->set("fov",a);
- } else {
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(0,0,-1),Vector3(4096,0,-1),s[0],s[1],ra,rb);
- float d = ra.x * 2.0;
- if (d<0)
- d=0;
-
- camera->set("size",d);
- }
-
-}
-void CameraSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
-
- if (p_cancel) {
-
- camera->set("fov",p_restore);
- } else {
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Camera FOV");
- ur->add_do_property(camera,"fov",camera->get_fov());
- ur->add_undo_property(camera,"fov",p_restore);
- ur->commit_action();
- }
-
- } else {
-
- if (p_cancel) {
-
- camera->set("size",p_restore);
- } else {
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Camera Size");
- ur->add_do_property(camera,"size",camera->get_size());
- ur->add_undo_property(camera,"size",p_restore);
- ur->commit_action();
- }
-
- }
-
-}
-
-void CameraSpatialGizmo::redraw(){
-
- clear();
-
- Vector<Vector3> lines;
- Vector<Vector3> handles;
-
-
- switch(camera->get_projection()) {
-
- case Camera::PROJECTION_PERSPECTIVE: {
-
- float fov = camera->get_fov();
-
- Vector3 side=Vector3( Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov)) );
- Vector3 nside=side;
- nside.x=-nside.x;
- Vector3 up=Vector3(0,side.x,0);
-
-
-#define ADD_TRIANGLE( m_a, m_b, m_c)\
-{\
- lines.push_back(m_a);\
- lines.push_back(m_b);\
- lines.push_back(m_b);\
- lines.push_back(m_c);\
- lines.push_back(m_c);\
- lines.push_back(m_a);\
-}
-
- ADD_TRIANGLE( Vector3(), side+up, side-up );
- ADD_TRIANGLE( Vector3(), nside+up, nside-up );
- ADD_TRIANGLE( Vector3(), side+up, nside+up );
- ADD_TRIANGLE( Vector3(), side-up, nside-up );
-
- handles.push_back(side);
- side.x*=0.25;
- nside.x*=0.25;
- Vector3 tup( 0, up.y*3/2,side.z);
- ADD_TRIANGLE( tup, side+up, nside+up );
-
- } break;
- case Camera::PROJECTION_ORTHOGONAL: {
-
-#define ADD_QUAD( m_a, m_b, m_c, m_d)\
-{\
- lines.push_back(m_a);\
- lines.push_back(m_b);\
- lines.push_back(m_b);\
- lines.push_back(m_c);\
- lines.push_back(m_c);\
- lines.push_back(m_d);\
- lines.push_back(m_d);\
- lines.push_back(m_a);\
-}
- float size = camera->get_size();
-
- float hsize=size*0.5;
- Vector3 right(hsize,0,0);
- Vector3 up(0,hsize,0);
- Vector3 back(0,0,-1.0);
- Vector3 front(0,0,0);
-
- ADD_QUAD( -up-right,-up+right,up+right,up-right);
- ADD_QUAD( -up-right+back,-up+right+back,up+right+back,up-right+back);
- ADD_QUAD( up+right,up+right+back,up-right+back,up-right);
- ADD_QUAD( -up+right,-up+right+back,-up-right+back,-up-right);
- handles.push_back(right+back);
-
- right.x*=0.25;
- Vector3 tup( 0, up.y*3/2,back.z );
- ADD_TRIANGLE( tup, right+up+back, -right+up+back );
-
- } break;
-
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->camera_material);
- add_collision_segments(lines);
- add_handles(handles);
-}
-
-
-CameraSpatialGizmo::CameraSpatialGizmo(Camera* p_camera){
-
- camera=p_camera;
- set_spatial_node(camera);
-}
-
-
-
-
-//////
-
-void MeshInstanceSpatialGizmo::redraw() {
-
- Ref<Mesh> m = mesh->get_mesh();
- if (!m.is_valid())
- return; //none
-
- Ref<TriangleMesh> tm = m->generate_triangle_mesh();
- if (tm.is_valid())
- add_collision_triangles(tm);
-}
-
-MeshInstanceSpatialGizmo::MeshInstanceSpatialGizmo(MeshInstance* p_mesh) {
-
- mesh=p_mesh;
- set_spatial_node(p_mesh);
-}
-
-/////
-
-
-void Position3DSpatialGizmo::redraw() {
-
- clear();
- add_mesh(SpatialEditorGizmos::singleton->pos3d_mesh);
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs));
- cursor_points.push_back(Vector3(0,0,-cs));
- add_collision_segments(cursor_points);
-
-}
-
-
-Position3DSpatialGizmo::Position3DSpatialGizmo(Position3D* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-
-/////
-
-void SkeletonSpatialGizmo::redraw() {
-
- clear();
-
- Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
-
-
- surface_tool->begin(Mesh::PRIMITIVE_LINES);
- surface_tool->set_material(SpatialEditorGizmos::singleton->skeleton_material);
- Vector<Transform> grests;
- grests.resize(skel->get_bone_count());
-
- Vector<int> bones;
- Vector<float> weights;
- bones.resize(4);
- weights.resize(4);
-
- for(int i=0;i<4;i++) {
- bones[i]=0;
- weights[i]=0;
- }
-
- weights[0]=1;
-
-
- AABB aabb;
-
- Color bonecolor = Color(1.0,0.4,0.4,0.3);
- Color rootcolor = Color(0.4,1.0,0.4,0.1);
-
- for (int i=0;i<skel->get_bone_count();i++) {
-
- int parent = skel->get_bone_parent(i);
-
- if (parent>=0) {
- grests[i]=grests[parent] * skel->get_bone_rest(i);
-
- Vector3 v0 = grests[parent].origin;
- Vector3 v1 = grests[i].origin;
- Vector3 d = (v1-v0).normalized();
- float dist = v0.distance_to(v1);
-
- //find closest axis
- int closest=-1;
- float closest_d = 0.0;
-
- for(int j=0;j<3;j++) {
- float dp = Math::abs(grests[parent].basis[j].normalized().dot(d));
- if (j==0 || dp>closest_d)
- closest=j;
- }
-
- //find closest other
- Vector3 first;
- Vector3 points[4];
- int pointidx=0;
- for(int j=0;j<3;j++) {
-
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(rootcolor);
- surface_tool->add_vertex(v0-grests[parent].basis[j].normalized()*dist*0.05);
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(rootcolor);
- surface_tool->add_vertex(v0+grests[parent].basis[j].normalized()*dist*0.05);
-
- if (j==closest)
- continue;
-
- Vector3 axis;
- if (first==Vector3()) {
- axis = d.cross(d.cross(grests[parent].basis[j])).normalized();
- first=axis;
- } else {
- axis = d.cross(first).normalized();
- }
-
- for(int k=0;k<2;k++) {
-
- if (k==1)
- axis=-axis;
- Vector3 point = v0+d*dist*0.2;
- point+=axis*dist*0.1;
-
-
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(v0);
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(point);
-
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(point);
- bones[0]=i;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(v1);
- points[pointidx++]=point;
-
- }
-
- }
-
- SWAP( points[1],points[2] );
- for(int j=0;j<4;j++) {
-
-
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(points[j]);
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(points[(j+1)%4]);
- }
-
-
-/*
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(0.4,1,0.4,0.4));
- surface_tool->add_vertex(v0);
- bones[0]=i;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(0.4,1,0.4,0.4));
- surface_tool->add_vertex(v1);
-*/
- } else {
-
- grests[i]=skel->get_bone_rest(i);
- bones[0]=i;
- }
-/*
- Transform t = grests[i];
- t.orthonormalize();
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- }
-
- for(int j=0;j<4;j++) {
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
- surface_tool->add_vertex(t.xform(face_points[j]*0.04));
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
- surface_tool->add_vertex(t.xform(face_points[(j+1)%4]*0.04));
- }
-
- }
- */
- }
-
- Ref<Mesh> m = surface_tool->commit();
- add_mesh(m,false,skel->get_skeleton());
-
-}
-
-SkeletonSpatialGizmo::SkeletonSpatialGizmo(Skeleton* p_skel) {
-
- skel=p_skel;
- set_spatial_node(p_skel);
-}
-
-/////
-
-
-void SpatialPlayerSpatialGizmo::redraw() {
-
- clear();
- if (splayer->cast_to<SpatialStreamPlayer>()) {
-
- add_unscaled_billboard(SpatialEditorGizmos::singleton->stream_player_icon,0.05);
-
- } else if (splayer->cast_to<SpatialSamplePlayer>()) {
-
- add_unscaled_billboard(SpatialEditorGizmos::singleton->sample_player_icon,0.05);
-
- }
-
-}
-
-SpatialPlayerSpatialGizmo::SpatialPlayerSpatialGizmo(SpatialPlayer* p_splayer){
-
- set_spatial_node(p_splayer);
- splayer=p_splayer;
-}
-
-
-/////
-
-
-void RoomSpatialGizmo::redraw() {
-
- clear();
- Ref<RoomBounds> roomie = room->get_room();
- if (roomie.is_null())
- return;
- DVector<Face3> faces = roomie->get_geometry_hint();
-
- Vector<Vector3> lines;
- int fc=faces.size();
- DVector<Face3>::Read r =faces.read();
-
- Map<_EdgeKey,Vector3> edge_map;
-
- for(int i=0;i<fc;i++) {
-
- Vector3 fn = r[i].get_plane().normal;
-
- for(int j=0;j<3;j++) {
-
- _EdgeKey ek;
- ek.from=r[i].vertex[j].snapped(CMP_EPSILON);
- ek.to=r[i].vertex[(j+1)%3].snapped(CMP_EPSILON);
- if (ek.from<ek.to)
- SWAP(ek.from,ek.to);
-
- Map<_EdgeKey,Vector3>::Element *E=edge_map.find(ek);
-
- if (E) {
-
- if (E->get().dot(fn) >0.9) {
-
- E->get()=Vector3();
- }
-
- } else {
-
- edge_map[ek]=fn;
- }
-
- }
- }
-
- for(Map<_EdgeKey,Vector3>::Element *E=edge_map.front();E;E=E->next()) {
-
- if (E->get()!=Vector3()) {
- lines.push_back(E->key().from);
- lines.push_back(E->key().to);
- }
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->room_material);
- add_collision_segments(lines);
-
-}
-
-RoomSpatialGizmo::RoomSpatialGizmo(Room* p_room){
-
- set_spatial_node(p_room);
- room=p_room;
-}
-
-/////
-
-
-void PortalSpatialGizmo::redraw() {
-
- clear();
-
- Vector<Point2> points = portal->get_shape();
- if (points.size()==0) {
- return;
- }
-
- Vector<Vector3> lines;
-
- Vector3 center;
- for(int i=0;i<points.size();i++) {
-
- Vector3 f;
- f.x=points[i].x;
- f.y=points[i].y;
- Vector3 fn;
- fn.x=points[(i+1)%points.size()].x;
- fn.y=points[(i+1)%points.size()].y;
- center+=f;
-
- lines.push_back(f);
- lines.push_back(fn);
- }
-
- center/=points.size();
- lines.push_back(center);
- lines.push_back(center+Vector3(0,0,1));
-
- add_lines(lines,SpatialEditorGizmos::singleton->portal_material);
- add_collision_segments(lines);
-
-}
-
-PortalSpatialGizmo::PortalSpatialGizmo(Portal* p_portal){
-
- set_spatial_node(p_portal);
- portal=p_portal;
-}
-
-/////
-
-
-void RayCastSpatialGizmo::redraw() {
-
- clear();
-
-
- Vector<Vector3> lines;
-
- lines.push_back(Vector3());
- lines.push_back(raycast->get_cast_to());
-
- add_lines(lines,SpatialEditorGizmos::singleton->raycast_material);
- add_collision_segments(lines);
-
-}
-
-RayCastSpatialGizmo::RayCastSpatialGizmo(RayCast* p_raycast){
-
- set_spatial_node(p_raycast);
- raycast=p_raycast;
-}
-
-
-
-/////
-
-
-void VehicleWheelSpatialGizmo::redraw() {
-
- clear();
-
-
- Vector<Vector3> points;
-
- float r = car_wheel->get_radius();
- const int skip=10;
- for(int i=0;i<=360;i+=skip) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+skip);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));
-
- const int springsec=4;
-
- for(int j=0;j<springsec;j++) {
- float t = car_wheel->get_suspension_rest_length()*5;
- points.push_back(Vector3(a.x,i/360.0*t/springsec+j*(t/springsec),a.y)*0.2);
- points.push_back(Vector3(b.x,(i+skip)/360.0*t/springsec+j*(t/springsec),b.y)*0.2);
- }
-
-
- }
-
- //travel
- points.push_back(Vector3(0,0,0));
- points.push_back(Vector3(0,car_wheel->get_suspension_rest_length(),0));
-
- //axis
- points.push_back(Vector3(r*0.2,car_wheel->get_suspension_rest_length(),0));
- points.push_back(Vector3(-r*0.2,car_wheel->get_suspension_rest_length(),0));
- //axis
- points.push_back(Vector3(r*0.2,0,0));
- points.push_back(Vector3(-r*0.2,0,0));
-
- //forward line
- points.push_back(Vector3(0,-r,0));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(r*2*0.2,-r,r*2*0.8));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(-r*2*0.2,-r,r*2*0.8));
-
- add_lines(points,SpatialEditorGizmos::singleton->car_wheel_material);
- add_collision_segments(points);
-
-}
-
-VehicleWheelSpatialGizmo::VehicleWheelSpatialGizmo(VehicleWheel* p_car_wheel){
-
- set_spatial_node(p_car_wheel);
- car_wheel=p_car_wheel;
-}
-
-
-
-///
-
-void TestCubeSpatialGizmo::redraw() {
-
- clear();
- add_collision_triangles(SpatialEditorGizmos::singleton->test_cube_tm);
-}
-
-TestCubeSpatialGizmo::TestCubeSpatialGizmo(TestCube* p_tc) {
-
- tc=p_tc;
- set_spatial_node(p_tc);
-}
-
-
-///////////
-
-
-
-
-
-
-String CollisionShapeSpatialGizmo::get_handle_name(int p_idx) const {
-
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return "";
-
- if (s->cast_to<SphereShape>()) {
-
- return "Radius";
- }
-
- if (s->cast_to<BoxShape>()) {
-
- return "Extents";
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- return p_idx==0?"Radius":"Height";
- }
-
- if (s->cast_to<RayShape>()) {
-
- return "Length";
- }
-
- return "";
-}
-Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const{
-
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return Variant();
-
- if (s->cast_to<SphereShape>()) {
-
- Ref<SphereShape> ss = s;
- return ss->get_radius();
- }
-
- if (s->cast_to<BoxShape>()) {
-
- Ref<BoxShape> bs = s;
- return bs->get_extents();
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- Ref<CapsuleShape> cs = s;
- return p_idx==0?cs->get_radius():cs->get_height();
- }
-
- if (s->cast_to<RayShape>()) {
-
- Ref<RayShape> cs = s;
- return cs->get_length();
- }
-
- return Variant();
-}
-void CollisionShapeSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return;
-
- Transform gt = cs->get_global_transform();
- gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
-
- if (s->cast_to<SphereShape>()) {
-
- Ref<SphereShape> ss = s;
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),Vector3(4096,0,0),sg[0],sg[1],ra,rb);
- float d = ra.x;
- if (d<0.001)
- d=0.001;
-
- ss->set_radius(d);
- }
-
- if (s->cast_to<RayShape>()) {
-
- Ref<RayShape> rs = s;
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,4096),sg[0],sg[1],ra,rb);
- float d = ra.z;
- if (d<0.001)
- d=0.001;
-
- rs->set_length(d);
- }
-
-
- if (s->cast_to<BoxShape>()) {
-
- Vector3 axis;
- axis[p_idx]=1.0;
- Ref<BoxShape> bs = s;
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- if (d<0.001)
- d=0.001;
-
- Vector3 he = bs->get_extents();
- he[p_idx]=d;
- bs->set_extents(he);
-
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- Vector3 axis;
- axis[p_idx==0?0:2]=1.0;
- Ref<CapsuleShape> cs = s;
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
- float d = axis.dot(ra);
- if (p_idx==1)
- d-=cs->get_radius();
- if (d<0.001)
- d=0.001;
-
- if (p_idx==0)
- cs->set_radius(d);
- else if (p_idx==1)
- cs->set_height(d*2.0);
-
- }
-
-}
-void CollisionShapeSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return;
-
- if (s->cast_to<SphereShape>()) {
-
- Ref<SphereShape> ss=s;
- if (p_cancel) {
- ss->set_radius(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Sphere Shape Radius");
- ur->add_do_method(ss.ptr(),"set_radius",ss->get_radius());
- ur->add_undo_method(ss.ptr(),"set_radius",p_restore);
- ur->commit_action();
-
- }
-
- if (s->cast_to<BoxShape>()) {
-
- Ref<BoxShape> ss=s;
- if (p_cancel) {
- ss->set_extents(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Box Shape Extents");
- ur->add_do_method(ss.ptr(),"set_extents",ss->get_extents());
- ur->add_undo_method(ss.ptr(),"set_extents",p_restore);
- ur->commit_action();
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- Ref<CapsuleShape> ss=s;
- if (p_cancel) {
- if (p_idx==0)
- ss->set_radius(p_restore);
- else
- ss->set_height(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- if (p_idx==0) {
- ur->create_action("Change Capsule Shape Radius");
- ur->add_do_method(ss.ptr(),"set_radius",ss->get_radius());
- ur->add_undo_method(ss.ptr(),"set_radius",p_restore);
- } else {
- ur->create_action("Change Capsule Shape Height");
- ur->add_do_method(ss.ptr(),"set_height",ss->get_height());
- ur->add_undo_method(ss.ptr(),"set_height",p_restore);
-
- }
-
- ur->commit_action();
-
- }
-
- if (s->cast_to<RayShape>()) {
-
- Ref<RayShape> ss=s;
- if (p_cancel) {
- ss->set_length(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Ray Shape Length");
- ur->add_do_method(ss.ptr(),"set_length",ss->get_length());
- ur->add_undo_method(ss.ptr(),"set_length",p_restore);
- ur->commit_action();
-
- }
-
-}
-void CollisionShapeSpatialGizmo::redraw(){
-
- clear();
-
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return;
-
- if (s->cast_to<SphereShape>()) {
-
- Ref<SphereShape> sp= s;
- float r=sp->get_radius();
-
- Vector<Vector3> points;
-
- for(int i=0;i<=360;i++) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));
- points.push_back(Vector3(a.x,a.y,0));
- points.push_back(Vector3(b.x,b.y,0));
-
- }
-
- Vector<Vector3> collision_segments;
-
- for(int i=0;i<64;i++) {
-
- float ra=i*Math_PI*2.0/64.0;
- float rb=(i+1)*Math_PI*2.0/64.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- collision_segments.push_back(Vector3(a.x,0,a.y));
- collision_segments.push_back(Vector3(b.x,0,b.y));
- collision_segments.push_back(Vector3(0,a.x,a.y));
- collision_segments.push_back(Vector3(0,b.x,b.y));
- collision_segments.push_back(Vector3(a.x,a.y,0));
- collision_segments.push_back(Vector3(b.x,b.y,0));
- }
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(collision_segments);
- Vector<Vector3> handles;
- handles.push_back(Vector3(r,0,0));
- add_handles(handles);
-
- }
-
- if (s->cast_to<BoxShape>()) {
-
- Ref<BoxShape> bs=s;
- Vector<Vector3> lines;
- AABB aabb;
- aabb.pos=-bs->get_extents();
- aabb.size=aabb.pos*-2;
-
- for(int i=0;i<12;i++) {
- Vector3 a,b;
- aabb.get_edge(i,a,b);
- lines.push_back(a);
- lines.push_back(b);
- }
-
- Vector<Vector3> handles;
-
- for(int i=0;i<3;i++) {
-
- Vector3 ax;
- ax[i]=bs->get_extents()[i];
- handles.push_back(ax);
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(lines);
- add_handles(handles);
-
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- Ref<CapsuleShape> cs=s;
- float radius = cs->get_radius();
- float height = cs->get_height();
-
-
- Vector<Vector3> points;
-
- Vector3 d(0,0,height*0.5);
- for(int i=0;i<360;i++) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
-
- points.push_back(Vector3(a.x,a.y,0)+d);
- points.push_back(Vector3(b.x,b.y,0)+d);
-
- points.push_back(Vector3(a.x,a.y,0)-d);
- points.push_back(Vector3(b.x,b.y,0)-d);
-
- if (i%90==0) {
-
- points.push_back(Vector3(a.x,a.y,0)+d);
- points.push_back(Vector3(a.x,a.y,0)-d);
- }
-
- Vector3 dud = i<180?d:-d;
-
- points.push_back(Vector3(0,a.y,a.x)+dud);
- points.push_back(Vector3(0,b.y,b.x)+dud);
- points.push_back(Vector3(a.y,0,a.x)+dud);
- points.push_back(Vector3(b.y,0,b.x)+dud);
-
- }
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
-
- Vector<Vector3> collision_segments;
-
- for(int i=0;i<64;i++) {
-
- float ra=i*Math_PI*2.0/64.0;
- float rb=(i+1)*Math_PI*2.0/64.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
-
- collision_segments.push_back(Vector3(a.x,a.y,0)+d);
- collision_segments.push_back(Vector3(b.x,b.y,0)+d);
-
- collision_segments.push_back(Vector3(a.x,a.y,0)-d);
- collision_segments.push_back(Vector3(b.x,b.y,0)-d);
-
- if (i%16==0) {
-
- collision_segments.push_back(Vector3(a.x,a.y,0)+d);
- collision_segments.push_back(Vector3(a.x,a.y,0)-d);
- }
-
- Vector3 dud = i<32?d:-d;
-
- collision_segments.push_back(Vector3(0,a.y,a.x)+dud);
- collision_segments.push_back(Vector3(0,b.y,b.x)+dud);
- collision_segments.push_back(Vector3(a.y,0,a.x)+dud);
- collision_segments.push_back(Vector3(b.y,0,b.x)+dud);
-
- }
-
- add_collision_segments(collision_segments);
-
- Vector<Vector3> handles;
- handles.push_back(Vector3(cs->get_radius(),0,0));
- handles.push_back(Vector3(0,0,cs->get_height()*0.5+cs->get_radius()));
- add_handles(handles);
-
-
- }
-
- if (s->cast_to<PlaneShape>()) {
-
- Ref<PlaneShape> ps=s;
- Plane p = ps->get_plane();
- Vector<Vector3> points;
-
- Vector3 n1 = p.get_any_perpendicular_normal();
- Vector3 n2 = p.normal.cross(n1).normalized();
-
- Vector3 pface[4]={
- p.normal*p.d+n1*10.0+n2*10.0,
- p.normal*p.d+n1*10.0+n2*-10.0,
- p.normal*p.d+n1*-10.0+n2*-10.0,
- p.normal*p.d+n1*-10.0+n2*10.0,
- };
-
- points.push_back(pface[0]);
- points.push_back(pface[1]);
- points.push_back(pface[1]);
- points.push_back(pface[2]);
- points.push_back(pface[2]);
- points.push_back(pface[3]);
- points.push_back(pface[3]);
- points.push_back(pface[0]);
- points.push_back(p.normal*p.d);
- points.push_back(p.normal*p.d+p.normal*3);
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(points);
-
- }
-
-
- if (s->cast_to<ConvexPolygonShape>()) {
-
- DVector<Vector3> points = s->cast_to<ConvexPolygonShape>()->get_points();
-
- if (points.size()>3) {
-
- QuickHull qh;
- Vector<Vector3> varr = Variant(points);
- Geometry::MeshData md;
- Error err = qh.build(varr,md);
- if (err==OK) {
- Vector<Vector3> points;
- points.resize(md.edges.size()*2);
- for(int i=0;i<md.edges.size();i++) {
- points[i*2+0]=md.vertices[md.edges[i].a];
- points[i*2+1]=md.vertices[md.edges[i].b];
- }
-
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(points);
-
- }
- }
-
- }
-
-
- if (s->cast_to<RayShape>()) {
-
- Ref<RayShape> rs=s;
-
- Vector<Vector3> points;
- points.push_back(Vector3());
- points.push_back(Vector3(0,0,rs->get_length()));
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(points);
- Vector<Vector3> handles;
- handles.push_back(Vector3(0,0,rs->get_length()));
- add_handles(handles);
-
-
- }
-
-}
-CollisionShapeSpatialGizmo::CollisionShapeSpatialGizmo(CollisionShape* p_cs) {
-
- cs=p_cs;
- set_spatial_node(p_cs);
-}
-
-
-
-/////
-
-
-void CollisionPolygonSpatialGizmo::redraw() {
-
- clear();
-
- Vector<Vector2> points = polygon->get_polygon();
- float depth = polygon->get_depth()*0.5;
-
- Vector<Vector3> lines;
- for(int i=0;i<points.size();i++) {
-
- int n = (i+1)%points.size();
- lines.push_back(Vector3(points[i].x,points[i].y,depth));
- lines.push_back(Vector3(points[n].x,points[n].y,depth));
- lines.push_back(Vector3(points[i].x,points[i].y,-depth));
- lines.push_back(Vector3(points[n].x,points[n].y,-depth));
- lines.push_back(Vector3(points[i].x,points[i].y,depth));
- lines.push_back(Vector3(points[i].x,points[i].y,-depth));
-
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(lines);
-}
-
-CollisionPolygonSpatialGizmo::CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon){
-
- set_spatial_node(p_polygon);
- polygon=p_polygon;
-}
-///
-
-
-String VisibilityNotifierGizmo::get_handle_name(int p_idx) const {
-
- switch(p_idx) {
- case 0: return "X";
- case 1: return "Y";
- case 2: return "Z";
- }
-
- return "";
-}
-Variant VisibilityNotifierGizmo::get_handle_value(int p_idx) const{
-
- return notifier->get_aabb();
-}
-void VisibilityNotifierGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
-
- Transform gt = notifier->get_global_transform();
- //gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- AABB aabb = notifier->get_aabb();
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
- Vector3 ofs = aabb.pos+aabb.size*0.5;;
-
- Vector3 axis;
- axis[p_idx]=1.0;
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(ofs,ofs+axis*4096,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- if (d<0.001)
- d=0.001;
-
- Vector3 he = aabb.size;
- aabb.pos[p_idx]=(aabb.pos[p_idx]+aabb.size[p_idx]*0.5)-d;
- aabb.size[p_idx]=d*2;
- notifier->set_aabb(aabb);
-}
-
-void VisibilityNotifierGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
-
- if (p_cancel) {
- notifier->set_aabb(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action("Change Notifier Extents");
- ur->add_do_method(notifier,"set_aabb",notifier->get_aabb());
- ur->add_undo_method(notifier,"set_aabb",p_restore);
- ur->commit_action();
-
-}
-
-void VisibilityNotifierGizmo::redraw(){
-
- clear();
-
- Vector<Vector3> lines;
- AABB aabb = notifier->get_aabb();
-
- for(int i=0;i<12;i++) {
- Vector3 a,b;
- aabb.get_edge(i,a,b);
- lines.push_back(a);
- lines.push_back(b);
- }
-
- Vector<Vector3> handles;
-
-
- for(int i=0;i<3;i++) {
-
- Vector3 ax;
- ax[i]=aabb.pos[i]+aabb.size[i];
- handles.push_back(ax);
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->visibility_notifier_material);
- //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
- add_collision_segments(lines);
- add_handles(handles);
-
-}
-VisibilityNotifierGizmo::VisibilityNotifierGizmo(VisibilityNotifier* p_notifier){
-
- notifier=p_notifier;
- set_spatial_node(p_notifier);
-}
-
-////////
-
-
-
-void NavigationMeshSpatialGizmo::redraw() {
-
- clear();
- Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh();
- if (navmeshie.is_null())
- return;
-
- DVector<Vector3> vertices = navmeshie->get_vertices();
- DVector<Vector3>::Read vr=vertices.read();
- List<Face3> faces;
- for(int i=0;i<navmeshie->get_polygon_count();i++) {
- Vector<int> p = navmeshie->get_polygon(i);
-
- for(int j=2;j<p.size();j++) {
- Face3 f;
- f.vertex[0]=vr[p[0]];
- f.vertex[1]=vr[p[j-1]];
- f.vertex[2]=vr[p[j]];
-
- faces.push_back(f);
- }
- }
-
-
- Map<_EdgeKey,bool> edge_map;
- DVector<Vector3> tmeshfaces;
- tmeshfaces.resize(faces.size()*3);
-
- {
- DVector<Vector3>::Write tw=tmeshfaces.write();
- int tidx=0;
-
-
- for(List<Face3>::Element *E=faces.front();E;E=E->next()) {
-
- const Face3 &f = E->get();
-
- for(int j=0;j<3;j++) {
-
- tw[tidx++]=f.vertex[j];
- _EdgeKey ek;
- ek.from=f.vertex[j].snapped(CMP_EPSILON);
- ek.to=f.vertex[(j+1)%3].snapped(CMP_EPSILON);
- if (ek.from<ek.to)
- SWAP(ek.from,ek.to);
-
- Map<_EdgeKey,bool>::Element *E=edge_map.find(ek);
-
- if (E) {
-
- E->get()=false;
-
- } else {
-
- edge_map[ek]=true;
- }
-
- }
- }
- }
- Vector<Vector3> lines;
-
- for(Map<_EdgeKey,bool>::Element *E=edge_map.front();E;E=E->next()) {
-
- if (E->get()) {
- lines.push_back(E->key().from);
- lines.push_back(E->key().to);
- }
- }
-
- Ref<TriangleMesh> tmesh = memnew( TriangleMesh);
- tmesh->create(tmeshfaces);
-
- if (lines.size())
- add_lines(lines,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_edge_material:SpatialEditorGizmos::singleton->navmesh_edge_material_disabled);
- add_collision_triangles(tmesh);
- Ref<Mesh> m = memnew( Mesh );
- Array a;
- a.resize(Mesh::ARRAY_MAX);
- a[0]=tmeshfaces;
- m->add_surface(Mesh::PRIMITIVE_TRIANGLES,a);
- m->surface_set_material(0,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_solid_material:SpatialEditorGizmos::singleton->navmesh_solid_material_disabled);
- add_mesh(m);
- add_collision_segments(lines);
-
-}
-
-NavigationMeshSpatialGizmo::NavigationMeshSpatialGizmo(NavigationMeshInstance *p_navmesh){
-
- set_spatial_node(p_navmesh);
- navmesh=p_navmesh;
-}
-
-//////
-///
-///
-
-
-
-void PinJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs));
- cursor_points.push_back(Vector3(0,0,-cs));
- add_collision_segments(cursor_points);
- add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-PinJointSpatialGizmo::PinJointSpatialGizmo(PinJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-////
-
-void HingeJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));*/
- cursor_points.push_back(Vector3(0,0,+cs*2));
- cursor_points.push_back(Vector3(0,0,-cs*2));
-
- float ll = p3d->get_param(HingeJoint::PARAM_LIMIT_LOWER);
- float ul = p3d->get_param(HingeJoint::PARAM_LIMIT_UPPER);
-
- if (p3d->get_flag(HingeJoint::FLAG_USE_LIMIT) && ll<ul) {
-
- const int points = 32;
- float step = (ul-ll)/points;
-
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(ul-ll)/points;
- float n = ll+(i+1)*(ul-ll)/points;
-
- Vector3 from=Vector3( -Math::sin(s),Math::cos(s), 0 )*cs;
- Vector3 to=Vector3( -Math::sin(n),Math::cos(n), 0 )*cs;
-
- if (i==points-1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i==0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
-
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
-
- }
-
- cursor_points.push_back(Vector3(0,cs*1.5,0));
- cursor_points.push_back(Vector3());
-
- } else {
-
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(Math_PI*2.0)/points;
- float n = ll+(i+1)*(Math_PI*2.0)/points;
-
- Vector3 from=Vector3( -Math::sin(s),Math::cos(s), 0 )*cs;
- Vector3 to=Vector3( -Math::sin(n),Math::cos(n), 0 )*cs;
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
- }
-
- }
- add_collision_segments(cursor_points);
- add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-///////
-///
-////
-
-void SliderJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));*/
- cursor_points.push_back(Vector3(0,0,+cs*2));
- cursor_points.push_back(Vector3(0,0,-cs*2));
-
- float ll = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER);
- float ul = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER);
- float lll = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER);
- float lul = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER);
-
- if (lll>lul) {
-
- cursor_points.push_back(Vector3(lul,0,0));
- cursor_points.push_back(Vector3(lll,0,0));
-
- cursor_points.push_back(Vector3(lul,-cs,-cs));
- cursor_points.push_back(Vector3(lul,-cs,cs));
- cursor_points.push_back(Vector3(lul,-cs,cs));
- cursor_points.push_back(Vector3(lul,cs,cs));
- cursor_points.push_back(Vector3(lul,cs,cs));
- cursor_points.push_back(Vector3(lul,cs,-cs));
- cursor_points.push_back(Vector3(lul,cs,-cs));
- cursor_points.push_back(Vector3(lul,-cs,-cs));
-
-
- cursor_points.push_back(Vector3(lll,-cs,-cs));
- cursor_points.push_back(Vector3(lll,-cs,cs));
- cursor_points.push_back(Vector3(lll,-cs,cs));
- cursor_points.push_back(Vector3(lll,cs,cs));
- cursor_points.push_back(Vector3(lll,cs,cs));
- cursor_points.push_back(Vector3(lll,cs,-cs));
- cursor_points.push_back(Vector3(lll,cs,-cs));
- cursor_points.push_back(Vector3(lll,-cs,-cs));
-
-
- } else {
-
- cursor_points.push_back(Vector3(+cs*2,0,0));
- cursor_points.push_back(Vector3(-cs*2,0,0));
-
- }
-
- if (ll<ul) {
-
- const int points = 32;
- float step = (ul-ll)/points;
-
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(ul-ll)/points;
- float n = ll+(i+1)*(ul-ll)/points;
-
- Vector3 from=Vector3(0, Math::cos(s), -Math::sin(s) )*cs;
- Vector3 to=Vector3(0,Math::cos(n), -Math::sin(n) )*cs;
-
- if (i==points-1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i==0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
-
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
-
- }
-
- cursor_points.push_back(Vector3(0,cs*1.5,0));
- cursor_points.push_back(Vector3());
-
- } else {
-
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(Math_PI*2.0)/points;
- float n = ll+(i+1)*(Math_PI*2.0)/points;
-
- Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs;
- Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs;
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
- }
-
- }
- add_collision_segments(cursor_points);
- add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-///////
-///
-////
-
-void ConeTwistJointSpatialGizmo::redraw() {
-
- clear();
- float cs = 0.25;
- Vector<Vector3> points;
-
- float r = 1.0;
- float w = r*Math::sin(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
- float d = r*Math::cos(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
-
-
- //swing
- for(int i=0;i<360;i+=10) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+10);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
-
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
- points.push_back(Vector3(d,a.x,a.y));
- points.push_back(Vector3(d,b.x,b.y));
-
- if (i%90==0) {
-
- points.push_back(Vector3(d,a.x,a.y));
- points.push_back(Vector3());
-
- }
- }
-
- points.push_back(Vector3());
- points.push_back(Vector3(1,0,0));
-
- //twist
- /*
- */
- float ts=Math::rad2deg(p3d->get_param(ConeTwistJoint::PARAM_TWIST_SPAN));
- ts=MIN(ts,720);
-
-
- for(int i=0;i<int(ts);i+=5) {
-
- float ra=Math::deg2rad(i);
- float rb=Math::deg2rad(i+5);
- float c = i/720.0;
- float cn = (i+5)/720.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w*c;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w*cn;
-
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
-
- points.push_back(Vector3(c,a.x,a.y));
- points.push_back(Vector3(cn,b.x,b.y));
-
- }
-
-
- add_collision_segments(points);
- add_lines(points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-////////
-/// \brief SpatialEditorGizmos::singleton
-///
-///////
-///
-////
-
-void Generic6DOFJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
-
- for(int ax=0;ax<3;ax++) {
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs*2));
- cursor_points.push_back(Vector3(0,0,-cs*2)); */
-
- float ll;
- float ul;
- float lll;
- float lul;
-
- int a1,a2,a3;
- bool enable_ang;
- bool enable_lin;
-
- switch(ax) {
- case 0:
- ll = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
- a1=0;
- a2=1;
- a3=2;
- break;
- case 1:
- ll = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
- a1=2;
- a2=0;
- a3=1;
- break;
- case 2:
- ll = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
-
- a1=1;
- a2=2;
- a3=0;
- break;
- }
-
-#define ADD_VTX(x,y,z)\
- {\
- Vector3 v;\
- v[a1]=(x);\
- v[a2]=(y);\
- v[a3]=(z);\
- cursor_points.push_back(v);\
- }
-
-#define SET_VTX(what,x,y,z)\
- {\
- Vector3 v;\
- v[a1]=(x);\
- v[a2]=(y);\
- v[a3]=(z);\
- what=v;\
- }
-
-
-
-
- if (enable_lin && lll>=lul) {
-
- ADD_VTX(lul,0,0);
- ADD_VTX(lll,0,0);
-
- ADD_VTX(lul,-cs,-cs);
- ADD_VTX(lul,-cs,cs);
- ADD_VTX(lul,-cs,cs);
- ADD_VTX(lul,cs,cs);
- ADD_VTX(lul,cs,cs);
- ADD_VTX(lul,cs,-cs);
- ADD_VTX(lul,cs,-cs);
- ADD_VTX(lul,-cs,-cs);
-
-
- ADD_VTX(lll,-cs,-cs);
- ADD_VTX(lll,-cs,cs);
- ADD_VTX(lll,-cs,cs);
- ADD_VTX(lll,cs,cs);
- ADD_VTX(lll,cs,cs);
- ADD_VTX(lll,cs,-cs);
- ADD_VTX(lll,cs,-cs);
- ADD_VTX(lll,-cs,-cs);
-
-
- } else {
-
- ADD_VTX(+cs*2,0,0);
- ADD_VTX(-cs*2,0,0);
-
- }
-
- if (enable_ang && ll<=ul) {
-
- const int points = 32;
- float step = (ul-ll)/points;
-
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(ul-ll)/points;
- float n = ll+(i+1)*(ul-ll)/points;
-
- Vector3 from;
- SET_VTX(from,0, Math::cos(s), -Math::sin(s) );
- from*=cs;
- Vector3 to;
- SET_VTX(to,0,Math::cos(n), -Math::sin(n));
- to*=cs;
-
- if (i==points-1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i==0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
-
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
-
- }
-
- ADD_VTX(0,cs*1.5,0);
- cursor_points.push_back(Vector3());
-
- } else {
-
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(Math_PI*2.0)/points;
- float n = ll+(i+1)*(Math_PI*2.0)/points;
-
-// Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs;
-// Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs;
-
- Vector3 from;
- SET_VTX(from,0, Math::cos(s), -Math::sin(s) );
- from*=cs;
- Vector3 to;
- SET_VTX(to,0,Math::cos(n), -Math::sin(n));
- to*=cs;
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
- }
-
- }
- }
-
-#undef ADD_VTX
-#undef SET_VTX
-
- add_collision_segments(cursor_points);
- add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-Generic6DOFJointSpatialGizmo::Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-///////
-///
-////
-
-
-SpatialEditorGizmos *SpatialEditorGizmos::singleton=NULL;
-
-Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) {
-
- if (p_spatial->cast_to<Light>()) {
-
- Ref<LightSpatialGizmo> lsg = memnew( LightSpatialGizmo(p_spatial->cast_to<Light>()) );
- return lsg;
- }
-
- if (p_spatial->cast_to<Camera>()) {
-
- Ref<CameraSpatialGizmo> lsg = memnew( CameraSpatialGizmo(p_spatial->cast_to<Camera>()) );
- return lsg;
- }
-
- if (p_spatial->cast_to<Skeleton>()) {
-
- Ref<SkeletonSpatialGizmo> lsg = memnew( SkeletonSpatialGizmo(p_spatial->cast_to<Skeleton>()) );
- return lsg;
- }
-
-
- if (p_spatial->cast_to<Position3D>()) {
-
- Ref<Position3DSpatialGizmo> lsg = memnew( Position3DSpatialGizmo(p_spatial->cast_to<Position3D>()) );
- return lsg;
- }
-
- if (p_spatial->cast_to<MeshInstance>()) {
-
- Ref<MeshInstanceSpatialGizmo> misg = memnew( MeshInstanceSpatialGizmo(p_spatial->cast_to<MeshInstance>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<Room>()) {
-
- Ref<RoomSpatialGizmo> misg = memnew( RoomSpatialGizmo(p_spatial->cast_to<Room>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<NavigationMeshInstance>()) {
-
- Ref<NavigationMeshSpatialGizmo> misg = memnew( NavigationMeshSpatialGizmo(p_spatial->cast_to<NavigationMeshInstance>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<RayCast>()) {
-
- Ref<RayCastSpatialGizmo> misg = memnew( RayCastSpatialGizmo(p_spatial->cast_to<RayCast>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<Portal>()) {
-
- Ref<PortalSpatialGizmo> misg = memnew( PortalSpatialGizmo(p_spatial->cast_to<Portal>()) );
- return misg;
- }
-
-
- if (p_spatial->cast_to<TestCube>()) {
-
- Ref<TestCubeSpatialGizmo> misg = memnew( TestCubeSpatialGizmo(p_spatial->cast_to<TestCube>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<SpatialPlayer>()) {
-
- Ref<SpatialPlayerSpatialGizmo> misg = memnew( SpatialPlayerSpatialGizmo(p_spatial->cast_to<SpatialPlayer>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<CollisionShape>()) {
-
- Ref<CollisionShapeSpatialGizmo> misg = memnew( CollisionShapeSpatialGizmo(p_spatial->cast_to<CollisionShape>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<VisibilityNotifier>()) {
-
- Ref<VisibilityNotifierGizmo> misg = memnew( VisibilityNotifierGizmo(p_spatial->cast_to<VisibilityNotifier>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<VehicleWheel>()) {
-
- Ref<VehicleWheelSpatialGizmo> misg = memnew( VehicleWheelSpatialGizmo(p_spatial->cast_to<VehicleWheel>()) );
- return misg;
- }
- if (p_spatial->cast_to<PinJoint>()) {
-
- Ref<PinJointSpatialGizmo> misg = memnew( PinJointSpatialGizmo(p_spatial->cast_to<PinJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<HingeJoint>()) {
-
- Ref<HingeJointSpatialGizmo> misg = memnew( HingeJointSpatialGizmo(p_spatial->cast_to<HingeJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<SliderJoint>()) {
-
- Ref<SliderJointSpatialGizmo> misg = memnew( SliderJointSpatialGizmo(p_spatial->cast_to<SliderJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<ConeTwistJoint>()) {
-
- Ref<ConeTwistJointSpatialGizmo> misg = memnew( ConeTwistJointSpatialGizmo(p_spatial->cast_to<ConeTwistJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<Generic6DOFJoint>()) {
-
- Ref<Generic6DOFJointSpatialGizmo> misg = memnew( Generic6DOFJointSpatialGizmo(p_spatial->cast_to<Generic6DOFJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<CollisionPolygon>()) {
-
- Ref<CollisionPolygonSpatialGizmo> misg = memnew( CollisionPolygonSpatialGizmo(p_spatial->cast_to<CollisionPolygon>()) );
- return misg;
- }
-
-
- return Ref<SpatialEditorGizmo>();
-}
-
-
-Ref<FixedMaterial> SpatialEditorGizmos::create_line_material(const Color& p_base_color) {
-
- Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
- line_material->set_flag(Material::FLAG_UNSHADED, true);
- line_material->set_line_width(3.0);
- line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
- line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,p_base_color);
-
- return line_material;
-
-}
-
-Ref<FixedMaterial> SpatialEditorGizmos::create_solid_material(const Color& p_base_color) {
-
- Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
- line_material->set_flag(Material::FLAG_UNSHADED, true);
- line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,p_base_color);
-
- return line_material;
-
-}
-
-SpatialEditorGizmos::SpatialEditorGizmos() {
-
- singleton=this;
-
- handle_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
- handle_material->set_flag(Material::FLAG_UNSHADED, true);
- handle_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(0.8,0.8,0.8));
-
- handle2_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
- handle2_material->set_flag(Material::FLAG_UNSHADED, true);
- handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_POINT_SIZE, true);
- handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle","EditorIcons");
- handle2_material->set_point_size(handle_t->get_width());
- handle2_material->set_texture(FixedMaterial::PARAM_DIFFUSE,handle_t);
- handle2_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1));
- handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
-
- light_material = create_line_material(Color(1,1,0.2));
-
- light_material_omni_icon = Ref<FixedMaterial>( memnew( FixedMaterial ));
- light_material_omni_icon->set_flag(Material::FLAG_UNSHADED, true);
- light_material_omni_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
- light_material_omni_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- light_material_omni_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- light_material_omni_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9));
- light_material_omni_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("GizmoLight","EditorIcons"));
-
-
- light_material_directional_icon = Ref<FixedMaterial>( memnew( FixedMaterial ));
- light_material_directional_icon->set_flag(Material::FLAG_UNSHADED, true);
- light_material_directional_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
- light_material_directional_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- light_material_directional_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- light_material_directional_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9));
- light_material_directional_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight","EditorIcons"));
-
- camera_material = create_line_material(Color(1.0,0.5,1.0));
-
-
- navmesh_edge_material = create_line_material(Color(0.1,0.8,1.0));
- navmesh_solid_material = create_solid_material(Color(0.1,0.8,1.0,0.4));
- navmesh_edge_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, false);
- navmesh_solid_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
-
- navmesh_edge_material_disabled = create_line_material(Color(1.0,0.8,0.1));
- navmesh_solid_material_disabled = create_solid_material(Color(1.0,0.8,0.1,0.4));
- navmesh_edge_material_disabled->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, false);
- navmesh_solid_material_disabled->set_flag(Material::FLAG_DOUBLE_SIDED,true);
-
- skeleton_material = create_line_material(Color(0.6,1.0,0.3));
- skeleton_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- skeleton_material->set_flag(Material::FLAG_UNSHADED,true);
- skeleton_material->set_flag(Material::FLAG_ONTOP,true);
- skeleton_material->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
-
- //position 3D Shared mesh
-
- pos3d_mesh = Ref<Mesh>( memnew( Mesh ) );
- {
-
- DVector<Vector3> cursor_points;
- DVector<Color> cursor_colors;
- float cs = 0.25;
- cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs));
- cursor_points.push_back(Vector3(0,0,-cs));
- cursor_colors.push_back(Color(1,0.5,0.5,0.7));
- cursor_colors.push_back(Color(1,0.5,0.5,0.7));
- cursor_colors.push_back(Color(0.5,1,0.5,0.7));
- cursor_colors.push_back(Color(0.5,1,0.5,0.7));
- cursor_colors.push_back(Color(0.5,0.5,1,0.7));
- cursor_colors.push_back(Color(0.5,0.5,1,0.7));
-
- Ref<FixedMaterial> mat = memnew( FixedMaterial );
- mat->set_flag(Material::FLAG_UNSHADED,true);
- mat->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true);
- mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
- mat->set_line_width(3);
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[Mesh::ARRAY_VERTEX]=cursor_points;
- d[Mesh::ARRAY_COLOR]=cursor_colors;
- pos3d_mesh->add_surface(Mesh::PRIMITIVE_LINES,d);
- pos3d_mesh->surface_set_material(0,mat);
- }
-
-
- sample_player_icon = Ref<FixedMaterial>( memnew( FixedMaterial ));
- sample_player_icon->set_flag(Material::FLAG_UNSHADED, true);
- sample_player_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
- sample_player_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- sample_player_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- sample_player_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9));
- sample_player_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer","EditorIcons"));
-
- room_material = create_line_material(Color(1.0,0.6,0.9));
- portal_material = create_line_material(Color(1.0,0.8,0.6));
- raycast_material = create_line_material(Color(1.0,0.8,0.6));
- car_wheel_material = create_line_material(Color(0.6,0.8,1.0));
- visibility_notifier_material = create_line_material(Color(1.0,0.5,1.0));
- joint_material = create_line_material(Color(0.6,0.8,1.0));
-
- stream_player_icon = Ref<FixedMaterial>( memnew( FixedMaterial ));
- stream_player_icon->set_flag(Material::FLAG_UNSHADED, true);
- stream_player_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
- stream_player_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- stream_player_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- stream_player_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9));
- stream_player_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer","EditorIcons"));
-
- visibility_notifier_icon = Ref<FixedMaterial>( memnew( FixedMaterial ));
- visibility_notifier_icon->set_flag(Material::FLAG_UNSHADED, true);
- visibility_notifier_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
- visibility_notifier_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- visibility_notifier_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- visibility_notifier_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9));
- visibility_notifier_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("Visible","EditorIcons"));
-
- {
-
- DVector<Vector3> vertices;
-
-#undef ADD_VTX
-#define ADD_VTX(m_idx);\
- vertices.push_back( face_points[m_idx] );
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- }
- //tri 1
- ADD_VTX(0);
- ADD_VTX(1);
- ADD_VTX(2);
- //tri 2
- ADD_VTX(2);
- ADD_VTX(3);
- ADD_VTX(0);
-
- }
-
- test_cube_tm = Ref<TriangleMesh>( memnew( TriangleMesh ) );
- test_cube_tm->create(vertices);
- }
-
- shape_material = create_line_material(Color(0.2,1,1.0));
-
-
-}
-
+/*************************************************************************/ +/* spatial_editor_gizmos.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "spatial_editor_gizmos.h" +#include "geometry.h" +#include "scene/3d/camera.h" +#include "scene/resources/surface_tool.h" +#include "scene/resources/sphere_shape.h" +#include "scene/resources/box_shape.h" +#include "scene/resources/capsule_shape.h" +#include "scene/resources/ray_shape.h" +#include "scene/resources/convex_polygon_shape.h" +#include "scene/resources/plane_shape.h" +#include "quick_hull.h" + +// Keep small children away from this file. +// It's so ugly it will eat them alive + +#define HANDLE_HALF_SIZE 0.05 + +void SpatialGizmoTool::clear() { + + for(int i=0;i<instances.size();i++) { + + if (instances[i].instance.is_valid()) + VS::get_singleton()->free(instances[i].instance); + + + } + + billboard_handle=false; + collision_segments.clear(); + collision_mesh=Ref<TriangleMesh>(); + instances.clear(); + handles.clear(); + secondary_handles.clear(); +} + +void SpatialGizmoTool::Instance::create_instance(Spatial *p_base) { + + instance = VS::get_singleton()->instance_create2(mesh->get_rid(),p_base->get_world()->get_scenario()); + VS::get_singleton()->instance_attach_object_instance_ID(instance,p_base->get_instance_ID()); + if (billboard) + VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_BILLBOARD,true); + if (unscaled) + VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_DEPH_SCALE,true); + if (skeleton.is_valid()) + VS::get_singleton()->instance_attach_skeleton(instance,skeleton); + if (extra_margin) + VS::get_singleton()->instance_set_extra_visibility_margin(instance,1); + VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_CAST_SHADOW,false); + VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_RECEIVE_SHADOWS,false); + VS::get_singleton()->instance_set_layer_mask(instance,1<<SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26 +} + + + +void SpatialGizmoTool::add_mesh(const Ref<Mesh>& p_mesh,bool p_billboard, const RID &p_skeleton) { + + ERR_FAIL_COND(!spatial_node); + Instance ins; + + ins.billboard=p_billboard; + ins.mesh=p_mesh; + ins.skeleton=p_skeleton; + if (valid) { + ins.create_instance(spatial_node); + VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform()); + } + + instances.push_back(ins); + +} + +void SpatialGizmoTool::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material,bool p_billboard){ + + ERR_FAIL_COND(!spatial_node); + Instance ins; + + Ref<Mesh> mesh = memnew( Mesh ); + Array a; + a.resize(Mesh::ARRAY_MAX); + + a[Mesh::ARRAY_VERTEX]=p_lines; + + DVector<Color> color; + color.resize(p_lines.size()); + { + DVector<Color>::Write w = color.write(); + for(int i=0;i<p_lines.size();i++) { + if (is_selected()) + w[i]=Color(1,1,1,0.6); + else + w[i]=Color(1,1,1,0.25); + } + + } + + a[Mesh::ARRAY_COLOR]=color; + + + mesh->add_surface(Mesh::PRIMITIVE_LINES,a); + mesh->surface_set_material(0,p_material); + + if (p_billboard) { + float md=0; + for(int i=0;i<p_lines.size();i++) { + + md=MAX(0,p_lines[i].length()); + + } + if (md) { + mesh->set_custom_aabb(AABB(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0)); + } + } + + ins.billboard=p_billboard; + ins.mesh=mesh; + if (valid) { + ins.create_instance(spatial_node); + VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform()); + } + + instances.push_back(ins); + +} + +void SpatialGizmoTool::add_unscaled_billboard(const Ref<Material>& p_material,float p_scale) { + + ERR_FAIL_COND(!spatial_node); + Instance ins; + + Vector<Vector3 > vs; + Vector<Vector2 > uv; + + vs.push_back(Vector3(-p_scale,p_scale,0)); + vs.push_back(Vector3(p_scale,p_scale,0)); + vs.push_back(Vector3(p_scale,-p_scale,0)); + vs.push_back(Vector3(-p_scale,-p_scale,0)); + + uv.push_back(Vector2(1,0)); + uv.push_back(Vector2(0,0)); + uv.push_back(Vector2(0,1)); + uv.push_back(Vector2(1,1)); + + Ref<Mesh> mesh = memnew( Mesh ); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX]=vs; + a[Mesh::ARRAY_TEX_UV]=uv; + mesh->add_surface(Mesh::PRIMITIVE_TRIANGLE_FAN,a); + mesh->surface_set_material(0,p_material); + + if (true) { + float md=0; + for(int i=0;i<vs.size();i++) { + + md=MAX(0,vs[i].length()); + + } + if (md) { + mesh->set_custom_aabb(AABB(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0)); + } + } + + ins.mesh=mesh; + ins.unscaled=true; + ins.billboard=true; + if (valid) { + ins.create_instance(spatial_node); + VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform()); + } + + instances.push_back(ins); + + +} + +void SpatialGizmoTool::add_collision_triangles(const Ref<TriangleMesh>& p_tmesh) { + + collision_mesh=p_tmesh; +} + +void SpatialGizmoTool::add_collision_segments(const Vector<Vector3> &p_lines) { + + int from=collision_segments.size(); + collision_segments.resize(from+p_lines.size()); + for(int i=0;i<p_lines.size();i++) { + + collision_segments[from+i]=p_lines[i]; + } +} + + +void SpatialGizmoTool::add_handles(const Vector<Vector3> &p_handles, bool p_billboard,bool p_secondary){ + + billboard_handle=p_billboard; + + if (!is_selected()) + return; + + ERR_FAIL_COND(!spatial_node); + + ERR_FAIL_COND(!spatial_node); + Instance ins; + + + Ref<Mesh> mesh = memnew( Mesh ); +#if 1 + + Array a; + a.resize(VS::ARRAY_MAX); + a[VS::ARRAY_VERTEX]=p_handles; + DVector<Color> colors; + { + colors.resize(p_handles.size()); + DVector<Color>::Write w=colors.write(); + for(int i=0;i<p_handles.size();i++) { + + Color col(1,1,1,1); + if (SpatialEditor::get_singleton()->get_over_gizmo_handle()!=i) + col=Color(0.9,0.9,0.9,0.9); + w[i]=col; + } + + } + a[VS::ARRAY_COLOR]=colors; + mesh->add_surface(Mesh::PRIMITIVE_POINTS,a); + mesh->surface_set_material(0,SpatialEditorGizmos::singleton->handle2_material); + + if (p_billboard) { + float md=0; + for(int i=0;i<p_handles.size();i++) { + + md=MAX(0,p_handles[i].length()); + + } + if (md) { + mesh->set_custom_aabb(AABB(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0)); + } + } + + + +#else + for(int ih=0;ih<p_handles.size();ih++) { + + + Vector<Vector3> vertices; + Vector<Vector3> normals; + + int vtx_idx=0; +#define ADD_VTX(m_idx);\ + vertices.push_back( (face_points[m_idx]*HANDLE_HALF_SIZE+p_handles[ih]) );\ + normals.push_back( normal_points[m_idx] );\ + vtx_idx++;\ + + for (int i=0;i<6;i++) { + + + Vector3 face_points[4]; + Vector3 normal_points[4]; + float uv_points[8]={0,0,0,1,1,1,1,0}; + + for (int j=0;j<4;j++) { + + float v[3]; + v[0]=1.0; + v[1]=1-2*((j>>1)&1); + v[2]=v[1]*(1-2*(j&1)); + + for (int k=0;k<3;k++) { + + if (i<3) + face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); + else + face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); + } + normal_points[j]=Vector3(); + normal_points[j][i%3]=(i>=3?-1:1); + } + //tri 1 + ADD_VTX(0); + ADD_VTX(1); + ADD_VTX(2); + //tri 2 + ADD_VTX(2); + ADD_VTX(3); + ADD_VTX(0); + + } + + + Array d; + d.resize(VS::ARRAY_MAX); + d[VisualServer::ARRAY_NORMAL]= normals ; + d[VisualServer::ARRAY_VERTEX]= vertices ; + + mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d); + mesh->surface_set_material(ih,SpatialEditorGizmos::singleton->handle_material); + + + } +#endif + ins.mesh=mesh; + ins.billboard=p_billboard; + ins.extra_margin=true; + if (valid) { + ins.create_instance(spatial_node); + VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform()); + } + instances.push_back(ins); + if (!p_secondary) { + int chs=handles.size(); + handles.resize(chs+p_handles.size()); + for(int i=0;i<p_handles.size();i++) { + handles[i+chs]=p_handles[i]; + } + } else { + + int chs=secondary_handles.size(); + secondary_handles.resize(chs+p_handles.size()); + for(int i=0;i<p_handles.size();i++) { + secondary_handles[i+chs]=p_handles[i]; + } + + } + +} + + +void SpatialGizmoTool::set_spatial_node(Spatial *p_node){ + + spatial_node=p_node; + +} + +bool SpatialGizmoTool::intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum) { + + ERR_FAIL_COND_V(!spatial_node,false); + ERR_FAIL_COND_V(!valid,false); + + if (collision_segments.size()) { + + const Plane *p=p_frustum.ptr(); + int fc=p_frustum.size(); + + int vc=collision_segments.size(); + const Vector3* vptr=collision_segments.ptr(); + Transform t = spatial_node->get_global_transform(); + + for(int i=0;i<vc/2;i++) { + + + Vector3 a=t.xform(vptr[i*2+0]); + Vector3 b=t.xform(vptr[i*2+1]); + + bool any_out=false; + for(int j=0;j<fc;j++) { + + if (p[j].distance_to(a) > 0 && p[j].distance_to(b) >0) { + + any_out=true; + break; + } + } + + if (!any_out) + return true; + } + + return false; + } + + return false; +} + + +bool SpatialGizmoTool::intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle,bool p_sec_first) { + + ERR_FAIL_COND_V(!spatial_node,false); + ERR_FAIL_COND_V(!valid,false); + + if (r_gizmo_handle) { + + Transform t = spatial_node->get_global_transform(); + t.orthonormalize(); + if (billboard_handle) { + t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1)); + } + Transform ti=t.affine_inverse(); + + Vector3 ray_from=ti.xform(p_camera->project_ray_origin(p_point)); + Vector3 ray_dir=t.basis.xform_inv(p_camera->project_ray_normal(p_point)).normalized(); + Vector3 ray_to = ray_from+ray_dir*4096; + + float min_d=1e20; + int idx=-1; + + for(int i=0;i<secondary_handles.size();i++) { +#if 1 + + + Vector3 hpos = t.xform(secondary_handles[i]); + Vector2 p = p_camera->unproject_position(hpos); + if (p.distance_to(p_point)<SpatialEditorGizmos::singleton->handle_t->get_width()*0.6) { + + + real_t dp = p_camera->get_transform().origin.distance_to(hpos); + if (dp<min_d) { + + r_pos=t.xform(hpos); + r_normal=p_camera->get_transform().basis.get_axis(2); + min_d=dp; + idx=i+handles.size(); + + } + + } + +#else + AABB aabb; + aabb.pos=Vector3(-1,-1,-1)*HANDLE_HALF_SIZE; + aabb.size=aabb.pos*-2; + aabb.pos+=secondary_handles[i]; + + + Vector3 rpos,rnorm; + + if (aabb.intersects_segment(ray_from,ray_to,&rpos,&rnorm)) { + + real_t dp = ray_dir.dot(rpos); + if (dp<min_d) { + + r_pos=t.xform(rpos); + r_normal=ti.basis.xform_inv(rnorm).normalized(); + min_d=dp; + idx=i+handles.size(); + + } + } +#endif + } + + if (p_sec_first && idx!=-1) { + + *r_gizmo_handle=idx; + return true; + } + + min_d=1e20; + + for(int i=0;i<handles.size();i++) { + +#if 1 + + + Vector3 hpos = t.xform(handles[i]); + Vector2 p = p_camera->unproject_position(hpos); + if (p.distance_to(p_point)<SpatialEditorGizmos::singleton->handle_t->get_width()*0.6) { + + + real_t dp = p_camera->get_transform().origin.distance_to(hpos); + if (dp<min_d) { + + r_pos=t.xform(hpos); + r_normal=p_camera->get_transform().basis.get_axis(2); + min_d=dp; + idx=i; + + } + + } + +#else + + AABB aabb; + aabb.pos=Vector3(-1,-1,-1)*HANDLE_HALF_SIZE; + aabb.size=aabb.pos*-2; + aabb.pos+=handles[i]; + + + Vector3 rpos,rnorm; + + if (aabb.intersects_segment(ray_from,ray_to,&rpos,&rnorm)) { + + real_t dp = ray_dir.dot(rpos); + if (dp<min_d) { + + r_pos=t.xform(rpos); + r_normal=ti.basis.xform_inv(rnorm).normalized(); + min_d=dp; + idx=i; + + } + } +#endif + } + + if (idx>=0) { + *r_gizmo_handle=idx; + return true; + } + + + } + + if (collision_segments.size()) { + + Plane camp(p_camera->get_transform().origin,(-p_camera->get_transform().basis.get_axis(2)).normalized()); + + int vc=collision_segments.size(); + const Vector3* vptr=collision_segments.ptr(); + Transform t = spatial_node->get_global_transform(); + if (billboard_handle) { + t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1)); + } + + Vector3 cp; + float cpd=1e20; + + for(int i=0;i<vc/2;i++) { + + + Vector3 a=t.xform(vptr[i*2+0]); + Vector3 b=t.xform(vptr[i*2+1]); + Vector2 s[2]; + s[0] = p_camera->unproject_position(a); + s[1] = p_camera->unproject_position(b); + + + Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point,s); + + float pd = p.distance_to(p_point); + + if (pd<cpd) { + + + float d = s[0].distance_to(s[1]); + Vector3 tcp; + if (d>0) { + + float d2=s[0].distance_to(p)/d; + tcp = a+(b-a)*d2; + + } else { + tcp=a; + + } + + if (camp.distance_to(tcp)<p_camera->get_znear()) + continue; + cp=tcp; + cpd=pd; + } + } + + if (cpd<8) { + + r_pos=cp; + r_normal=-p_camera->project_ray_normal(p_point); + return true; + } + + return false; + } + + + if (collision_mesh.is_valid()) { + Transform gt = spatial_node->get_global_transform(); + + if (billboard_handle) { + gt.set_look_at(gt.origin,gt.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1)); + } + + Transform ai=gt.affine_inverse(); + Vector3 ray_from = ai.xform(p_camera->project_ray_origin(p_point)); + Vector3 ray_dir=ai.basis.xform(p_camera->project_ray_normal(p_point)).normalized(); + Vector3 rpos,rnorm; + +#if 1 + + + + if (collision_mesh->intersect_ray(ray_from,ray_dir,rpos,rnorm)) { + + r_pos=gt.xform(rpos); + r_normal=gt.basis.xform(rnorm).normalized(); + return true; + } +#else + + if (collision_mesh->intersect_segment(ray_from,ray_from+ray_dir*4906.0,rpos,rnorm)) { + + r_pos=gt.xform(rpos); + r_normal=gt.basis.xform(rnorm).normalized(); + return true; + } + +#endif + } + + return false; + +} + + + +void SpatialGizmoTool::create() { + + ERR_FAIL_COND(!spatial_node); + ERR_FAIL_COND(valid); + valid=true; + + for(int i=0;i<instances.size();i++) { + + instances[i].create_instance(spatial_node); + } + + transform(); + +} + +void SpatialGizmoTool::transform(){ + + ERR_FAIL_COND(!spatial_node); + ERR_FAIL_COND(!valid); + for(int i=0;i<instances.size();i++) { + VS::get_singleton()->instance_set_transform(instances[i].instance,spatial_node->get_global_transform()); + } + +} + + +void SpatialGizmoTool::free(){ + + ERR_FAIL_COND(!spatial_node); + ERR_FAIL_COND(!valid); + + for(int i=0;i<instances.size();i++) { + + if (instances[i].instance.is_valid()) + VS::get_singleton()->free(instances[i].instance); + instances[i].instance=RID(); + } + + valid=false; + + +} + + + +SpatialGizmoTool::SpatialGizmoTool() { + valid=false; + billboard_handle=false; + +} + +SpatialGizmoTool::~SpatialGizmoTool(){ + + clear(); +} + +Vector3 SpatialGizmoTool::get_handle_pos(int p_idx) const { + + ERR_FAIL_INDEX_V(p_idx,handles.size(),Vector3()); + + return handles[p_idx]; + +} + +//// light gizmo + + +String LightSpatialGizmo::get_handle_name(int p_idx) const { + + if (p_idx==0) + return "Radius"; + else + return "Aperture"; +} + + +Variant LightSpatialGizmo::get_handle_value(int p_idx) const{ + + if (p_idx==0) + return light->get_parameter(Light::PARAM_RADIUS); + if (p_idx==1) + return light->get_parameter(Light::PARAM_SPOT_ANGLE); + + return Variant(); +} + + +static float _find_closest_angle_to_half_pi_arc(const Vector3& p_from, const Vector3& p_to, float p_arc_radius,const Transform& p_arc_xform) { + + //bleh, discrete is simpler + static const int arc_test_points=64; + float min_d = 1e20; + Vector3 min_p; + + + for(int i=0;i<arc_test_points;i++) { + + float a = i*Math_PI*0.5/arc_test_points; + float an = (i+1)*Math_PI*0.5/arc_test_points; + Vector3 p=Vector3( Math::cos(a), 0, -Math::sin(a) )*p_arc_radius; + Vector3 n=Vector3( Math::cos(an), 0,- Math::sin(an) )*p_arc_radius; + + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(p,n,p_from,p_to,ra,rb); + + float d = ra.distance_to(rb); + if (d<min_d) { + min_d=d; + min_p=ra; + } + + } + + //min_p = p_arc_xform.affine_inverse().xform(min_p); + float a = Vector2(min_p.x,-min_p.z).atan2(); + return a*180.0/Math_PI; +} + + +void LightSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point) { + + Transform gt = light->get_global_transform(); + gt.orthonormalize(); + Transform gi = gt.affine_inverse(); + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 s[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)}; + if (p_idx==0) { + + if (light->cast_to<SpotLight>()) { + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,-4096),s[0],s[1],ra,rb); + + float d = -ra.z; + if (d<0) + d=0; + + light->set_parameter(Light::PARAM_RADIUS,d); + } else if (light->cast_to<OmniLight>()) { + + Plane cp=Plane( gt.origin, p_camera->get_transform().basis.get_axis(2)); + + Vector3 inters; + if (cp.intersects_ray(ray_from,ray_dir,&inters)) { + + float r = inters.distance_to(gt.origin); + light->set_parameter(Light::PARAM_RADIUS,r); + } + + } + + } else if (p_idx==1) { + + float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],light->get_parameter(Light::PARAM_RADIUS),gt); + light->set_parameter(Light::PARAM_SPOT_ANGLE,CLAMP(a,0.01,89.99)); + } +} + +void LightSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){ + + if (p_cancel) { + + light->set_parameter(p_idx==0?Light::PARAM_RADIUS:Light::PARAM_SPOT_ANGLE,p_restore); + + } else if (p_idx==0) { + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action("Change Light Radius"); + ur->add_do_method(light,"set_parameter",Light::PARAM_RADIUS,light->get_parameter(Light::PARAM_RADIUS)); + ur->add_undo_method(light,"set_parameter",Light::PARAM_RADIUS,p_restore); + ur->commit_action(); + } else if (p_idx==1) { + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action("Change Light Radius"); + ur->add_do_method(light,"set_parameter",Light::PARAM_SPOT_ANGLE,light->get_parameter(Light::PARAM_SPOT_ANGLE)); + ur->add_undo_method(light,"set_parameter",Light::PARAM_SPOT_ANGLE,p_restore); + ur->commit_action(); + + } +} + + + +void LightSpatialGizmo::redraw() { + + + if (light->cast_to<DirectionalLight>()) { + + + + const int arrow_points=5; + Vector3 arrow[arrow_points]={ + Vector3(0,0,2), + Vector3(1,1,2), + Vector3(1,1,-1), + Vector3(2,2,-1), + Vector3(0,0,-3) + }; + + int arrow_sides=4; + + Vector<Vector3> lines; + + + for(int i = 0; i < arrow_sides ; i++) { + + + Matrix3 ma(Vector3(0,0,1),Math_PI*2*float(i)/arrow_sides); + Matrix3 mb(Vector3(0,0,1),Math_PI*2*float(i+1)/arrow_sides); + + + for(int j=1;j<arrow_points-1;j++) { + + if (j!=2) { + lines.push_back(ma.xform(arrow[j])); + lines.push_back(ma.xform(arrow[j+1])); + } + if (j<arrow_points-1) { + lines.push_back(ma.xform(arrow[j])); + lines.push_back(mb.xform(arrow[j])); + } + + } + } + + add_lines(lines,SpatialEditorGizmos::singleton->light_material); + add_collision_segments(lines); + add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_directional_icon,0.05); + + } + + if (light->cast_to<OmniLight>()) { + + clear(); + + + OmniLight *on = light->cast_to<OmniLight>(); + + float r = on->get_parameter(Light::PARAM_RADIUS); + + Vector<Vector3> points; + + for(int i=0;i<=360;i++) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+1); + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r; + + /*points.push_back(Vector3(a.x,0,a.y)); + points.push_back(Vector3(b.x,0,b.y)); + points.push_back(Vector3(0,a.x,a.y)); + points.push_back(Vector3(0,b.x,b.y));*/ + points.push_back(Vector3(a.x,a.y,0)); + points.push_back(Vector3(b.x,b.y,0)); + + } + + add_lines(points,SpatialEditorGizmos::singleton->light_material,true); + add_collision_segments(points); + + add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon,0.05); + + Vector<Vector3> handles; + handles.push_back(Vector3(r,0,0)); + add_handles(handles,true); + + + } + + + if (light->cast_to<SpotLight>()) { + + clear(); + + Vector<Vector3> points; + SpotLight *on = light->cast_to<SpotLight>(); + + float r = on->get_parameter(Light::PARAM_RADIUS); + float w = r*Math::sin(Math::deg2rad(on->get_parameter(Light::PARAM_SPOT_ANGLE))); + float d = r*Math::cos(Math::deg2rad(on->get_parameter(Light::PARAM_SPOT_ANGLE))); + + + + for(int i=0;i<360;i++) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+1); + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w; + + /*points.push_back(Vector3(a.x,0,a.y)); + points.push_back(Vector3(b.x,0,b.y)); + points.push_back(Vector3(0,a.x,a.y)); + points.push_back(Vector3(0,b.x,b.y));*/ + points.push_back(Vector3(a.x,a.y,-d)); + points.push_back(Vector3(b.x,b.y,-d)); + + if (i%90==0) { + + points.push_back(Vector3(a.x,a.y,-d)); + points.push_back(Vector3()); + + } + + + } + + points.push_back(Vector3(0,0,-r)); + points.push_back(Vector3()); + + add_lines(points,SpatialEditorGizmos::singleton->light_material); + + Vector<Vector3> handles; + handles.push_back(Vector3(0,0,-r)); + + Vector<Vector3> collision_segments; + + for(int i=0;i<64;i++) { + + float ra=i*Math_PI*2.0/64.0; + float rb=(i+1)*Math_PI*2.0/64.0; + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w; + + collision_segments.push_back(Vector3(a.x,a.y,-d)); + collision_segments.push_back(Vector3(b.x,b.y,-d)); + + if (i%16==0) { + + collision_segments.push_back(Vector3(a.x,a.y,-d)); + collision_segments.push_back(Vector3()); + + } + + if (i==16) { + + handles.push_back(Vector3(a.x,a.y,-d)); + } + + } + + collision_segments.push_back(Vector3(0,0,-r)); + collision_segments.push_back(Vector3()); + + + add_handles(handles); + add_collision_segments(collision_segments); + add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon,0.05); + + } + +} + +LightSpatialGizmo::LightSpatialGizmo(Light* p_light){ + + light=p_light; + set_spatial_node(p_light); + +} + +////// + +String CameraSpatialGizmo::get_handle_name(int p_idx) const { + + if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) { + return "FOV"; + } else { + return "Size"; + } +} +Variant CameraSpatialGizmo::get_handle_value(int p_idx) const{ + + if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) { + return camera->get_fov(); + } else { + + return camera->get_size(); + } +} +void CameraSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){ + + Transform gt = camera->get_global_transform(); + gt.orthonormalize(); + Transform gi = gt.affine_inverse(); + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 s[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)}; + + if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) { + Transform gt=camera->get_global_transform(); + float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],1.0,gt); + camera->set("fov",a); + } else { + + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(Vector3(0,0,-1),Vector3(4096,0,-1),s[0],s[1],ra,rb); + float d = ra.x * 2.0; + if (d<0) + d=0; + + camera->set("size",d); + } + +} +void CameraSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){ + + if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) { + + if (p_cancel) { + + camera->set("fov",p_restore); + } else { + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action("Change Camera FOV"); + ur->add_do_property(camera,"fov",camera->get_fov()); + ur->add_undo_property(camera,"fov",p_restore); + ur->commit_action(); + } + + } else { + + if (p_cancel) { + + camera->set("size",p_restore); + } else { + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action("Change Camera Size"); + ur->add_do_property(camera,"size",camera->get_size()); + ur->add_undo_property(camera,"size",p_restore); + ur->commit_action(); + } + + } + +} + +void CameraSpatialGizmo::redraw(){ + + clear(); + + Vector<Vector3> lines; + Vector<Vector3> handles; + + + switch(camera->get_projection()) { + + case Camera::PROJECTION_PERSPECTIVE: { + + float fov = camera->get_fov(); + + Vector3 side=Vector3( Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov)) ); + Vector3 nside=side; + nside.x=-nside.x; + Vector3 up=Vector3(0,side.x,0); + + +#define ADD_TRIANGLE( m_a, m_b, m_c)\ +{\ + lines.push_back(m_a);\ + lines.push_back(m_b);\ + lines.push_back(m_b);\ + lines.push_back(m_c);\ + lines.push_back(m_c);\ + lines.push_back(m_a);\ +} + + ADD_TRIANGLE( Vector3(), side+up, side-up ); + ADD_TRIANGLE( Vector3(), nside+up, nside-up ); + ADD_TRIANGLE( Vector3(), side+up, nside+up ); + ADD_TRIANGLE( Vector3(), side-up, nside-up ); + + handles.push_back(side); + side.x*=0.25; + nside.x*=0.25; + Vector3 tup( 0, up.y*3/2,side.z); + ADD_TRIANGLE( tup, side+up, nside+up ); + + } break; + case Camera::PROJECTION_ORTHOGONAL: { + +#define ADD_QUAD( m_a, m_b, m_c, m_d)\ +{\ + lines.push_back(m_a);\ + lines.push_back(m_b);\ + lines.push_back(m_b);\ + lines.push_back(m_c);\ + lines.push_back(m_c);\ + lines.push_back(m_d);\ + lines.push_back(m_d);\ + lines.push_back(m_a);\ +} + float size = camera->get_size(); + + float hsize=size*0.5; + Vector3 right(hsize,0,0); + Vector3 up(0,hsize,0); + Vector3 back(0,0,-1.0); + Vector3 front(0,0,0); + + ADD_QUAD( -up-right,-up+right,up+right,up-right); + ADD_QUAD( -up-right+back,-up+right+back,up+right+back,up-right+back); + ADD_QUAD( up+right,up+right+back,up-right+back,up-right); + ADD_QUAD( -up+right,-up+right+back,-up-right+back,-up-right); + handles.push_back(right+back); + + right.x*=0.25; + Vector3 tup( 0, up.y*3/2,back.z ); + ADD_TRIANGLE( tup, right+up+back, -right+up+back ); + + } break; + + } + + add_lines(lines,SpatialEditorGizmos::singleton->camera_material); + add_collision_segments(lines); + add_handles(handles); +} + + +CameraSpatialGizmo::CameraSpatialGizmo(Camera* p_camera){ + + camera=p_camera; + set_spatial_node(camera); +} + + + + +////// + +void MeshInstanceSpatialGizmo::redraw() { + + Ref<Mesh> m = mesh->get_mesh(); + if (!m.is_valid()) + return; //none + + Ref<TriangleMesh> tm = m->generate_triangle_mesh(); + if (tm.is_valid()) + add_collision_triangles(tm); +} + +MeshInstanceSpatialGizmo::MeshInstanceSpatialGizmo(MeshInstance* p_mesh) { + + mesh=p_mesh; + set_spatial_node(p_mesh); +} + +///// + + +void Position3DSpatialGizmo::redraw() { + + clear(); + add_mesh(SpatialEditorGizmos::singleton->pos3d_mesh); + Vector<Vector3> cursor_points; + float cs = 0.25; + cursor_points.push_back(Vector3(+cs,0,0)); + cursor_points.push_back(Vector3(-cs,0,0)); + cursor_points.push_back(Vector3(0,+cs,0)); + cursor_points.push_back(Vector3(0,-cs,0)); + cursor_points.push_back(Vector3(0,0,+cs)); + cursor_points.push_back(Vector3(0,0,-cs)); + add_collision_segments(cursor_points); + +} + + +Position3DSpatialGizmo::Position3DSpatialGizmo(Position3D* p_p3d) { + + p3d=p_p3d; + set_spatial_node(p3d); +} + + +///// + +void SkeletonSpatialGizmo::redraw() { + + clear(); + + Ref<SurfaceTool> surface_tool( memnew( SurfaceTool )); + + + surface_tool->begin(Mesh::PRIMITIVE_LINES); + surface_tool->set_material(SpatialEditorGizmos::singleton->skeleton_material); + Vector<Transform> grests; + grests.resize(skel->get_bone_count()); + + Vector<int> bones; + Vector<float> weights; + bones.resize(4); + weights.resize(4); + + for(int i=0;i<4;i++) { + bones[i]=0; + weights[i]=0; + } + + weights[0]=1; + + + AABB aabb; + + Color bonecolor = Color(1.0,0.4,0.4,0.3); + Color rootcolor = Color(0.4,1.0,0.4,0.1); + + for (int i=0;i<skel->get_bone_count();i++) { + + int parent = skel->get_bone_parent(i); + + if (parent>=0) { + grests[i]=grests[parent] * skel->get_bone_rest(i); + + Vector3 v0 = grests[parent].origin; + Vector3 v1 = grests[i].origin; + Vector3 d = (v1-v0).normalized(); + float dist = v0.distance_to(v1); + + //find closest axis + int closest=-1; + float closest_d = 0.0; + + for(int j=0;j<3;j++) { + float dp = Math::abs(grests[parent].basis[j].normalized().dot(d)); + if (j==0 || dp>closest_d) + closest=j; + } + + //find closest other + Vector3 first; + Vector3 points[4]; + int pointidx=0; + for(int j=0;j<3;j++) { + + bones[0]=parent; + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(rootcolor); + surface_tool->add_vertex(v0-grests[parent].basis[j].normalized()*dist*0.05); + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(rootcolor); + surface_tool->add_vertex(v0+grests[parent].basis[j].normalized()*dist*0.05); + + if (j==closest) + continue; + + Vector3 axis; + if (first==Vector3()) { + axis = d.cross(d.cross(grests[parent].basis[j])).normalized(); + first=axis; + } else { + axis = d.cross(first).normalized(); + } + + for(int k=0;k<2;k++) { + + if (k==1) + axis=-axis; + Vector3 point = v0+d*dist*0.2; + point+=axis*dist*0.1; + + + bones[0]=parent; + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(bonecolor); + surface_tool->add_vertex(v0); + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(bonecolor); + surface_tool->add_vertex(point); + + bones[0]=parent; + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(bonecolor); + surface_tool->add_vertex(point); + bones[0]=i; + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(bonecolor); + surface_tool->add_vertex(v1); + points[pointidx++]=point; + + } + + } + + SWAP( points[1],points[2] ); + for(int j=0;j<4;j++) { + + + bones[0]=parent; + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(bonecolor); + surface_tool->add_vertex(points[j]); + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(bonecolor); + surface_tool->add_vertex(points[(j+1)%4]); + } + + +/* + bones[0]=parent; + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(Color(0.4,1,0.4,0.4)); + surface_tool->add_vertex(v0); + bones[0]=i; + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(Color(0.4,1,0.4,0.4)); + surface_tool->add_vertex(v1); +*/ + } else { + + grests[i]=skel->get_bone_rest(i); + bones[0]=i; + } +/* + Transform t = grests[i]; + t.orthonormalize(); + + for (int i=0;i<6;i++) { + + + Vector3 face_points[4]; + + for (int j=0;j<4;j++) { + + float v[3]; + v[0]=1.0; + v[1]=1-2*((j>>1)&1); + v[2]=v[1]*(1-2*(j&1)); + + for (int k=0;k<3;k++) { + + if (i<3) + face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); + else + face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); + } + } + + for(int j=0;j<4;j++) { + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(Color(1.0,0.4,0.4,0.4)); + surface_tool->add_vertex(t.xform(face_points[j]*0.04)); + surface_tool->add_bones(bones); + surface_tool->add_weights(weights); + surface_tool->add_color(Color(1.0,0.4,0.4,0.4)); + surface_tool->add_vertex(t.xform(face_points[(j+1)%4]*0.04)); + } + + } + */ + } + + Ref<Mesh> m = surface_tool->commit(); + add_mesh(m,false,skel->get_skeleton()); + +} + +SkeletonSpatialGizmo::SkeletonSpatialGizmo(Skeleton* p_skel) { + + skel=p_skel; + set_spatial_node(p_skel); +} + +///// + + +void SpatialPlayerSpatialGizmo::redraw() { + + clear(); + if (splayer->cast_to<SpatialStreamPlayer>()) { + + add_unscaled_billboard(SpatialEditorGizmos::singleton->stream_player_icon,0.05); + + } else if (splayer->cast_to<SpatialSamplePlayer>()) { + + add_unscaled_billboard(SpatialEditorGizmos::singleton->sample_player_icon,0.05); + + } + +} + +SpatialPlayerSpatialGizmo::SpatialPlayerSpatialGizmo(SpatialPlayer* p_splayer){ + + set_spatial_node(p_splayer); + splayer=p_splayer; +} + + +///// + + +void RoomSpatialGizmo::redraw() { + + clear(); + Ref<RoomBounds> roomie = room->get_room(); + if (roomie.is_null()) + return; + DVector<Face3> faces = roomie->get_geometry_hint(); + + Vector<Vector3> lines; + int fc=faces.size(); + DVector<Face3>::Read r =faces.read(); + + Map<_EdgeKey,Vector3> edge_map; + + for(int i=0;i<fc;i++) { + + Vector3 fn = r[i].get_plane().normal; + + for(int j=0;j<3;j++) { + + _EdgeKey ek; + ek.from=r[i].vertex[j].snapped(CMP_EPSILON); + ek.to=r[i].vertex[(j+1)%3].snapped(CMP_EPSILON); + if (ek.from<ek.to) + SWAP(ek.from,ek.to); + + Map<_EdgeKey,Vector3>::Element *E=edge_map.find(ek); + + if (E) { + + if (E->get().dot(fn) >0.9) { + + E->get()=Vector3(); + } + + } else { + + edge_map[ek]=fn; + } + + } + } + + for(Map<_EdgeKey,Vector3>::Element *E=edge_map.front();E;E=E->next()) { + + if (E->get()!=Vector3()) { + lines.push_back(E->key().from); + lines.push_back(E->key().to); + } + } + + add_lines(lines,SpatialEditorGizmos::singleton->room_material); + add_collision_segments(lines); + +} + +RoomSpatialGizmo::RoomSpatialGizmo(Room* p_room){ + + set_spatial_node(p_room); + room=p_room; +} + +///// + + +void PortalSpatialGizmo::redraw() { + + clear(); + + Vector<Point2> points = portal->get_shape(); + if (points.size()==0) { + return; + } + + Vector<Vector3> lines; + + Vector3 center; + for(int i=0;i<points.size();i++) { + + Vector3 f; + f.x=points[i].x; + f.y=points[i].y; + Vector3 fn; + fn.x=points[(i+1)%points.size()].x; + fn.y=points[(i+1)%points.size()].y; + center+=f; + + lines.push_back(f); + lines.push_back(fn); + } + + center/=points.size(); + lines.push_back(center); + lines.push_back(center+Vector3(0,0,1)); + + add_lines(lines,SpatialEditorGizmos::singleton->portal_material); + add_collision_segments(lines); + +} + +PortalSpatialGizmo::PortalSpatialGizmo(Portal* p_portal){ + + set_spatial_node(p_portal); + portal=p_portal; +} + +///// + + +void RayCastSpatialGizmo::redraw() { + + clear(); + + + Vector<Vector3> lines; + + lines.push_back(Vector3()); + lines.push_back(raycast->get_cast_to()); + + add_lines(lines,SpatialEditorGizmos::singleton->raycast_material); + add_collision_segments(lines); + +} + +RayCastSpatialGizmo::RayCastSpatialGizmo(RayCast* p_raycast){ + + set_spatial_node(p_raycast); + raycast=p_raycast; +} + + + +///// + + +void VehicleWheelSpatialGizmo::redraw() { + + clear(); + + + Vector<Vector3> points; + + float r = car_wheel->get_radius(); + const int skip=10; + for(int i=0;i<=360;i+=skip) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+skip); + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r; + + points.push_back(Vector3(0,a.x,a.y)); + points.push_back(Vector3(0,b.x,b.y)); + + const int springsec=4; + + for(int j=0;j<springsec;j++) { + float t = car_wheel->get_suspension_rest_length()*5; + points.push_back(Vector3(a.x,i/360.0*t/springsec+j*(t/springsec),a.y)*0.2); + points.push_back(Vector3(b.x,(i+skip)/360.0*t/springsec+j*(t/springsec),b.y)*0.2); + } + + + } + + //travel + points.push_back(Vector3(0,0,0)); + points.push_back(Vector3(0,car_wheel->get_suspension_rest_length(),0)); + + //axis + points.push_back(Vector3(r*0.2,car_wheel->get_suspension_rest_length(),0)); + points.push_back(Vector3(-r*0.2,car_wheel->get_suspension_rest_length(),0)); + //axis + points.push_back(Vector3(r*0.2,0,0)); + points.push_back(Vector3(-r*0.2,0,0)); + + //forward line + points.push_back(Vector3(0,-r,0)); + points.push_back(Vector3(0,-r,r*2)); + points.push_back(Vector3(0,-r,r*2)); + points.push_back(Vector3(r*2*0.2,-r,r*2*0.8)); + points.push_back(Vector3(0,-r,r*2)); + points.push_back(Vector3(-r*2*0.2,-r,r*2*0.8)); + + add_lines(points,SpatialEditorGizmos::singleton->car_wheel_material); + add_collision_segments(points); + +} + +VehicleWheelSpatialGizmo::VehicleWheelSpatialGizmo(VehicleWheel* p_car_wheel){ + + set_spatial_node(p_car_wheel); + car_wheel=p_car_wheel; +} + + + +/// + +void TestCubeSpatialGizmo::redraw() { + + clear(); + add_collision_triangles(SpatialEditorGizmos::singleton->test_cube_tm); +} + +TestCubeSpatialGizmo::TestCubeSpatialGizmo(TestCube* p_tc) { + + tc=p_tc; + set_spatial_node(p_tc); +} + + +/////////// + + + + + + +String CollisionShapeSpatialGizmo::get_handle_name(int p_idx) const { + + Ref<Shape> s = cs->get_shape(); + if (s.is_null()) + return ""; + + if (s->cast_to<SphereShape>()) { + + return "Radius"; + } + + if (s->cast_to<BoxShape>()) { + + return "Extents"; + } + + if (s->cast_to<CapsuleShape>()) { + + return p_idx==0?"Radius":"Height"; + } + + if (s->cast_to<RayShape>()) { + + return "Length"; + } + + return ""; +} +Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const{ + + Ref<Shape> s = cs->get_shape(); + if (s.is_null()) + return Variant(); + + if (s->cast_to<SphereShape>()) { + + Ref<SphereShape> ss = s; + return ss->get_radius(); + } + + if (s->cast_to<BoxShape>()) { + + Ref<BoxShape> bs = s; + return bs->get_extents(); + } + + if (s->cast_to<CapsuleShape>()) { + + Ref<CapsuleShape> cs = s; + return p_idx==0?cs->get_radius():cs->get_height(); + } + + if (s->cast_to<RayShape>()) { + + Ref<RayShape> cs = s; + return cs->get_length(); + } + + return Variant(); +} +void CollisionShapeSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){ + Ref<Shape> s = cs->get_shape(); + if (s.is_null()) + return; + + Transform gt = cs->get_global_transform(); + gt.orthonormalize(); + Transform gi = gt.affine_inverse(); + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)}; + + if (s->cast_to<SphereShape>()) { + + Ref<SphereShape> ss = s; + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(Vector3(),Vector3(4096,0,0),sg[0],sg[1],ra,rb); + float d = ra.x; + if (d<0.001) + d=0.001; + + ss->set_radius(d); + } + + if (s->cast_to<RayShape>()) { + + Ref<RayShape> rs = s; + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,4096),sg[0],sg[1],ra,rb); + float d = ra.z; + if (d<0.001) + d=0.001; + + rs->set_length(d); + } + + + if (s->cast_to<BoxShape>()) { + + Vector3 axis; + axis[p_idx]=1.0; + Ref<BoxShape> bs = s; + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb); + float d = ra[p_idx]; + if (d<0.001) + d=0.001; + + Vector3 he = bs->get_extents(); + he[p_idx]=d; + bs->set_extents(he); + + } + + if (s->cast_to<CapsuleShape>()) { + + Vector3 axis; + axis[p_idx==0?0:2]=1.0; + Ref<CapsuleShape> cs = s; + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb); + float d = axis.dot(ra); + if (p_idx==1) + d-=cs->get_radius(); + if (d<0.001) + d=0.001; + + if (p_idx==0) + cs->set_radius(d); + else if (p_idx==1) + cs->set_height(d*2.0); + + } + +} +void CollisionShapeSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){ + Ref<Shape> s = cs->get_shape(); + if (s.is_null()) + return; + + if (s->cast_to<SphereShape>()) { + + Ref<SphereShape> ss=s; + if (p_cancel) { + ss->set_radius(p_restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action("Change Sphere Shape Radius"); + ur->add_do_method(ss.ptr(),"set_radius",ss->get_radius()); + ur->add_undo_method(ss.ptr(),"set_radius",p_restore); + ur->commit_action(); + + } + + if (s->cast_to<BoxShape>()) { + + Ref<BoxShape> ss=s; + if (p_cancel) { + ss->set_extents(p_restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action("Change Box Shape Extents"); + ur->add_do_method(ss.ptr(),"set_extents",ss->get_extents()); + ur->add_undo_method(ss.ptr(),"set_extents",p_restore); + ur->commit_action(); + } + + if (s->cast_to<CapsuleShape>()) { + + Ref<CapsuleShape> ss=s; + if (p_cancel) { + if (p_idx==0) + ss->set_radius(p_restore); + else + ss->set_height(p_restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + if (p_idx==0) { + ur->create_action("Change Capsule Shape Radius"); + ur->add_do_method(ss.ptr(),"set_radius",ss->get_radius()); + ur->add_undo_method(ss.ptr(),"set_radius",p_restore); + } else { + ur->create_action("Change Capsule Shape Height"); + ur->add_do_method(ss.ptr(),"set_height",ss->get_height()); + ur->add_undo_method(ss.ptr(),"set_height",p_restore); + + } + + ur->commit_action(); + + } + + if (s->cast_to<RayShape>()) { + + Ref<RayShape> ss=s; + if (p_cancel) { + ss->set_length(p_restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action("Change Ray Shape Length"); + ur->add_do_method(ss.ptr(),"set_length",ss->get_length()); + ur->add_undo_method(ss.ptr(),"set_length",p_restore); + ur->commit_action(); + + } + +} +void CollisionShapeSpatialGizmo::redraw(){ + + clear(); + + Ref<Shape> s = cs->get_shape(); + if (s.is_null()) + return; + + if (s->cast_to<SphereShape>()) { + + Ref<SphereShape> sp= s; + float r=sp->get_radius(); + + Vector<Vector3> points; + + for(int i=0;i<=360;i++) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+1); + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r; + + points.push_back(Vector3(a.x,0,a.y)); + points.push_back(Vector3(b.x,0,b.y)); + points.push_back(Vector3(0,a.x,a.y)); + points.push_back(Vector3(0,b.x,b.y)); + points.push_back(Vector3(a.x,a.y,0)); + points.push_back(Vector3(b.x,b.y,0)); + + } + + Vector<Vector3> collision_segments; + + for(int i=0;i<64;i++) { + + float ra=i*Math_PI*2.0/64.0; + float rb=(i+1)*Math_PI*2.0/64.0; + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r; + + collision_segments.push_back(Vector3(a.x,0,a.y)); + collision_segments.push_back(Vector3(b.x,0,b.y)); + collision_segments.push_back(Vector3(0,a.x,a.y)); + collision_segments.push_back(Vector3(0,b.x,b.y)); + collision_segments.push_back(Vector3(a.x,a.y,0)); + collision_segments.push_back(Vector3(b.x,b.y,0)); + } + + add_lines(points,SpatialEditorGizmos::singleton->shape_material); + add_collision_segments(collision_segments); + Vector<Vector3> handles; + handles.push_back(Vector3(r,0,0)); + add_handles(handles); + + } + + if (s->cast_to<BoxShape>()) { + + Ref<BoxShape> bs=s; + Vector<Vector3> lines; + AABB aabb; + aabb.pos=-bs->get_extents(); + aabb.size=aabb.pos*-2; + + for(int i=0;i<12;i++) { + Vector3 a,b; + aabb.get_edge(i,a,b); + lines.push_back(a); + lines.push_back(b); + } + + Vector<Vector3> handles; + + for(int i=0;i<3;i++) { + + Vector3 ax; + ax[i]=bs->get_extents()[i]; + handles.push_back(ax); + } + + add_lines(lines,SpatialEditorGizmos::singleton->shape_material); + add_collision_segments(lines); + add_handles(handles); + + } + + if (s->cast_to<CapsuleShape>()) { + + Ref<CapsuleShape> cs=s; + float radius = cs->get_radius(); + float height = cs->get_height(); + + + Vector<Vector3> points; + + Vector3 d(0,0,height*0.5); + for(int i=0;i<360;i++) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+1); + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius; + + points.push_back(Vector3(a.x,a.y,0)+d); + points.push_back(Vector3(b.x,b.y,0)+d); + + points.push_back(Vector3(a.x,a.y,0)-d); + points.push_back(Vector3(b.x,b.y,0)-d); + + if (i%90==0) { + + points.push_back(Vector3(a.x,a.y,0)+d); + points.push_back(Vector3(a.x,a.y,0)-d); + } + + Vector3 dud = i<180?d:-d; + + points.push_back(Vector3(0,a.y,a.x)+dud); + points.push_back(Vector3(0,b.y,b.x)+dud); + points.push_back(Vector3(a.y,0,a.x)+dud); + points.push_back(Vector3(b.y,0,b.x)+dud); + + } + + add_lines(points,SpatialEditorGizmos::singleton->shape_material); + + Vector<Vector3> collision_segments; + + for(int i=0;i<64;i++) { + + float ra=i*Math_PI*2.0/64.0; + float rb=(i+1)*Math_PI*2.0/64.0; + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius; + + collision_segments.push_back(Vector3(a.x,a.y,0)+d); + collision_segments.push_back(Vector3(b.x,b.y,0)+d); + + collision_segments.push_back(Vector3(a.x,a.y,0)-d); + collision_segments.push_back(Vector3(b.x,b.y,0)-d); + + if (i%16==0) { + + collision_segments.push_back(Vector3(a.x,a.y,0)+d); + collision_segments.push_back(Vector3(a.x,a.y,0)-d); + } + + Vector3 dud = i<32?d:-d; + + collision_segments.push_back(Vector3(0,a.y,a.x)+dud); + collision_segments.push_back(Vector3(0,b.y,b.x)+dud); + collision_segments.push_back(Vector3(a.y,0,a.x)+dud); + collision_segments.push_back(Vector3(b.y,0,b.x)+dud); + + } + + add_collision_segments(collision_segments); + + Vector<Vector3> handles; + handles.push_back(Vector3(cs->get_radius(),0,0)); + handles.push_back(Vector3(0,0,cs->get_height()*0.5+cs->get_radius())); + add_handles(handles); + + + } + + if (s->cast_to<PlaneShape>()) { + + Ref<PlaneShape> ps=s; + Plane p = ps->get_plane(); + Vector<Vector3> points; + + Vector3 n1 = p.get_any_perpendicular_normal(); + Vector3 n2 = p.normal.cross(n1).normalized(); + + Vector3 pface[4]={ + p.normal*p.d+n1*10.0+n2*10.0, + p.normal*p.d+n1*10.0+n2*-10.0, + p.normal*p.d+n1*-10.0+n2*-10.0, + p.normal*p.d+n1*-10.0+n2*10.0, + }; + + points.push_back(pface[0]); + points.push_back(pface[1]); + points.push_back(pface[1]); + points.push_back(pface[2]); + points.push_back(pface[2]); + points.push_back(pface[3]); + points.push_back(pface[3]); + points.push_back(pface[0]); + points.push_back(p.normal*p.d); + points.push_back(p.normal*p.d+p.normal*3); + + add_lines(points,SpatialEditorGizmos::singleton->shape_material); + add_collision_segments(points); + + } + + + if (s->cast_to<ConvexPolygonShape>()) { + + DVector<Vector3> points = s->cast_to<ConvexPolygonShape>()->get_points(); + + if (points.size()>3) { + + QuickHull qh; + Vector<Vector3> varr = Variant(points); + Geometry::MeshData md; + Error err = qh.build(varr,md); + if (err==OK) { + Vector<Vector3> points; + points.resize(md.edges.size()*2); + for(int i=0;i<md.edges.size();i++) { + points[i*2+0]=md.vertices[md.edges[i].a]; + points[i*2+1]=md.vertices[md.edges[i].b]; + } + + + add_lines(points,SpatialEditorGizmos::singleton->shape_material); + add_collision_segments(points); + + } + } + + } + + + if (s->cast_to<RayShape>()) { + + Ref<RayShape> rs=s; + + Vector<Vector3> points; + points.push_back(Vector3()); + points.push_back(Vector3(0,0,rs->get_length())); + add_lines(points,SpatialEditorGizmos::singleton->shape_material); + add_collision_segments(points); + Vector<Vector3> handles; + handles.push_back(Vector3(0,0,rs->get_length())); + add_handles(handles); + + + } + +} +CollisionShapeSpatialGizmo::CollisionShapeSpatialGizmo(CollisionShape* p_cs) { + + cs=p_cs; + set_spatial_node(p_cs); +} + + + +///// + + +void CollisionPolygonSpatialGizmo::redraw() { + + clear(); + + Vector<Vector2> points = polygon->get_polygon(); + float depth = polygon->get_depth()*0.5; + + Vector<Vector3> lines; + for(int i=0;i<points.size();i++) { + + int n = (i+1)%points.size(); + lines.push_back(Vector3(points[i].x,points[i].y,depth)); + lines.push_back(Vector3(points[n].x,points[n].y,depth)); + lines.push_back(Vector3(points[i].x,points[i].y,-depth)); + lines.push_back(Vector3(points[n].x,points[n].y,-depth)); + lines.push_back(Vector3(points[i].x,points[i].y,depth)); + lines.push_back(Vector3(points[i].x,points[i].y,-depth)); + + } + + add_lines(lines,SpatialEditorGizmos::singleton->shape_material); + add_collision_segments(lines); +} + +CollisionPolygonSpatialGizmo::CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon){ + + set_spatial_node(p_polygon); + polygon=p_polygon; +} +/// + + +String VisibilityNotifierGizmo::get_handle_name(int p_idx) const { + + switch(p_idx) { + case 0: return "X"; + case 1: return "Y"; + case 2: return "Z"; + } + + return ""; +} +Variant VisibilityNotifierGizmo::get_handle_value(int p_idx) const{ + + return notifier->get_aabb(); +} +void VisibilityNotifierGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){ + + + Transform gt = notifier->get_global_transform(); + //gt.orthonormalize(); + Transform gi = gt.affine_inverse(); + + AABB aabb = notifier->get_aabb(); + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)}; + Vector3 ofs = aabb.pos+aabb.size*0.5;; + + Vector3 axis; + axis[p_idx]=1.0; + + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(ofs,ofs+axis*4096,sg[0],sg[1],ra,rb); + float d = ra[p_idx]; + if (d<0.001) + d=0.001; + + Vector3 he = aabb.size; + aabb.pos[p_idx]=(aabb.pos[p_idx]+aabb.size[p_idx]*0.5)-d; + aabb.size[p_idx]=d*2; + notifier->set_aabb(aabb); +} + +void VisibilityNotifierGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){ + + + if (p_cancel) { + notifier->set_aabb(p_restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action("Change Notifier Extents"); + ur->add_do_method(notifier,"set_aabb",notifier->get_aabb()); + ur->add_undo_method(notifier,"set_aabb",p_restore); + ur->commit_action(); + +} + +void VisibilityNotifierGizmo::redraw(){ + + clear(); + + Vector<Vector3> lines; + AABB aabb = notifier->get_aabb(); + + for(int i=0;i<12;i++) { + Vector3 a,b; + aabb.get_edge(i,a,b); + lines.push_back(a); + lines.push_back(b); + } + + Vector<Vector3> handles; + + + for(int i=0;i<3;i++) { + + Vector3 ax; + ax[i]=aabb.pos[i]+aabb.size[i]; + handles.push_back(ax); + } + + add_lines(lines,SpatialEditorGizmos::singleton->visibility_notifier_material); + //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05); + add_collision_segments(lines); + add_handles(handles); + +} +VisibilityNotifierGizmo::VisibilityNotifierGizmo(VisibilityNotifier* p_notifier){ + + notifier=p_notifier; + set_spatial_node(p_notifier); +} + +//////// + + + +void NavigationMeshSpatialGizmo::redraw() { + + clear(); + Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh(); + if (navmeshie.is_null()) + return; + + DVector<Vector3> vertices = navmeshie->get_vertices(); + DVector<Vector3>::Read vr=vertices.read(); + List<Face3> faces; + for(int i=0;i<navmeshie->get_polygon_count();i++) { + Vector<int> p = navmeshie->get_polygon(i); + + for(int j=2;j<p.size();j++) { + Face3 f; + f.vertex[0]=vr[p[0]]; + f.vertex[1]=vr[p[j-1]]; + f.vertex[2]=vr[p[j]]; + + faces.push_back(f); + } + } + + + Map<_EdgeKey,bool> edge_map; + DVector<Vector3> tmeshfaces; + tmeshfaces.resize(faces.size()*3); + + { + DVector<Vector3>::Write tw=tmeshfaces.write(); + int tidx=0; + + + for(List<Face3>::Element *E=faces.front();E;E=E->next()) { + + const Face3 &f = E->get(); + + for(int j=0;j<3;j++) { + + tw[tidx++]=f.vertex[j]; + _EdgeKey ek; + ek.from=f.vertex[j].snapped(CMP_EPSILON); + ek.to=f.vertex[(j+1)%3].snapped(CMP_EPSILON); + if (ek.from<ek.to) + SWAP(ek.from,ek.to); + + Map<_EdgeKey,bool>::Element *E=edge_map.find(ek); + + if (E) { + + E->get()=false; + + } else { + + edge_map[ek]=true; + } + + } + } + } + Vector<Vector3> lines; + + for(Map<_EdgeKey,bool>::Element *E=edge_map.front();E;E=E->next()) { + + if (E->get()) { + lines.push_back(E->key().from); + lines.push_back(E->key().to); + } + } + + Ref<TriangleMesh> tmesh = memnew( TriangleMesh); + tmesh->create(tmeshfaces); + + if (lines.size()) + add_lines(lines,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_edge_material:SpatialEditorGizmos::singleton->navmesh_edge_material_disabled); + add_collision_triangles(tmesh); + Ref<Mesh> m = memnew( Mesh ); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[0]=tmeshfaces; + m->add_surface(Mesh::PRIMITIVE_TRIANGLES,a); + m->surface_set_material(0,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_solid_material:SpatialEditorGizmos::singleton->navmesh_solid_material_disabled); + add_mesh(m); + add_collision_segments(lines); + +} + +NavigationMeshSpatialGizmo::NavigationMeshSpatialGizmo(NavigationMeshInstance *p_navmesh){ + + set_spatial_node(p_navmesh); + navmesh=p_navmesh; +} + +////// +/// +/// + + + +void PinJointSpatialGizmo::redraw() { + + clear(); + Vector<Vector3> cursor_points; + float cs = 0.25; + cursor_points.push_back(Vector3(+cs,0,0)); + cursor_points.push_back(Vector3(-cs,0,0)); + cursor_points.push_back(Vector3(0,+cs,0)); + cursor_points.push_back(Vector3(0,-cs,0)); + cursor_points.push_back(Vector3(0,0,+cs)); + cursor_points.push_back(Vector3(0,0,-cs)); + add_collision_segments(cursor_points); + add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material); + +} + + +PinJointSpatialGizmo::PinJointSpatialGizmo(PinJoint* p_p3d) { + + p3d=p_p3d; + set_spatial_node(p3d); +} + +//// + +void HingeJointSpatialGizmo::redraw() { + + clear(); + Vector<Vector3> cursor_points; + float cs = 0.25; + /*cursor_points.push_back(Vector3(+cs,0,0)); + cursor_points.push_back(Vector3(-cs,0,0)); + cursor_points.push_back(Vector3(0,+cs,0)); + cursor_points.push_back(Vector3(0,-cs,0));*/ + cursor_points.push_back(Vector3(0,0,+cs*2)); + cursor_points.push_back(Vector3(0,0,-cs*2)); + + float ll = p3d->get_param(HingeJoint::PARAM_LIMIT_LOWER); + float ul = p3d->get_param(HingeJoint::PARAM_LIMIT_UPPER); + + if (p3d->get_flag(HingeJoint::FLAG_USE_LIMIT) && ll<ul) { + + const int points = 32; + float step = (ul-ll)/points; + + + for(int i=0;i<points;i++) { + + float s = ll+i*(ul-ll)/points; + float n = ll+(i+1)*(ul-ll)/points; + + Vector3 from=Vector3( -Math::sin(s),Math::cos(s), 0 )*cs; + Vector3 to=Vector3( -Math::sin(n),Math::cos(n), 0 )*cs; + + if (i==points-1) { + cursor_points.push_back(to); + cursor_points.push_back(Vector3()); + } + if (i==0) { + cursor_points.push_back(from); + cursor_points.push_back(Vector3()); + } + + + cursor_points.push_back(from); + cursor_points.push_back(to); + + + } + + cursor_points.push_back(Vector3(0,cs*1.5,0)); + cursor_points.push_back(Vector3()); + + } else { + + + const int points = 32; + + for(int i=0;i<points;i++) { + + float s = ll+i*(Math_PI*2.0)/points; + float n = ll+(i+1)*(Math_PI*2.0)/points; + + Vector3 from=Vector3( -Math::sin(s),Math::cos(s), 0 )*cs; + Vector3 to=Vector3( -Math::sin(n),Math::cos(n), 0 )*cs; + + cursor_points.push_back(from); + cursor_points.push_back(to); + + } + + } + add_collision_segments(cursor_points); + add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material); + +} + + +HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint* p_p3d) { + + p3d=p_p3d; + set_spatial_node(p3d); +} + +/////// +/// +//// + +void SliderJointSpatialGizmo::redraw() { + + clear(); + Vector<Vector3> cursor_points; + float cs = 0.25; + /*cursor_points.push_back(Vector3(+cs,0,0)); + cursor_points.push_back(Vector3(-cs,0,0)); + cursor_points.push_back(Vector3(0,+cs,0)); + cursor_points.push_back(Vector3(0,-cs,0));*/ + cursor_points.push_back(Vector3(0,0,+cs*2)); + cursor_points.push_back(Vector3(0,0,-cs*2)); + + float ll = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER); + float ul = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER); + float lll = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER); + float lul = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER); + + if (lll>lul) { + + cursor_points.push_back(Vector3(lul,0,0)); + cursor_points.push_back(Vector3(lll,0,0)); + + cursor_points.push_back(Vector3(lul,-cs,-cs)); + cursor_points.push_back(Vector3(lul,-cs,cs)); + cursor_points.push_back(Vector3(lul,-cs,cs)); + cursor_points.push_back(Vector3(lul,cs,cs)); + cursor_points.push_back(Vector3(lul,cs,cs)); + cursor_points.push_back(Vector3(lul,cs,-cs)); + cursor_points.push_back(Vector3(lul,cs,-cs)); + cursor_points.push_back(Vector3(lul,-cs,-cs)); + + + cursor_points.push_back(Vector3(lll,-cs,-cs)); + cursor_points.push_back(Vector3(lll,-cs,cs)); + cursor_points.push_back(Vector3(lll,-cs,cs)); + cursor_points.push_back(Vector3(lll,cs,cs)); + cursor_points.push_back(Vector3(lll,cs,cs)); + cursor_points.push_back(Vector3(lll,cs,-cs)); + cursor_points.push_back(Vector3(lll,cs,-cs)); + cursor_points.push_back(Vector3(lll,-cs,-cs)); + + + } else { + + cursor_points.push_back(Vector3(+cs*2,0,0)); + cursor_points.push_back(Vector3(-cs*2,0,0)); + + } + + if (ll<ul) { + + const int points = 32; + float step = (ul-ll)/points; + + + for(int i=0;i<points;i++) { + + float s = ll+i*(ul-ll)/points; + float n = ll+(i+1)*(ul-ll)/points; + + Vector3 from=Vector3(0, Math::cos(s), -Math::sin(s) )*cs; + Vector3 to=Vector3(0,Math::cos(n), -Math::sin(n) )*cs; + + if (i==points-1) { + cursor_points.push_back(to); + cursor_points.push_back(Vector3()); + } + if (i==0) { + cursor_points.push_back(from); + cursor_points.push_back(Vector3()); + } + + + cursor_points.push_back(from); + cursor_points.push_back(to); + + + } + + cursor_points.push_back(Vector3(0,cs*1.5,0)); + cursor_points.push_back(Vector3()); + + } else { + + + const int points = 32; + + for(int i=0;i<points;i++) { + + float s = ll+i*(Math_PI*2.0)/points; + float n = ll+(i+1)*(Math_PI*2.0)/points; + + Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs; + Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs; + + cursor_points.push_back(from); + cursor_points.push_back(to); + + } + + } + add_collision_segments(cursor_points); + add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material); + +} + + +SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint* p_p3d) { + + p3d=p_p3d; + set_spatial_node(p3d); +} + +/////// +/// +//// + +void ConeTwistJointSpatialGizmo::redraw() { + + clear(); + float cs = 0.25; + Vector<Vector3> points; + + float r = 1.0; + float w = r*Math::sin(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN)); + float d = r*Math::cos(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN)); + + + //swing + for(int i=0;i<360;i+=10) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+10); + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w; + + /*points.push_back(Vector3(a.x,0,a.y)); + points.push_back(Vector3(b.x,0,b.y)); + points.push_back(Vector3(0,a.x,a.y)); + points.push_back(Vector3(0,b.x,b.y));*/ + points.push_back(Vector3(d,a.x,a.y)); + points.push_back(Vector3(d,b.x,b.y)); + + if (i%90==0) { + + points.push_back(Vector3(d,a.x,a.y)); + points.push_back(Vector3()); + + } + } + + points.push_back(Vector3()); + points.push_back(Vector3(1,0,0)); + + //twist + /* + */ + float ts=Math::rad2deg(p3d->get_param(ConeTwistJoint::PARAM_TWIST_SPAN)); + ts=MIN(ts,720); + + + for(int i=0;i<int(ts);i+=5) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+5); + float c = i/720.0; + float cn = (i+5)/720.0; + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w*c; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w*cn; + + /*points.push_back(Vector3(a.x,0,a.y)); + points.push_back(Vector3(b.x,0,b.y)); + points.push_back(Vector3(0,a.x,a.y)); + points.push_back(Vector3(0,b.x,b.y));*/ + + points.push_back(Vector3(c,a.x,a.y)); + points.push_back(Vector3(cn,b.x,b.y)); + + } + + + add_collision_segments(points); + add_lines(points,SpatialEditorGizmos::singleton->joint_material); + +} + + +ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d) { + + p3d=p_p3d; + set_spatial_node(p3d); +} + +//////// +/// \brief SpatialEditorGizmos::singleton +/// +/////// +/// +//// + +void Generic6DOFJointSpatialGizmo::redraw() { + + clear(); + Vector<Vector3> cursor_points; + float cs = 0.25; + + for(int ax=0;ax<3;ax++) { + /*cursor_points.push_back(Vector3(+cs,0,0)); + cursor_points.push_back(Vector3(-cs,0,0)); + cursor_points.push_back(Vector3(0,+cs,0)); + cursor_points.push_back(Vector3(0,-cs,0)); + cursor_points.push_back(Vector3(0,0,+cs*2)); + cursor_points.push_back(Vector3(0,0,-cs*2)); */ + + float ll; + float ul; + float lll; + float lul; + + int a1,a2,a3; + bool enable_ang; + bool enable_lin; + + switch(ax) { + case 0: + ll = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT); + ul = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT); + lll = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT); + lul = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT); + enable_ang = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT); + enable_lin = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT); + a1=0; + a2=1; + a3=2; + break; + case 1: + ll = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT); + ul = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT); + lll = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT); + lul = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT); + enable_ang = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT); + enable_lin = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT); + a1=2; + a2=0; + a3=1; + break; + case 2: + ll = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT); + ul = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT); + lll = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT); + lul = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT); + enable_ang = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT); + enable_lin = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT); + + a1=1; + a2=2; + a3=0; + break; + } + +#define ADD_VTX(x,y,z)\ + {\ + Vector3 v;\ + v[a1]=(x);\ + v[a2]=(y);\ + v[a3]=(z);\ + cursor_points.push_back(v);\ + } + +#define SET_VTX(what,x,y,z)\ + {\ + Vector3 v;\ + v[a1]=(x);\ + v[a2]=(y);\ + v[a3]=(z);\ + what=v;\ + } + + + + + if (enable_lin && lll>=lul) { + + ADD_VTX(lul,0,0); + ADD_VTX(lll,0,0); + + ADD_VTX(lul,-cs,-cs); + ADD_VTX(lul,-cs,cs); + ADD_VTX(lul,-cs,cs); + ADD_VTX(lul,cs,cs); + ADD_VTX(lul,cs,cs); + ADD_VTX(lul,cs,-cs); + ADD_VTX(lul,cs,-cs); + ADD_VTX(lul,-cs,-cs); + + + ADD_VTX(lll,-cs,-cs); + ADD_VTX(lll,-cs,cs); + ADD_VTX(lll,-cs,cs); + ADD_VTX(lll,cs,cs); + ADD_VTX(lll,cs,cs); + ADD_VTX(lll,cs,-cs); + ADD_VTX(lll,cs,-cs); + ADD_VTX(lll,-cs,-cs); + + + } else { + + ADD_VTX(+cs*2,0,0); + ADD_VTX(-cs*2,0,0); + + } + + if (enable_ang && ll<=ul) { + + const int points = 32; + float step = (ul-ll)/points; + + + for(int i=0;i<points;i++) { + + float s = ll+i*(ul-ll)/points; + float n = ll+(i+1)*(ul-ll)/points; + + Vector3 from; + SET_VTX(from,0, Math::cos(s), -Math::sin(s) ); + from*=cs; + Vector3 to; + SET_VTX(to,0,Math::cos(n), -Math::sin(n)); + to*=cs; + + if (i==points-1) { + cursor_points.push_back(to); + cursor_points.push_back(Vector3()); + } + if (i==0) { + cursor_points.push_back(from); + cursor_points.push_back(Vector3()); + } + + + cursor_points.push_back(from); + cursor_points.push_back(to); + + + } + + ADD_VTX(0,cs*1.5,0); + cursor_points.push_back(Vector3()); + + } else { + + + const int points = 32; + + for(int i=0;i<points;i++) { + + float s = ll+i*(Math_PI*2.0)/points; + float n = ll+(i+1)*(Math_PI*2.0)/points; + +// Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs; +// Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs; + + Vector3 from; + SET_VTX(from,0, Math::cos(s), -Math::sin(s) ); + from*=cs; + Vector3 to; + SET_VTX(to,0,Math::cos(n), -Math::sin(n)); + to*=cs; + + cursor_points.push_back(from); + cursor_points.push_back(to); + + } + + } + } + +#undef ADD_VTX +#undef SET_VTX + + add_collision_segments(cursor_points); + add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material); + +} + + +Generic6DOFJointSpatialGizmo::Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d) { + + p3d=p_p3d; + set_spatial_node(p3d); +} + +/////// +/// +//// + + +SpatialEditorGizmos *SpatialEditorGizmos::singleton=NULL; + +Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) { + + if (p_spatial->cast_to<Light>()) { + + Ref<LightSpatialGizmo> lsg = memnew( LightSpatialGizmo(p_spatial->cast_to<Light>()) ); + return lsg; + } + + if (p_spatial->cast_to<Camera>()) { + + Ref<CameraSpatialGizmo> lsg = memnew( CameraSpatialGizmo(p_spatial->cast_to<Camera>()) ); + return lsg; + } + + if (p_spatial->cast_to<Skeleton>()) { + + Ref<SkeletonSpatialGizmo> lsg = memnew( SkeletonSpatialGizmo(p_spatial->cast_to<Skeleton>()) ); + return lsg; + } + + + if (p_spatial->cast_to<Position3D>()) { + + Ref<Position3DSpatialGizmo> lsg = memnew( Position3DSpatialGizmo(p_spatial->cast_to<Position3D>()) ); + return lsg; + } + + if (p_spatial->cast_to<MeshInstance>()) { + + Ref<MeshInstanceSpatialGizmo> misg = memnew( MeshInstanceSpatialGizmo(p_spatial->cast_to<MeshInstance>()) ); + return misg; + } + + if (p_spatial->cast_to<Room>()) { + + Ref<RoomSpatialGizmo> misg = memnew( RoomSpatialGizmo(p_spatial->cast_to<Room>()) ); + return misg; + } + + if (p_spatial->cast_to<NavigationMeshInstance>()) { + + Ref<NavigationMeshSpatialGizmo> misg = memnew( NavigationMeshSpatialGizmo(p_spatial->cast_to<NavigationMeshInstance>()) ); + return misg; + } + + if (p_spatial->cast_to<RayCast>()) { + + Ref<RayCastSpatialGizmo> misg = memnew( RayCastSpatialGizmo(p_spatial->cast_to<RayCast>()) ); + return misg; + } + + if (p_spatial->cast_to<Portal>()) { + + Ref<PortalSpatialGizmo> misg = memnew( PortalSpatialGizmo(p_spatial->cast_to<Portal>()) ); + return misg; + } + + + if (p_spatial->cast_to<TestCube>()) { + + Ref<TestCubeSpatialGizmo> misg = memnew( TestCubeSpatialGizmo(p_spatial->cast_to<TestCube>()) ); + return misg; + } + + if (p_spatial->cast_to<SpatialPlayer>()) { + + Ref<SpatialPlayerSpatialGizmo> misg = memnew( SpatialPlayerSpatialGizmo(p_spatial->cast_to<SpatialPlayer>()) ); + return misg; + } + + if (p_spatial->cast_to<CollisionShape>()) { + + Ref<CollisionShapeSpatialGizmo> misg = memnew( CollisionShapeSpatialGizmo(p_spatial->cast_to<CollisionShape>()) ); + return misg; + } + + if (p_spatial->cast_to<VisibilityNotifier>()) { + + Ref<VisibilityNotifierGizmo> misg = memnew( VisibilityNotifierGizmo(p_spatial->cast_to<VisibilityNotifier>()) ); + return misg; + } + + if (p_spatial->cast_to<VehicleWheel>()) { + + Ref<VehicleWheelSpatialGizmo> misg = memnew( VehicleWheelSpatialGizmo(p_spatial->cast_to<VehicleWheel>()) ); + return misg; + } + if (p_spatial->cast_to<PinJoint>()) { + + Ref<PinJointSpatialGizmo> misg = memnew( PinJointSpatialGizmo(p_spatial->cast_to<PinJoint>()) ); + return misg; + } + + if (p_spatial->cast_to<HingeJoint>()) { + + Ref<HingeJointSpatialGizmo> misg = memnew( HingeJointSpatialGizmo(p_spatial->cast_to<HingeJoint>()) ); + return misg; + } + + if (p_spatial->cast_to<SliderJoint>()) { + + Ref<SliderJointSpatialGizmo> misg = memnew( SliderJointSpatialGizmo(p_spatial->cast_to<SliderJoint>()) ); + return misg; + } + + if (p_spatial->cast_to<ConeTwistJoint>()) { + + Ref<ConeTwistJointSpatialGizmo> misg = memnew( ConeTwistJointSpatialGizmo(p_spatial->cast_to<ConeTwistJoint>()) ); + return misg; + } + + if (p_spatial->cast_to<Generic6DOFJoint>()) { + + Ref<Generic6DOFJointSpatialGizmo> misg = memnew( Generic6DOFJointSpatialGizmo(p_spatial->cast_to<Generic6DOFJoint>()) ); + return misg; + } + + if (p_spatial->cast_to<CollisionPolygon>()) { + + Ref<CollisionPolygonSpatialGizmo> misg = memnew( CollisionPolygonSpatialGizmo(p_spatial->cast_to<CollisionPolygon>()) ); + return misg; + } + + + return Ref<SpatialEditorGizmo>(); +} + + +Ref<FixedMaterial> SpatialEditorGizmos::create_line_material(const Color& p_base_color) { + + Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + line_material->set_flag(Material::FLAG_UNSHADED, true); + line_material->set_line_width(3.0); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true); + line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,p_base_color); + + return line_material; + +} + +Ref<FixedMaterial> SpatialEditorGizmos::create_solid_material(const Color& p_base_color) { + + Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + line_material->set_flag(Material::FLAG_UNSHADED, true); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,p_base_color); + + return line_material; + +} + +SpatialEditorGizmos::SpatialEditorGizmos() { + + singleton=this; + + handle_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + handle_material->set_flag(Material::FLAG_UNSHADED, true); + handle_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(0.8,0.8,0.8)); + + handle2_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + handle2_material->set_flag(Material::FLAG_UNSHADED, true); + handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_POINT_SIZE, true); + handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle","EditorIcons"); + handle2_material->set_point_size(handle_t->get_width()); + handle2_material->set_texture(FixedMaterial::PARAM_DIFFUSE,handle_t); + handle2_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1)); + handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true); + + light_material = create_line_material(Color(1,1,0.2)); + + light_material_omni_icon = Ref<FixedMaterial>( memnew( FixedMaterial )); + light_material_omni_icon->set_flag(Material::FLAG_UNSHADED, true); + light_material_omni_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true); + light_material_omni_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); + light_material_omni_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + light_material_omni_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9)); + light_material_omni_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("GizmoLight","EditorIcons")); + + + light_material_directional_icon = Ref<FixedMaterial>( memnew( FixedMaterial )); + light_material_directional_icon->set_flag(Material::FLAG_UNSHADED, true); + light_material_directional_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true); + light_material_directional_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); + light_material_directional_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + light_material_directional_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9)); + light_material_directional_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight","EditorIcons")); + + camera_material = create_line_material(Color(1.0,0.5,1.0)); + + + navmesh_edge_material = create_line_material(Color(0.1,0.8,1.0)); + navmesh_solid_material = create_solid_material(Color(0.1,0.8,1.0,0.4)); + navmesh_edge_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, false); + navmesh_solid_material->set_flag(Material::FLAG_DOUBLE_SIDED,true); + + navmesh_edge_material_disabled = create_line_material(Color(1.0,0.8,0.1)); + navmesh_solid_material_disabled = create_solid_material(Color(1.0,0.8,0.1,0.4)); + navmesh_edge_material_disabled->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, false); + navmesh_solid_material_disabled->set_flag(Material::FLAG_DOUBLE_SIDED,true); + + skeleton_material = create_line_material(Color(0.6,1.0,0.3)); + skeleton_material->set_flag(Material::FLAG_DOUBLE_SIDED,true); + skeleton_material->set_flag(Material::FLAG_UNSHADED,true); + skeleton_material->set_flag(Material::FLAG_ONTOP,true); + skeleton_material->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); + + //position 3D Shared mesh + + pos3d_mesh = Ref<Mesh>( memnew( Mesh ) ); + { + + DVector<Vector3> cursor_points; + DVector<Color> cursor_colors; + float cs = 0.25; + cursor_points.push_back(Vector3(+cs,0,0)); + cursor_points.push_back(Vector3(-cs,0,0)); + cursor_points.push_back(Vector3(0,+cs,0)); + cursor_points.push_back(Vector3(0,-cs,0)); + cursor_points.push_back(Vector3(0,0,+cs)); + cursor_points.push_back(Vector3(0,0,-cs)); + cursor_colors.push_back(Color(1,0.5,0.5,0.7)); + cursor_colors.push_back(Color(1,0.5,0.5,0.7)); + cursor_colors.push_back(Color(0.5,1,0.5,0.7)); + cursor_colors.push_back(Color(0.5,1,0.5,0.7)); + cursor_colors.push_back(Color(0.5,0.5,1,0.7)); + cursor_colors.push_back(Color(0.5,0.5,1,0.7)); + + Ref<FixedMaterial> mat = memnew( FixedMaterial ); + mat->set_flag(Material::FLAG_UNSHADED,true); + mat->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); + mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); + mat->set_line_width(3); + Array d; + d.resize(VS::ARRAY_MAX); + d[Mesh::ARRAY_VERTEX]=cursor_points; + d[Mesh::ARRAY_COLOR]=cursor_colors; + pos3d_mesh->add_surface(Mesh::PRIMITIVE_LINES,d); + pos3d_mesh->surface_set_material(0,mat); + } + + + sample_player_icon = Ref<FixedMaterial>( memnew( FixedMaterial )); + sample_player_icon->set_flag(Material::FLAG_UNSHADED, true); + sample_player_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true); + sample_player_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); + sample_player_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + sample_player_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9)); + sample_player_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer","EditorIcons")); + + room_material = create_line_material(Color(1.0,0.6,0.9)); + portal_material = create_line_material(Color(1.0,0.8,0.6)); + raycast_material = create_line_material(Color(1.0,0.8,0.6)); + car_wheel_material = create_line_material(Color(0.6,0.8,1.0)); + visibility_notifier_material = create_line_material(Color(1.0,0.5,1.0)); + joint_material = create_line_material(Color(0.6,0.8,1.0)); + + stream_player_icon = Ref<FixedMaterial>( memnew( FixedMaterial )); + stream_player_icon->set_flag(Material::FLAG_UNSHADED, true); + stream_player_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true); + stream_player_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); + stream_player_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + stream_player_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9)); + stream_player_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer","EditorIcons")); + + visibility_notifier_icon = Ref<FixedMaterial>( memnew( FixedMaterial )); + visibility_notifier_icon->set_flag(Material::FLAG_UNSHADED, true); + visibility_notifier_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true); + visibility_notifier_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); + visibility_notifier_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + visibility_notifier_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1,0.9)); + visibility_notifier_icon->set_texture(FixedMaterial::PARAM_DIFFUSE,SpatialEditor::get_singleton()->get_icon("Visible","EditorIcons")); + + { + + DVector<Vector3> vertices; + +#undef ADD_VTX +#define ADD_VTX(m_idx);\ + vertices.push_back( face_points[m_idx] ); + + for (int i=0;i<6;i++) { + + + Vector3 face_points[4]; + + for (int j=0;j<4;j++) { + + float v[3]; + v[0]=1.0; + v[1]=1-2*((j>>1)&1); + v[2]=v[1]*(1-2*(j&1)); + + for (int k=0;k<3;k++) { + + if (i<3) + face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); + else + face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); + } + } + //tri 1 + ADD_VTX(0); + ADD_VTX(1); + ADD_VTX(2); + //tri 2 + ADD_VTX(2); + ADD_VTX(3); + ADD_VTX(0); + + } + + test_cube_tm = Ref<TriangleMesh>( memnew( TriangleMesh ) ); + test_cube_tm->create(vertices); + } + + shape_material = create_line_material(Color(0.2,1,1.0)); + + +} + diff --git a/tools/editor/spatial_editor_gizmos.h b/tools/editor/spatial_editor_gizmos.h index 02f60db7f8..bc7e8ad21d 100644 --- a/tools/editor/spatial_editor_gizmos.h +++ b/tools/editor/spatial_editor_gizmos.h @@ -1,491 +1,491 @@ -/*************************************************************************/
-/* spatial_editor_gizmos.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef SPATIAL_EDITOR_GIZMOS_H
-#define SPATIAL_EDITOR_GIZMOS_H
-
-
-#include "tools/editor/plugins/spatial_editor_plugin.h"
-#include "scene/3d/light.h"
-#include "scene/3d/camera.h"
-#include "scene/3d/position_3d.h"
-#include "scene/3d/spatial_sample_player.h"
-#include "scene/3d/spatial_stream_player.h"
-#include "scene/3d/test_cube.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/3d/body_shape.h"
-#include "scene/3d/room_instance.h"
-#include "scene/3d/visibility_notifier.h"
-#include "scene/3d/portal.h"
-#include "scene/3d/ray_cast.h"
-#include "scene/3d/navigation_mesh.h"
-
-#include "scene/3d/vehicle_body.h"
-#include "scene/3d/collision_polygon.h"
-#include "scene/3d/physics_joint.h"
-
-
-class Camera;
-
-class SpatialGizmoTool : public SpatialEditorGizmo {
-
- OBJ_TYPE(SpatialGizmoTool,SpatialGizmo);
-
- struct Instance{
-
- RID instance;
- Ref<Mesh> mesh;
- RID skeleton;
- bool billboard;
- bool unscaled;
- bool can_intersect;
- bool extra_margin;
- Instance() {
-
- billboard=false;
- unscaled=false;
- can_intersect=false;
- extra_margin=false;
- }
-
- void create_instance(Spatial *p_base);
-
- };
-
- Vector<Vector3> collision_segments;
- Ref<TriangleMesh> collision_mesh;
-
- struct Handle {
- Vector3 pos;
- bool billboard;
- };
-
- Vector<Vector3> handles;
- Vector<Vector3> secondary_handles;
- bool billboard_handle;
-
- bool valid;
- Spatial *base;
- Vector<Instance> instances;
- Spatial *spatial_node;
-protected:
- void add_lines(const Vector<Vector3> &p_lines,const Ref<Material>& p_material,bool p_billboard=false);
- void add_mesh(const Ref<Mesh>& p_mesh,bool p_billboard=false,const RID& p_skeleton=RID());
- void add_collision_segments(const Vector<Vector3> &p_lines);
- void add_collision_triangles(const Ref<TriangleMesh>& p_tmesh);
- void add_unscaled_billboard(const Ref<Material>& p_material,float p_scale=1);
- void add_handles(const Vector<Vector3> &p_handles,bool p_billboard=false,bool p_secondary=false);
-
- void set_spatial_node(Spatial *p_node);
-
-public:
-
- virtual Vector3 get_handle_pos(int p_idx) const;
- virtual bool intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum);
- virtual bool intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle=NULL,bool p_sec_first=false);
-
- void clear();
- void create();
- void transform();
- //void redraw();
- void free();
-
- SpatialGizmoTool();
- ~SpatialGizmoTool();
-};
-
-
-
-class LightSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(LightSpatialGizmo,SpatialGizmoTool);
-
- Light* light;
-
-public:
-
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- LightSpatialGizmo(Light* p_light=NULL);
-
-};
-
-class CameraSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(CameraSpatialGizmo,SpatialGizmoTool);
-
- Camera* camera;
-
-public:
-
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- CameraSpatialGizmo(Camera* p_camera=NULL);
-
-};
-
-
-
-class MeshInstanceSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(MeshInstanceSpatialGizmo,SpatialGizmoTool);
-
- MeshInstance* mesh;
-
-public:
-
- void redraw();
- MeshInstanceSpatialGizmo(MeshInstance* p_mesh=NULL);
-
-};
-
-class Position3DSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(Position3DSpatialGizmo,SpatialGizmoTool);
-
- Position3D* p3d;
-
-public:
-
- void redraw();
- Position3DSpatialGizmo(Position3D* p_p3d=NULL);
-
-};
-
-class SkeletonSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(SkeletonSpatialGizmo,SpatialGizmoTool);
-
- Skeleton* skel;
-
-public:
-
- void redraw();
- SkeletonSpatialGizmo(Skeleton* p_skel=NULL);
-
-};
-
-
-
-
-class SpatialPlayerSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(SpatialPlayerSpatialGizmo,SpatialGizmoTool);
-
- SpatialPlayer* splayer;
-
-public:
-
- void redraw();
- SpatialPlayerSpatialGizmo(SpatialPlayer* p_splayer=NULL);
-
-};
-
-
-
-class TestCubeSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(TestCubeSpatialGizmo,SpatialGizmoTool);
-
- TestCube* tc;
-
-public:
- void redraw();
- TestCubeSpatialGizmo(TestCube* p_tc=NULL);
-
-};
-
-
-class RoomSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(RoomSpatialGizmo,SpatialGizmoTool);
-
-
- struct _EdgeKey {
-
- Vector3 from;
- Vector3 to;
-
- bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; }
- };
-
-
-
- Room* room;
-
-public:
-
- void redraw();
- RoomSpatialGizmo(Room* p_room=NULL);
-
-};
-
-
-class PortalSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(PortalSpatialGizmo,SpatialGizmoTool);
-
- Portal* portal;
-
-public:
-
- void redraw();
- PortalSpatialGizmo(Portal* p_portal=NULL);
-
-};
-
-
-class VisibilityNotifierGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(VisibilityNotifierGizmo ,SpatialGizmoTool);
-
-
- VisibilityNotifier* notifier;
-
-public:
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- VisibilityNotifierGizmo(VisibilityNotifier* p_notifier=NULL);
-
-};
-
-
-
-class CollisionShapeSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(CollisionShapeSpatialGizmo,SpatialGizmoTool);
-
- CollisionShape* cs;
-
-public:
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
- void redraw();
- CollisionShapeSpatialGizmo(CollisionShape* p_cs=NULL);
-
-};
-
-
-class CollisionPolygonSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(CollisionPolygonSpatialGizmo,SpatialGizmoTool);
-
- CollisionPolygon* polygon;
-
-public:
-
- void redraw();
- CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon=NULL);
-
-};
-
-
-class RayCastSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(RayCastSpatialGizmo,SpatialGizmoTool);
-
- RayCast* raycast;
-
-public:
-
- void redraw();
- RayCastSpatialGizmo(RayCast* p_raycast=NULL);
-
-};
-
-
-
-class VehicleWheelSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(VehicleWheelSpatialGizmo,SpatialGizmoTool);
-
- VehicleWheel* car_wheel;
-
-public:
-
- void redraw();
- VehicleWheelSpatialGizmo(VehicleWheel* p_car_wheel=NULL);
-
-};
-
-
-class NavigationMeshSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(NavigationMeshSpatialGizmo,SpatialGizmoTool);
-
-
- struct _EdgeKey {
-
- Vector3 from;
- Vector3 to;
-
- bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; }
- };
-
-
-
- NavigationMeshInstance* navmesh;
-
-public:
-
- void redraw();
- NavigationMeshSpatialGizmo(NavigationMeshInstance* p_navmesh=NULL);
-
-};
-
-
-class PinJointSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(PinJointSpatialGizmo,SpatialGizmoTool);
-
- PinJoint* p3d;
-
-public:
-
- void redraw();
- PinJointSpatialGizmo(PinJoint* p_p3d=NULL);
-
-};
-
-
-class HingeJointSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(HingeJointSpatialGizmo,SpatialGizmoTool);
-
- HingeJoint* p3d;
-
-public:
-
- void redraw();
- HingeJointSpatialGizmo(HingeJoint* p_p3d=NULL);
-
-};
-
-class SliderJointSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(SliderJointSpatialGizmo,SpatialGizmoTool);
-
- SliderJoint* p3d;
-
-public:
-
- void redraw();
- SliderJointSpatialGizmo(SliderJoint* p_p3d=NULL);
-
-};
-
-class ConeTwistJointSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(ConeTwistJointSpatialGizmo,SpatialGizmoTool);
-
- ConeTwistJoint* p3d;
-
-public:
-
- void redraw();
- ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d=NULL);
-
-};
-
-
-class Generic6DOFJointSpatialGizmo : public SpatialGizmoTool {
-
- OBJ_TYPE(Generic6DOFJointSpatialGizmo,SpatialGizmoTool);
-
- Generic6DOFJoint* p3d;
-
-public:
-
- void redraw();
- Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d=NULL);
-
-};
-
-
-class SpatialEditorGizmos {
-public:
-
- Ref<FixedMaterial> create_line_material(const Color& p_base_color);
- Ref<FixedMaterial> create_solid_material(const Color& p_base_color);
- Ref<FixedMaterial> handle2_material;
- Ref<FixedMaterial> handle_material;
- Ref<FixedMaterial> light_material;
- Ref<FixedMaterial> light_material_omni_icon;
- Ref<FixedMaterial> light_material_directional_icon;
- Ref<FixedMaterial> camera_material;
- Ref<FixedMaterial> skeleton_material;
- Ref<FixedMaterial> room_material;
- Ref<FixedMaterial> portal_material;
- Ref<FixedMaterial> raycast_material;
- Ref<FixedMaterial> visibility_notifier_material;
- Ref<FixedMaterial> car_wheel_material;
- Ref<FixedMaterial> joint_material;
-
- Ref<FixedMaterial> navmesh_edge_material;
- Ref<FixedMaterial> navmesh_solid_material;
- Ref<FixedMaterial> navmesh_edge_material_disabled;
- Ref<FixedMaterial> navmesh_solid_material_disabled;
-
-
- Ref<FixedMaterial> sample_player_icon;
- Ref<FixedMaterial> stream_player_icon;
- Ref<FixedMaterial> visibility_notifier_icon;
-
- Ref<FixedMaterial> shape_material;
- Ref<Texture> handle_t;
-
- Ref<Mesh> pos3d_mesh;
- static SpatialEditorGizmos *singleton;
-
- Ref<TriangleMesh> test_cube_tm;
-
-
- Ref<SpatialEditorGizmo> get_gizmo(Spatial *p_spatial);
-
- SpatialEditorGizmos();
-};
-
-#endif // SPATIAL_EDITOR_GIZMOS_H
-
+/*************************************************************************/ +/* spatial_editor_gizmos.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef SPATIAL_EDITOR_GIZMOS_H +#define SPATIAL_EDITOR_GIZMOS_H + + +#include "tools/editor/plugins/spatial_editor_plugin.h" +#include "scene/3d/light.h" +#include "scene/3d/camera.h" +#include "scene/3d/position_3d.h" +#include "scene/3d/spatial_sample_player.h" +#include "scene/3d/spatial_stream_player.h" +#include "scene/3d/test_cube.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/body_shape.h" +#include "scene/3d/room_instance.h" +#include "scene/3d/visibility_notifier.h" +#include "scene/3d/portal.h" +#include "scene/3d/ray_cast.h" +#include "scene/3d/navigation_mesh.h" + +#include "scene/3d/vehicle_body.h" +#include "scene/3d/collision_polygon.h" +#include "scene/3d/physics_joint.h" + + +class Camera; + +class SpatialGizmoTool : public SpatialEditorGizmo { + + OBJ_TYPE(SpatialGizmoTool,SpatialGizmo); + + struct Instance{ + + RID instance; + Ref<Mesh> mesh; + RID skeleton; + bool billboard; + bool unscaled; + bool can_intersect; + bool extra_margin; + Instance() { + + billboard=false; + unscaled=false; + can_intersect=false; + extra_margin=false; + } + + void create_instance(Spatial *p_base); + + }; + + Vector<Vector3> collision_segments; + Ref<TriangleMesh> collision_mesh; + + struct Handle { + Vector3 pos; + bool billboard; + }; + + Vector<Vector3> handles; + Vector<Vector3> secondary_handles; + bool billboard_handle; + + bool valid; + Spatial *base; + Vector<Instance> instances; + Spatial *spatial_node; +protected: + void add_lines(const Vector<Vector3> &p_lines,const Ref<Material>& p_material,bool p_billboard=false); + void add_mesh(const Ref<Mesh>& p_mesh,bool p_billboard=false,const RID& p_skeleton=RID()); + void add_collision_segments(const Vector<Vector3> &p_lines); + void add_collision_triangles(const Ref<TriangleMesh>& p_tmesh); + void add_unscaled_billboard(const Ref<Material>& p_material,float p_scale=1); + void add_handles(const Vector<Vector3> &p_handles,bool p_billboard=false,bool p_secondary=false); + + void set_spatial_node(Spatial *p_node); + +public: + + virtual Vector3 get_handle_pos(int p_idx) const; + virtual bool intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum); + virtual bool intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle=NULL,bool p_sec_first=false); + + void clear(); + void create(); + void transform(); + //void redraw(); + void free(); + + SpatialGizmoTool(); + ~SpatialGizmoTool(); +}; + + + +class LightSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(LightSpatialGizmo,SpatialGizmoTool); + + Light* light; + +public: + + + virtual String get_handle_name(int p_idx) const; + virtual Variant get_handle_value(int p_idx) const; + virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point); + virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false); + + void redraw(); + LightSpatialGizmo(Light* p_light=NULL); + +}; + +class CameraSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(CameraSpatialGizmo,SpatialGizmoTool); + + Camera* camera; + +public: + + + virtual String get_handle_name(int p_idx) const; + virtual Variant get_handle_value(int p_idx) const; + virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point); + virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false); + + void redraw(); + CameraSpatialGizmo(Camera* p_camera=NULL); + +}; + + + +class MeshInstanceSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(MeshInstanceSpatialGizmo,SpatialGizmoTool); + + MeshInstance* mesh; + +public: + + void redraw(); + MeshInstanceSpatialGizmo(MeshInstance* p_mesh=NULL); + +}; + +class Position3DSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(Position3DSpatialGizmo,SpatialGizmoTool); + + Position3D* p3d; + +public: + + void redraw(); + Position3DSpatialGizmo(Position3D* p_p3d=NULL); + +}; + +class SkeletonSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(SkeletonSpatialGizmo,SpatialGizmoTool); + + Skeleton* skel; + +public: + + void redraw(); + SkeletonSpatialGizmo(Skeleton* p_skel=NULL); + +}; + + + + +class SpatialPlayerSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(SpatialPlayerSpatialGizmo,SpatialGizmoTool); + + SpatialPlayer* splayer; + +public: + + void redraw(); + SpatialPlayerSpatialGizmo(SpatialPlayer* p_splayer=NULL); + +}; + + + +class TestCubeSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(TestCubeSpatialGizmo,SpatialGizmoTool); + + TestCube* tc; + +public: + void redraw(); + TestCubeSpatialGizmo(TestCube* p_tc=NULL); + +}; + + +class RoomSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(RoomSpatialGizmo,SpatialGizmoTool); + + + struct _EdgeKey { + + Vector3 from; + Vector3 to; + + bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; } + }; + + + + Room* room; + +public: + + void redraw(); + RoomSpatialGizmo(Room* p_room=NULL); + +}; + + +class PortalSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(PortalSpatialGizmo,SpatialGizmoTool); + + Portal* portal; + +public: + + void redraw(); + PortalSpatialGizmo(Portal* p_portal=NULL); + +}; + + +class VisibilityNotifierGizmo : public SpatialGizmoTool { + + OBJ_TYPE(VisibilityNotifierGizmo ,SpatialGizmoTool); + + + VisibilityNotifier* notifier; + +public: + + virtual String get_handle_name(int p_idx) const; + virtual Variant get_handle_value(int p_idx) const; + virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point); + virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false); + + void redraw(); + VisibilityNotifierGizmo(VisibilityNotifier* p_notifier=NULL); + +}; + + + +class CollisionShapeSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(CollisionShapeSpatialGizmo,SpatialGizmoTool); + + CollisionShape* cs; + +public: + virtual String get_handle_name(int p_idx) const; + virtual Variant get_handle_value(int p_idx) const; + virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point); + virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false); + void redraw(); + CollisionShapeSpatialGizmo(CollisionShape* p_cs=NULL); + +}; + + +class CollisionPolygonSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(CollisionPolygonSpatialGizmo,SpatialGizmoTool); + + CollisionPolygon* polygon; + +public: + + void redraw(); + CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon=NULL); + +}; + + +class RayCastSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(RayCastSpatialGizmo,SpatialGizmoTool); + + RayCast* raycast; + +public: + + void redraw(); + RayCastSpatialGizmo(RayCast* p_raycast=NULL); + +}; + + + +class VehicleWheelSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(VehicleWheelSpatialGizmo,SpatialGizmoTool); + + VehicleWheel* car_wheel; + +public: + + void redraw(); + VehicleWheelSpatialGizmo(VehicleWheel* p_car_wheel=NULL); + +}; + + +class NavigationMeshSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(NavigationMeshSpatialGizmo,SpatialGizmoTool); + + + struct _EdgeKey { + + Vector3 from; + Vector3 to; + + bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; } + }; + + + + NavigationMeshInstance* navmesh; + +public: + + void redraw(); + NavigationMeshSpatialGizmo(NavigationMeshInstance* p_navmesh=NULL); + +}; + + +class PinJointSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(PinJointSpatialGizmo,SpatialGizmoTool); + + PinJoint* p3d; + +public: + + void redraw(); + PinJointSpatialGizmo(PinJoint* p_p3d=NULL); + +}; + + +class HingeJointSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(HingeJointSpatialGizmo,SpatialGizmoTool); + + HingeJoint* p3d; + +public: + + void redraw(); + HingeJointSpatialGizmo(HingeJoint* p_p3d=NULL); + +}; + +class SliderJointSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(SliderJointSpatialGizmo,SpatialGizmoTool); + + SliderJoint* p3d; + +public: + + void redraw(); + SliderJointSpatialGizmo(SliderJoint* p_p3d=NULL); + +}; + +class ConeTwistJointSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(ConeTwistJointSpatialGizmo,SpatialGizmoTool); + + ConeTwistJoint* p3d; + +public: + + void redraw(); + ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d=NULL); + +}; + + +class Generic6DOFJointSpatialGizmo : public SpatialGizmoTool { + + OBJ_TYPE(Generic6DOFJointSpatialGizmo,SpatialGizmoTool); + + Generic6DOFJoint* p3d; + +public: + + void redraw(); + Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d=NULL); + +}; + + +class SpatialEditorGizmos { +public: + + Ref<FixedMaterial> create_line_material(const Color& p_base_color); + Ref<FixedMaterial> create_solid_material(const Color& p_base_color); + Ref<FixedMaterial> handle2_material; + Ref<FixedMaterial> handle_material; + Ref<FixedMaterial> light_material; + Ref<FixedMaterial> light_material_omni_icon; + Ref<FixedMaterial> light_material_directional_icon; + Ref<FixedMaterial> camera_material; + Ref<FixedMaterial> skeleton_material; + Ref<FixedMaterial> room_material; + Ref<FixedMaterial> portal_material; + Ref<FixedMaterial> raycast_material; + Ref<FixedMaterial> visibility_notifier_material; + Ref<FixedMaterial> car_wheel_material; + Ref<FixedMaterial> joint_material; + + Ref<FixedMaterial> navmesh_edge_material; + Ref<FixedMaterial> navmesh_solid_material; + Ref<FixedMaterial> navmesh_edge_material_disabled; + Ref<FixedMaterial> navmesh_solid_material_disabled; + + + Ref<FixedMaterial> sample_player_icon; + Ref<FixedMaterial> stream_player_icon; + Ref<FixedMaterial> visibility_notifier_icon; + + Ref<FixedMaterial> shape_material; + Ref<Texture> handle_t; + + Ref<Mesh> pos3d_mesh; + static SpatialEditorGizmos *singleton; + + Ref<TriangleMesh> test_cube_tm; + + + Ref<SpatialEditorGizmo> get_gizmo(Spatial *p_spatial); + + SpatialEditorGizmos(); +}; + +#endif // SPATIAL_EDITOR_GIZMOS_H + diff --git a/tools/export/blender25/godot_export_manager.py b/tools/export/blender25/godot_export_manager.py index 31db2c9e94..e390ae6ce3 100644 --- a/tools/export/blender25/godot_export_manager.py +++ b/tools/export/blender25/godot_export_manager.py @@ -1,474 +1,474 @@ -# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# Script copyright (c) Andreas Esau
-
-bl_info = {
- "name": "Godot Export Manager",
- "author": "Andreas Esau",
- "version": (1, 0),
- "blender": (2, 7, 0),
- "location": "Scene Properties > Godot Export Manager",
- "description": "Godot Export Manager uses the Better Collada Exporter to manage Export Groups and automatically export the objects groups to Collada Files.",
- "warning": "",
- "wiki_url": ("http://www.godotengine.org"),
- "tracker_url": "",
- "category": "Import-Export"}
-
-import bpy
-from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatProperty, FloatVectorProperty, IntProperty, CollectionProperty, PointerProperty
-import os
-from bpy.app.handlers import persistent
-from mathutils import Vector, Matrix
-
-class godot_export_manager(bpy.types.Panel):
- bl_label = "Godot Export Manager"
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "scene"
-
- bpy.types.Scene.godot_export_on_save = BoolProperty(default=False)
-
- ### draw function for all ui elements
- def draw(self, context):
- layout = self.layout
- split = self.layout.split()
- scene = bpy.data.scenes[0]
- ob = context.object
- scene = context.scene
-
- row = layout.row()
- col = row.column()
- col.prop(scene,"godot_export_on_save",text="Export Groups on save")
-
- row = layout.row()
- col = row.column(align=True)
- op = col.operator("scene.godot_add_objects_to_group",text="Add selected objects to Group",icon="COPYDOWN")
-
- op = col.operator("scene.godot_delete_objects_from_group",text="Delete selected objects from Group",icon="PASTEDOWN")
-
-
-
- row = layout.row()
- col = row.column()
- col.label(text="Export Groups:")
-
-
- row = layout.row()
- col = row.column()
-
- col.template_list("UI_List_Godot","dummy",scene, "godot_export_groups", scene, "godot_export_groups_index",rows=1,maxrows=10,type='DEFAULT')
-
- col = row.column(align=True)
- col.operator("scene.godot_add_export_group",text="",icon="ZOOMIN")
- col.operator("scene.godot_delete_export_group",text="",icon="ZOOMOUT")
- col.operator("scene.godot_export_all_groups",text="",icon="EXPORT")
-
- if len(scene.godot_export_groups) > 0:
- row = layout.row()
- col = row.column()
- group = scene.godot_export_groups[scene.godot_export_groups_index]
- col.prop(group,"name",text="Group Name")
- col.prop(group,"export_name",text="Export Name")
- col.prop(group,"export_path",text="Export Filepath")
-
- row = layout.row()
- col = row.column()
- row = layout.row()
- col = row.column()
- col.label(text="Export Settings:")
-
- col = col.row(align=True)
- col.prop(group,"apply_loc",toggle=True,icon="MAN_TRANS")
- col.prop(group,"apply_rot",toggle=True,icon="MAN_ROT")
- col.prop(group,"apply_scale",toggle=True,icon="MAN_SCALE")
-
- row = layout.row()
- col = row.column()
-
- col.prop(group,"use_include_particle_duplicates")
- col.prop(group,"use_mesh_modifiers")
- col.prop(group,"use_tangent_arrays")
- col.prop(group,"use_triangles")
- col.prop(group,"use_copy_images")
- col.prop(group,"use_active_layers")
- col.prop(group,"use_exclude_ctrl_bones")
- col.prop(group,"use_anim")
- col.prop(group,"use_anim_action_all")
- col.prop(group,"use_anim_skip_noexp")
- col.prop(group,"use_anim_optimize")
- col.prop(group,"anim_optimize_precision")
- col.prop(group,"use_metadata")
-
-### Custom template_list look
-class UI_List_Godot(bpy.types.UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- ob = data
- slot = item
- col = layout.row(align=True)
-
- col.label(text=item.name,icon="GROUP")
- col.prop(item,"active",text="")
-
- op = col.operator("scene.godot_select_group_objects",text="",emboss=False,icon="RESTRICT_SELECT_OFF")
- op.idx = index
- op = col.operator("scene.godot_export_group",text="",emboss=False,icon="EXPORT")
- op.idx = index
-
-class add_objects_to_group(bpy.types.Operator):
- bl_idname = "scene.godot_add_objects_to_group"
- bl_label = "Add Objects to Group"
- bl_description = "Adds the selected Objects to the active group below."
-
- undo = BoolProperty(default=True)
-
- def execute(self,context):
- scene = context.scene
-
- objects_str = ""
- if len(scene.godot_export_groups) > 0:
- for i,object in enumerate(context.selected_objects):
- if object.name not in scene.godot_export_groups[scene.godot_export_groups_index].nodes:
- node = scene.godot_export_groups[scene.godot_export_groups_index].nodes.add()
- node.name = object.name
- if i == 0:
- objects_str += object.name
- else:
- objects_str += ", "+object.name
-
-
- self.report({'INFO'}, objects_str + " added to group." )
- if self.undo:
- bpy.ops.ed.undo_push(message="Objects added to group")
- else:
- self.report({'WARNING'}, "Create a group first." )
- return{'FINISHED'}
-
-class del_objects_from_group(bpy.types.Operator):
- bl_idname = "scene.godot_delete_objects_from_group"
- bl_label = "Delete Objects from Group"
- bl_description = "Delets the selected Objects from the active group below."
-
- def execute(self,context):
- scene = context.scene
-
- if len(scene.godot_export_groups) > 0:
-
- selected_objects = []
- for object in context.selected_objects:
- selected_objects.append(object.name)
-
- objects_str = ""
- j = 0
- for i,node in enumerate(scene.godot_export_groups[scene.godot_export_groups_index].nodes):
- if node.name in selected_objects:
- scene.godot_export_groups[scene.godot_export_groups_index].nodes.remove(i)
-
-
- if j == 0:
- objects_str += object.name
- else:
- objects_str += ", "+object.name
- j+=1
-
-
- self.report({'INFO'}, objects_str + " deleted from group." )
- bpy.ops.ed.undo_push(message="Objects deleted from group")
- else:
- self.report({'WARNING'}, "There is no group to delete from." )
- return{'FINISHED'}
-
-class select_group_objects(bpy.types.Operator):
- bl_idname = "scene.godot_select_group_objects"
- bl_label = "Select Group Objects"
- bl_description = "Will select all group Objects in the scene."
-
- idx = IntProperty()
-
- def execute(self,context):
- scene = context.scene
- for object in context.scene.objects:
- object.select = False
- for node in scene.godot_export_groups[self.idx].nodes:
- if node.name in bpy.data.objects:
- bpy.data.objects[node.name].select = True
- context.scene.objects.active = bpy.data.objects[node.name]
- return{'FINISHED'}
-
-class export_groups_autosave(bpy.types.Operator):
- bl_idname = "scene.godot_export_groups_autosave"
- bl_label = "Export All Groups"
- bl_description = "Exports all groups to Collada."
-
- def execute(self,context):
- scene = context.scene
- if scene.godot_export_on_save:
- for i in range(len(scene.godot_export_groups)):
- if scene.godot_export_groups[i].active:
- bpy.ops.scene.godot_export_group(idx=i)
- self.report({'INFO'}, "All Groups exported." )
- bpy.ops.ed.undo_push(message="Export all Groups")
- return{'FINISHED'}
-
-class export_all_groups(bpy.types.Operator):
- bl_idname = "scene.godot_export_all_groups"
- bl_label = "Export All Groups"
- bl_description = "Exports all groups to Collada."
-
- def execute(self,context):
- scene = context.scene
-
- for i in range(0,len(scene.godot_export_groups)):
- bpy.ops.scene.godot_export_group(idx=i,export_all=True)
-
- self.report({'INFO'}, "All Groups exported." )
- return{'FINISHED'}
-
-
-class export_group(bpy.types.Operator):
- bl_idname = "scene.godot_export_group"
- bl_label = "Export Group"
- bl_description = "Exports the active group to destination folder as Collada file."
-
- idx = IntProperty(default=0)
- export_all = BoolProperty(default=False)
-
-
- def copy_object_recursive(self,ob,parent,single_user = True):
- new_ob = bpy.data.objects[ob.name].copy()
- if single_user or ob.type=="ARMATURE":
- new_mesh_data = new_ob.data.copy()
- new_ob.data = new_mesh_data
- bpy.context.scene.objects.link(new_ob)
-
- if ob != parent:
- new_ob.parent = parent
- else:
- new_ob.parent = None
-
- for child in ob.children:
- self.copy_object_recursive(child,new_ob,single_user)
- new_ob.select = True
- return new_ob
-
- def delete_object(self,ob):
- if ob != None:
- for child in ob.children:
- self.delete_object(child)
- bpy.context.scene.objects.unlink(ob)
- bpy.data.objects.remove(ob)
-
- def convert_group_to_node(self,group):
- if group.dupli_group != None:
- for object in group.dupli_group.objects:
- if object.parent == None:
- object = self.copy_object_recursive(object,object,True)
- matrix = Matrix(object.matrix_local)
- object.matrix_local = Matrix()
- object.matrix_local *= group.matrix_local
- object.matrix_local *= matrix
-
- self.delete_object(group)
-
- def execute(self,context):
-
- scene = context.scene
- group = context.scene.godot_export_groups
-
- if not group[self.idx].active and self.export_all:
- return{'FINISHED'}
-
- for i,object in enumerate(group[self.idx].nodes):
- if object.name in bpy.data.objects:
- pass
- else:
- group[self.idx].nodes.remove(i)
- bpy.ops.ed.undo_push(message="Clear not existent Group Nodes.")
-
- path = group[self.idx].export_path
- if (path.find("//")==0 or path.find("\\\\")==0):
- #if relative, convert to absolute
- path = bpy.path.abspath(path)
- path = path.replace("\\","/")
-
- ### if path exists and group export name is set the group will be exported
- if os.path.exists(path) and group[self.idx].export_name != "":
-
- context.scene.layers = [True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True]
-
-
- if group[self.idx].export_name.endswith(".dae"):
- path = os.path.join(path,group[self.idx].export_name)
- else:
- path = os.path.join(path,group[self.idx].export_name+".dae")
-
- hide_select = []
- for object in context.scene.objects:
- hide_select.append(object.hide_select)
- object.hide_select = False
- object.select = False
- context.scene.objects.active = None
-
- ### make particle duplicates, parent and select them
- nodes_to_be_added = []
- if group[self.idx].use_include_particle_duplicates:
- for i,object in enumerate(group[self.idx].nodes):
- if bpy.data.objects[object.name].type != "EMPTY":
- context.scene.objects.active = bpy.data.objects[object.name]
- bpy.data.objects[object.name].select = True
- bpy.ops.object.duplicates_make_real()
- for object in context.selected_objects:
- nodes_to_be_added.append(object)
- bpy.ops.object.parent_set(type="OBJECT", keep_transform=False)
-
- for object in context.selected_objects:
- object.select = False
- bpy.data.objects[object.name].select = False
- context.scene.objects.active = None
- for object in nodes_to_be_added:
- object.select = True
-
- ### select all other nodes from the group
- for i,object in enumerate(group[self.idx].nodes):
- if bpy.data.objects[object.name].type == "EMPTY":
- self.convert_group_to_node(bpy.data.objects[object.name])
- else:
- bpy.data.objects[object.name].select = True
-
- bpy.ops.object.transform_apply(location=group[self.idx].apply_loc, rotation=group[self.idx].apply_rot, scale=group[self.idx].apply_scale)
- bpy.ops.export_scene.dae(check_existing=True, filepath=path, filter_glob="*.dae", object_types=group[self.idx].object_types, use_export_selected=group[self.idx].use_export_selected, use_mesh_modifiers=group[self.idx].use_mesh_modifiers, use_tangent_arrays=group[self.idx].use_tangent_arrays, use_triangles=group[self.idx].use_triangles, use_copy_images=group[self.idx].use_copy_images, use_active_layers=group[self.idx].use_active_layers, use_exclude_ctrl_bones=group[self.idx].use_exclude_ctrl_bones, use_anim=group[self.idx].use_anim, use_anim_action_all=group[self.idx].use_anim_action_all, use_anim_skip_noexp=group[self.idx].use_anim_skip_noexp, use_anim_optimize=group[self.idx].use_anim_optimize, anim_optimize_precision=group[self.idx].anim_optimize_precision, use_metadata=group[self.idx].use_metadata)
-
- self.report({'INFO'}, '"'+group[self.idx].name+'"' + " Group exported." )
- msg = "Export Group "+group[self.idx].name
-
- bpy.ops.ed.undo_push(message="")
- bpy.ops.ed.undo()
- bpy.ops.ed.undo_push(message=msg)
-
- else:
- self.report({'INFO'}, "Define Export Name and Export Path." )
- return{'FINISHED'}
-
-class add_export_group(bpy.types.Operator):
- bl_idname = "scene.godot_add_export_group"
- bl_label = "Adds a new export Group"
- bl_description = "Creates a new Export Group with the selected Objects assigned to it."
-
- def execute(self,context):
- scene = context.scene
-
- item = scene.godot_export_groups.add()
- item.name = "New Group"
- for object in context.selected_objects:
- node = item.nodes.add()
- node.name = object.name
- scene.godot_export_groups_index = len(scene.godot_export_groups)-1
- bpy.ops.ed.undo_push(message="Create New Export Group")
- return{'FINISHED'}
-
-class del_export_group(bpy.types.Operator):
- bl_idname = "scene.godot_delete_export_group"
- bl_label = "Delets the selected export Group"
- bl_description = "Delets the active Export Group."
-
- def invoke(self, context, event):
- wm = context.window_manager
- return wm.invoke_confirm(self,event)
-
- def execute(self,context):
- scene = context.scene
-
- scene.godot_export_groups.remove(scene.godot_export_groups_index)
- if scene.godot_export_groups_index > 0:
- scene.godot_export_groups_index -= 1
- bpy.ops.ed.undo_push(message="Delete Export Group")
- return{'FINISHED'}
-
-class godot_node_list(bpy.types.PropertyGroup):
- name = StringProperty()
-
-class godot_export_groups(bpy.types.PropertyGroup):
- name = StringProperty(name="Group Name")
- export_name = StringProperty(name="scene_name")
- nodes = CollectionProperty(type=godot_node_list)
- export_path = StringProperty(subtype="DIR_PATH")
- active = BoolProperty(default=True,description="Export Group")
-
- object_types = EnumProperty(name="Object Types",options={'ENUM_FLAG'},items=(('EMPTY', "Empty", ""),('CAMERA', "Camera", ""),('LAMP', "Lamp", ""),('ARMATURE', "Armature", ""),('MESH', "Mesh", ""),('CURVE', "Curve", ""),),default={'EMPTY', 'CAMERA', 'LAMP', 'ARMATURE', 'MESH','CURVE'})
-
- apply_scale = BoolProperty(name="Apply Scale",description="Apply Scale before export.",default=False)
- apply_rot = BoolProperty(name="Apply Rotation",description="Apply Rotation before export.",default=False)
- apply_loc = BoolProperty(name="Apply Location",description="Apply Location before export.",default=False)
-
- use_export_selected = BoolProperty(name="Selected Objects",description="Export only selected objects (and visible in active layers if that applies).",default=True)
- use_mesh_modifiers = BoolProperty(name="Apply Modifiers",description="Apply modifiers to mesh objects (on a copy!).",default=True)
- use_tangent_arrays = BoolProperty(name="Tangent Arrays",description="Export Tangent and Binormal arrays (for normalmapping).",default=False)
- use_triangles = BoolProperty(name="Triangulate",description="Export Triangles instead of Polygons.",default=False)
-
- use_copy_images = BoolProperty(name="Copy Images",description="Copy Images (create images/ subfolder)",default=False)
- use_active_layers = BoolProperty(name="Active Layers",description="Export only objects on the active layers.",default=True)
- use_exclude_ctrl_bones = BoolProperty(name="Exclude Control Bones",description="Exclude skeleton bones with names that begin with 'ctrl'.",default=True)
- use_anim = BoolProperty(name="Export Animation",description="Export keyframe animation",default=False)
- use_anim_action_all = BoolProperty(name="All Actions",description=("Export all actions for the first armature found in separate DAE files"),default=False)
- use_anim_skip_noexp = BoolProperty(name="Skip (-noexp) Actions",description="Skip exporting of actions whose name end in (-noexp). Useful to skip control animations.",default=True)
- use_anim_optimize = BoolProperty(name="Optimize Keyframes",description="Remove double keyframes",default=True)
-
- anim_optimize_precision = FloatProperty(name="Precision",description=("Tolerence for comparing double keyframes (higher for greater accuracy)"),min=1, max=16,soft_min=1, soft_max=16,default=6.0)
-
- use_metadata = BoolProperty(name="Use Metadata",default=True,options={'HIDDEN'})
- use_include_particle_duplicates = BoolProperty(name="Include Particle Duplicates",default=True)
-
-def register():
- bpy.utils.register_class(godot_export_manager)
- bpy.utils.register_class(godot_node_list)
- bpy.utils.register_class(godot_export_groups)
- bpy.utils.register_class(add_export_group)
- bpy.utils.register_class(del_export_group)
- bpy.utils.register_class(export_all_groups)
- bpy.utils.register_class(export_groups_autosave)
- bpy.utils.register_class(export_group)
- bpy.utils.register_class(add_objects_to_group)
- bpy.utils.register_class(del_objects_from_group)
- bpy.utils.register_class(select_group_objects)
- bpy.utils.register_class(UI_List_Godot)
-
- bpy.types.Scene.godot_export_groups = CollectionProperty(type=godot_export_groups)
- bpy.types.Scene.godot_export_groups_index = IntProperty(default=0,min=0)
-
-def unregister():
- bpy.utils.unregister_class(godot_export_manager)
- bpy.utils.unregister_class(godot_node_list)
- bpy.utils.unregister_class(godot_export_groups)
- bpy.utils.unregister_class(export_groups_autosave)
- bpy.utils.unregister_class(add_export_group)
- bpy.utils.unregister_class(del_export_group)
- bpy.utils.unregister_class(export_all_groups)
- bpy.utils.unregister_class(export_group)
- bpy.utils.unregister_class(add_objects_to_group)
- bpy.utils.unregister_class(del_objects_from_group)
- bpy.utils.unregister_class(select_group_objects)
- bpy.utils.unregister_class(UI_List_Godot)
-
-@persistent
-def auto_export(dummy):
- bpy.ops.scene.godot_export_groups_autosave()
-
-bpy.app.handlers.save_post.append(auto_export)
-
-if __name__ == "__main__":
- register()
+# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Script copyright (c) Andreas Esau + +bl_info = { + "name": "Godot Export Manager", + "author": "Andreas Esau", + "version": (1, 0), + "blender": (2, 7, 0), + "location": "Scene Properties > Godot Export Manager", + "description": "Godot Export Manager uses the Better Collada Exporter to manage Export Groups and automatically export the objects groups to Collada Files.", + "warning": "", + "wiki_url": ("http://www.godotengine.org"), + "tracker_url": "", + "category": "Import-Export"} + +import bpy +from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatProperty, FloatVectorProperty, IntProperty, CollectionProperty, PointerProperty +import os +from bpy.app.handlers import persistent +from mathutils import Vector, Matrix + +class godot_export_manager(bpy.types.Panel): + bl_label = "Godot Export Manager" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "scene" + + bpy.types.Scene.godot_export_on_save = BoolProperty(default=False) + + ### draw function for all ui elements + def draw(self, context): + layout = self.layout + split = self.layout.split() + scene = bpy.data.scenes[0] + ob = context.object + scene = context.scene + + row = layout.row() + col = row.column() + col.prop(scene,"godot_export_on_save",text="Export Groups on save") + + row = layout.row() + col = row.column(align=True) + op = col.operator("scene.godot_add_objects_to_group",text="Add selected objects to Group",icon="COPYDOWN") + + op = col.operator("scene.godot_delete_objects_from_group",text="Delete selected objects from Group",icon="PASTEDOWN") + + + + row = layout.row() + col = row.column() + col.label(text="Export Groups:") + + + row = layout.row() + col = row.column() + + col.template_list("UI_List_Godot","dummy",scene, "godot_export_groups", scene, "godot_export_groups_index",rows=1,maxrows=10,type='DEFAULT') + + col = row.column(align=True) + col.operator("scene.godot_add_export_group",text="",icon="ZOOMIN") + col.operator("scene.godot_delete_export_group",text="",icon="ZOOMOUT") + col.operator("scene.godot_export_all_groups",text="",icon="EXPORT") + + if len(scene.godot_export_groups) > 0: + row = layout.row() + col = row.column() + group = scene.godot_export_groups[scene.godot_export_groups_index] + col.prop(group,"name",text="Group Name") + col.prop(group,"export_name",text="Export Name") + col.prop(group,"export_path",text="Export Filepath") + + row = layout.row() + col = row.column() + row = layout.row() + col = row.column() + col.label(text="Export Settings:") + + col = col.row(align=True) + col.prop(group,"apply_loc",toggle=True,icon="MAN_TRANS") + col.prop(group,"apply_rot",toggle=True,icon="MAN_ROT") + col.prop(group,"apply_scale",toggle=True,icon="MAN_SCALE") + + row = layout.row() + col = row.column() + + col.prop(group,"use_include_particle_duplicates") + col.prop(group,"use_mesh_modifiers") + col.prop(group,"use_tangent_arrays") + col.prop(group,"use_triangles") + col.prop(group,"use_copy_images") + col.prop(group,"use_active_layers") + col.prop(group,"use_exclude_ctrl_bones") + col.prop(group,"use_anim") + col.prop(group,"use_anim_action_all") + col.prop(group,"use_anim_skip_noexp") + col.prop(group,"use_anim_optimize") + col.prop(group,"anim_optimize_precision") + col.prop(group,"use_metadata") + +### Custom template_list look +class UI_List_Godot(bpy.types.UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): + ob = data + slot = item + col = layout.row(align=True) + + col.label(text=item.name,icon="GROUP") + col.prop(item,"active",text="") + + op = col.operator("scene.godot_select_group_objects",text="",emboss=False,icon="RESTRICT_SELECT_OFF") + op.idx = index + op = col.operator("scene.godot_export_group",text="",emboss=False,icon="EXPORT") + op.idx = index + +class add_objects_to_group(bpy.types.Operator): + bl_idname = "scene.godot_add_objects_to_group" + bl_label = "Add Objects to Group" + bl_description = "Adds the selected Objects to the active group below." + + undo = BoolProperty(default=True) + + def execute(self,context): + scene = context.scene + + objects_str = "" + if len(scene.godot_export_groups) > 0: + for i,object in enumerate(context.selected_objects): + if object.name not in scene.godot_export_groups[scene.godot_export_groups_index].nodes: + node = scene.godot_export_groups[scene.godot_export_groups_index].nodes.add() + node.name = object.name + if i == 0: + objects_str += object.name + else: + objects_str += ", "+object.name + + + self.report({'INFO'}, objects_str + " added to group." ) + if self.undo: + bpy.ops.ed.undo_push(message="Objects added to group") + else: + self.report({'WARNING'}, "Create a group first." ) + return{'FINISHED'} + +class del_objects_from_group(bpy.types.Operator): + bl_idname = "scene.godot_delete_objects_from_group" + bl_label = "Delete Objects from Group" + bl_description = "Delets the selected Objects from the active group below." + + def execute(self,context): + scene = context.scene + + if len(scene.godot_export_groups) > 0: + + selected_objects = [] + for object in context.selected_objects: + selected_objects.append(object.name) + + objects_str = "" + j = 0 + for i,node in enumerate(scene.godot_export_groups[scene.godot_export_groups_index].nodes): + if node.name in selected_objects: + scene.godot_export_groups[scene.godot_export_groups_index].nodes.remove(i) + + + if j == 0: + objects_str += object.name + else: + objects_str += ", "+object.name + j+=1 + + + self.report({'INFO'}, objects_str + " deleted from group." ) + bpy.ops.ed.undo_push(message="Objects deleted from group") + else: + self.report({'WARNING'}, "There is no group to delete from." ) + return{'FINISHED'} + +class select_group_objects(bpy.types.Operator): + bl_idname = "scene.godot_select_group_objects" + bl_label = "Select Group Objects" + bl_description = "Will select all group Objects in the scene." + + idx = IntProperty() + + def execute(self,context): + scene = context.scene + for object in context.scene.objects: + object.select = False + for node in scene.godot_export_groups[self.idx].nodes: + if node.name in bpy.data.objects: + bpy.data.objects[node.name].select = True + context.scene.objects.active = bpy.data.objects[node.name] + return{'FINISHED'} + +class export_groups_autosave(bpy.types.Operator): + bl_idname = "scene.godot_export_groups_autosave" + bl_label = "Export All Groups" + bl_description = "Exports all groups to Collada." + + def execute(self,context): + scene = context.scene + if scene.godot_export_on_save: + for i in range(len(scene.godot_export_groups)): + if scene.godot_export_groups[i].active: + bpy.ops.scene.godot_export_group(idx=i) + self.report({'INFO'}, "All Groups exported." ) + bpy.ops.ed.undo_push(message="Export all Groups") + return{'FINISHED'} + +class export_all_groups(bpy.types.Operator): + bl_idname = "scene.godot_export_all_groups" + bl_label = "Export All Groups" + bl_description = "Exports all groups to Collada." + + def execute(self,context): + scene = context.scene + + for i in range(0,len(scene.godot_export_groups)): + bpy.ops.scene.godot_export_group(idx=i,export_all=True) + + self.report({'INFO'}, "All Groups exported." ) + return{'FINISHED'} + + +class export_group(bpy.types.Operator): + bl_idname = "scene.godot_export_group" + bl_label = "Export Group" + bl_description = "Exports the active group to destination folder as Collada file." + + idx = IntProperty(default=0) + export_all = BoolProperty(default=False) + + + def copy_object_recursive(self,ob,parent,single_user = True): + new_ob = bpy.data.objects[ob.name].copy() + if single_user or ob.type=="ARMATURE": + new_mesh_data = new_ob.data.copy() + new_ob.data = new_mesh_data + bpy.context.scene.objects.link(new_ob) + + if ob != parent: + new_ob.parent = parent + else: + new_ob.parent = None + + for child in ob.children: + self.copy_object_recursive(child,new_ob,single_user) + new_ob.select = True + return new_ob + + def delete_object(self,ob): + if ob != None: + for child in ob.children: + self.delete_object(child) + bpy.context.scene.objects.unlink(ob) + bpy.data.objects.remove(ob) + + def convert_group_to_node(self,group): + if group.dupli_group != None: + for object in group.dupli_group.objects: + if object.parent == None: + object = self.copy_object_recursive(object,object,True) + matrix = Matrix(object.matrix_local) + object.matrix_local = Matrix() + object.matrix_local *= group.matrix_local + object.matrix_local *= matrix + + self.delete_object(group) + + def execute(self,context): + + scene = context.scene + group = context.scene.godot_export_groups + + if not group[self.idx].active and self.export_all: + return{'FINISHED'} + + for i,object in enumerate(group[self.idx].nodes): + if object.name in bpy.data.objects: + pass + else: + group[self.idx].nodes.remove(i) + bpy.ops.ed.undo_push(message="Clear not existent Group Nodes.") + + path = group[self.idx].export_path + if (path.find("//")==0 or path.find("\\\\")==0): + #if relative, convert to absolute + path = bpy.path.abspath(path) + path = path.replace("\\","/") + + ### if path exists and group export name is set the group will be exported + if os.path.exists(path) and group[self.idx].export_name != "": + + context.scene.layers = [True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True] + + + if group[self.idx].export_name.endswith(".dae"): + path = os.path.join(path,group[self.idx].export_name) + else: + path = os.path.join(path,group[self.idx].export_name+".dae") + + hide_select = [] + for object in context.scene.objects: + hide_select.append(object.hide_select) + object.hide_select = False + object.select = False + context.scene.objects.active = None + + ### make particle duplicates, parent and select them + nodes_to_be_added = [] + if group[self.idx].use_include_particle_duplicates: + for i,object in enumerate(group[self.idx].nodes): + if bpy.data.objects[object.name].type != "EMPTY": + context.scene.objects.active = bpy.data.objects[object.name] + bpy.data.objects[object.name].select = True + bpy.ops.object.duplicates_make_real() + for object in context.selected_objects: + nodes_to_be_added.append(object) + bpy.ops.object.parent_set(type="OBJECT", keep_transform=False) + + for object in context.selected_objects: + object.select = False + bpy.data.objects[object.name].select = False + context.scene.objects.active = None + for object in nodes_to_be_added: + object.select = True + + ### select all other nodes from the group + for i,object in enumerate(group[self.idx].nodes): + if bpy.data.objects[object.name].type == "EMPTY": + self.convert_group_to_node(bpy.data.objects[object.name]) + else: + bpy.data.objects[object.name].select = True + + bpy.ops.object.transform_apply(location=group[self.idx].apply_loc, rotation=group[self.idx].apply_rot, scale=group[self.idx].apply_scale) + bpy.ops.export_scene.dae(check_existing=True, filepath=path, filter_glob="*.dae", object_types=group[self.idx].object_types, use_export_selected=group[self.idx].use_export_selected, use_mesh_modifiers=group[self.idx].use_mesh_modifiers, use_tangent_arrays=group[self.idx].use_tangent_arrays, use_triangles=group[self.idx].use_triangles, use_copy_images=group[self.idx].use_copy_images, use_active_layers=group[self.idx].use_active_layers, use_exclude_ctrl_bones=group[self.idx].use_exclude_ctrl_bones, use_anim=group[self.idx].use_anim, use_anim_action_all=group[self.idx].use_anim_action_all, use_anim_skip_noexp=group[self.idx].use_anim_skip_noexp, use_anim_optimize=group[self.idx].use_anim_optimize, anim_optimize_precision=group[self.idx].anim_optimize_precision, use_metadata=group[self.idx].use_metadata) + + self.report({'INFO'}, '"'+group[self.idx].name+'"' + " Group exported." ) + msg = "Export Group "+group[self.idx].name + + bpy.ops.ed.undo_push(message="") + bpy.ops.ed.undo() + bpy.ops.ed.undo_push(message=msg) + + else: + self.report({'INFO'}, "Define Export Name and Export Path." ) + return{'FINISHED'} + +class add_export_group(bpy.types.Operator): + bl_idname = "scene.godot_add_export_group" + bl_label = "Adds a new export Group" + bl_description = "Creates a new Export Group with the selected Objects assigned to it." + + def execute(self,context): + scene = context.scene + + item = scene.godot_export_groups.add() + item.name = "New Group" + for object in context.selected_objects: + node = item.nodes.add() + node.name = object.name + scene.godot_export_groups_index = len(scene.godot_export_groups)-1 + bpy.ops.ed.undo_push(message="Create New Export Group") + return{'FINISHED'} + +class del_export_group(bpy.types.Operator): + bl_idname = "scene.godot_delete_export_group" + bl_label = "Delets the selected export Group" + bl_description = "Delets the active Export Group." + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_confirm(self,event) + + def execute(self,context): + scene = context.scene + + scene.godot_export_groups.remove(scene.godot_export_groups_index) + if scene.godot_export_groups_index > 0: + scene.godot_export_groups_index -= 1 + bpy.ops.ed.undo_push(message="Delete Export Group") + return{'FINISHED'} + +class godot_node_list(bpy.types.PropertyGroup): + name = StringProperty() + +class godot_export_groups(bpy.types.PropertyGroup): + name = StringProperty(name="Group Name") + export_name = StringProperty(name="scene_name") + nodes = CollectionProperty(type=godot_node_list) + export_path = StringProperty(subtype="DIR_PATH") + active = BoolProperty(default=True,description="Export Group") + + object_types = EnumProperty(name="Object Types",options={'ENUM_FLAG'},items=(('EMPTY', "Empty", ""),('CAMERA', "Camera", ""),('LAMP', "Lamp", ""),('ARMATURE', "Armature", ""),('MESH', "Mesh", ""),('CURVE', "Curve", ""),),default={'EMPTY', 'CAMERA', 'LAMP', 'ARMATURE', 'MESH','CURVE'}) + + apply_scale = BoolProperty(name="Apply Scale",description="Apply Scale before export.",default=False) + apply_rot = BoolProperty(name="Apply Rotation",description="Apply Rotation before export.",default=False) + apply_loc = BoolProperty(name="Apply Location",description="Apply Location before export.",default=False) + + use_export_selected = BoolProperty(name="Selected Objects",description="Export only selected objects (and visible in active layers if that applies).",default=True) + use_mesh_modifiers = BoolProperty(name="Apply Modifiers",description="Apply modifiers to mesh objects (on a copy!).",default=True) + use_tangent_arrays = BoolProperty(name="Tangent Arrays",description="Export Tangent and Binormal arrays (for normalmapping).",default=False) + use_triangles = BoolProperty(name="Triangulate",description="Export Triangles instead of Polygons.",default=False) + + use_copy_images = BoolProperty(name="Copy Images",description="Copy Images (create images/ subfolder)",default=False) + use_active_layers = BoolProperty(name="Active Layers",description="Export only objects on the active layers.",default=True) + use_exclude_ctrl_bones = BoolProperty(name="Exclude Control Bones",description="Exclude skeleton bones with names that begin with 'ctrl'.",default=True) + use_anim = BoolProperty(name="Export Animation",description="Export keyframe animation",default=False) + use_anim_action_all = BoolProperty(name="All Actions",description=("Export all actions for the first armature found in separate DAE files"),default=False) + use_anim_skip_noexp = BoolProperty(name="Skip (-noexp) Actions",description="Skip exporting of actions whose name end in (-noexp). Useful to skip control animations.",default=True) + use_anim_optimize = BoolProperty(name="Optimize Keyframes",description="Remove double keyframes",default=True) + + anim_optimize_precision = FloatProperty(name="Precision",description=("Tolerence for comparing double keyframes (higher for greater accuracy)"),min=1, max=16,soft_min=1, soft_max=16,default=6.0) + + use_metadata = BoolProperty(name="Use Metadata",default=True,options={'HIDDEN'}) + use_include_particle_duplicates = BoolProperty(name="Include Particle Duplicates",default=True) + +def register(): + bpy.utils.register_class(godot_export_manager) + bpy.utils.register_class(godot_node_list) + bpy.utils.register_class(godot_export_groups) + bpy.utils.register_class(add_export_group) + bpy.utils.register_class(del_export_group) + bpy.utils.register_class(export_all_groups) + bpy.utils.register_class(export_groups_autosave) + bpy.utils.register_class(export_group) + bpy.utils.register_class(add_objects_to_group) + bpy.utils.register_class(del_objects_from_group) + bpy.utils.register_class(select_group_objects) + bpy.utils.register_class(UI_List_Godot) + + bpy.types.Scene.godot_export_groups = CollectionProperty(type=godot_export_groups) + bpy.types.Scene.godot_export_groups_index = IntProperty(default=0,min=0) + +def unregister(): + bpy.utils.unregister_class(godot_export_manager) + bpy.utils.unregister_class(godot_node_list) + bpy.utils.unregister_class(godot_export_groups) + bpy.utils.unregister_class(export_groups_autosave) + bpy.utils.unregister_class(add_export_group) + bpy.utils.unregister_class(del_export_group) + bpy.utils.unregister_class(export_all_groups) + bpy.utils.unregister_class(export_group) + bpy.utils.unregister_class(add_objects_to_group) + bpy.utils.unregister_class(del_objects_from_group) + bpy.utils.unregister_class(select_group_objects) + bpy.utils.unregister_class(UI_List_Godot) + +@persistent +def auto_export(dummy): + bpy.ops.scene.godot_export_groups_autosave() + +bpy.app.handlers.save_post.append(auto_export) + +if __name__ == "__main__": + register() |