/*************************************************************************/ /* spatial_editor_gizmos.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 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 EditorSpatialGizmo::clear() { for(int i=0;ifree(instances[i].instance); } billboard_handle=false; collision_segments.clear(); collision_mesh=Ref(); instances.clear(); handles.clear(); secondary_handles.clear(); } void EditorSpatialGizmo::redraw() { if (get_script_instance() && get_script_instance()->has_method("redraw")) get_script_instance()->call("redraw"); } void EditorSpatialGizmo::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_cast_shadows_setting(instance,VS::SHADOW_CASTING_SETTING_OFF); VS::get_singleton()->instance_set_layer_mask(instance,1<& 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 EditorSpatialGizmo::add_lines(const Vector &p_lines, const Ref &p_material,bool p_billboard){ ERR_FAIL_COND(!spatial_node); Instance ins; Ref mesh = memnew( Mesh ); Array a; a.resize(Mesh::ARRAY_MAX); a[Mesh::ARRAY_VERTEX]=p_lines; DVector color; color.resize(p_lines.size()); { DVector::Write w = color.write(); for(int i=0;iadd_surface_from_arrays(Mesh::PRIMITIVE_LINES,a); mesh->surface_set_material(0,p_material); if (p_billboard) { float md=0; for(int i=0;iset_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 EditorSpatialGizmo::add_unscaled_billboard(const Ref& p_material,float p_scale) { ERR_FAIL_COND(!spatial_node); Instance ins; Vector vs; Vector 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 = memnew( Mesh ); Array a; a.resize(Mesh::ARRAY_MAX); a[Mesh::ARRAY_VERTEX]=vs; a[Mesh::ARRAY_TEX_UV]=uv; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLE_FAN,a); mesh->surface_set_material(0,p_material); if (true) { float md=0; for(int i=0;iset_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 EditorSpatialGizmo::add_collision_triangles(const Ref& p_tmesh) { collision_mesh=p_tmesh; } void EditorSpatialGizmo::add_collision_segments(const Vector &p_lines) { int from=collision_segments.size(); collision_segments.resize(from+p_lines.size()); for(int i=0;i &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 = memnew( Mesh ); #if 1 Array a; a.resize(VS::ARRAY_MAX); a[VS::ARRAY_VERTEX]=p_handles; print_line("handles?: "+itos(p_handles.size())); DVector colors; { colors.resize(p_handles.size()); DVector::Write w=colors.write(); for(int i=0;iget_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_from_arrays(Mesh::PRIMITIVE_POINTS,a); mesh->surface_set_material(0,SpatialEditorGizmos::singleton->handle2_material); if (p_billboard) { float md=0; for(int i=0;iset_custom_aabb(AABB(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0)); } } #else for(int ih=0;ih vertices; Vector 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_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 0 && p[j].distance_to(b) >0) { any_out=true; break; } } if (!any_out) return true; } return false; } return false; } bool EditorSpatialGizmo::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)); } float min_d=1e20; int idx=-1; for(int i=0;iunproject_position(hpos); if (p.distance_to(p_point)handle_t->get_width()*0.6) { real_t dp = p_camera->get_transform().origin.distance_to(hpos); if (dpget_transform().basis.get_axis(2); min_d=dp; idx=i+handles.size(); } } } if (p_sec_first && idx!=-1) { *r_gizmo_handle=idx; return true; } min_d=1e20; for(int i=0;iunproject_position(hpos); if (p.distance_to(p_point)handle_t->get_width()*0.6) { real_t dp = p_camera->get_transform().origin.distance_to(hpos); if (dpget_transform().basis.get_axis(2); min_d=dp; idx=i; } } } 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;iunproject_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 (pd0) { float d2=s[0].distance_to(p)/d; tcp = a+(b-a)*d2; } else { tcp=a; } if (camp.distance_to(tcp)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 (collision_mesh->intersect_ray(ray_from,ray_dir,rpos,rnorm)) { r_pos=gt.xform(rpos); r_normal=gt.basis.xform(rnorm).normalized(); return true; } } return false; } void EditorSpatialGizmo::create() { ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND(valid); valid=true; for(int i=0;iinstance_set_transform(instances[i].instance,spatial_node->get_global_transform()); } } void EditorSpatialGizmo::free(){ ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND(!valid); for(int i=0;ifree(instances[i].instance); instances[i].instance=RID(); } valid=false; } void EditorSpatialGizmo::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_lines","lines","material:Material","billboard"),&EditorSpatialGizmo::add_lines,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("add_mesh","mesh:Mesh","billboard","skeleton"),&EditorSpatialGizmo::add_mesh,DEFVAL(false),DEFVAL(RID())); ObjectTypeDB::bind_method(_MD("add_collision_segments","segments"),&EditorSpatialGizmo::add_collision_segments); ObjectTypeDB::bind_method(_MD("add_collision_triangles","triangles:TriangleMesh"),&EditorSpatialGizmo::add_collision_triangles); ObjectTypeDB::bind_method(_MD("add_unscaled_billboard","material:Material","default_scale"),&EditorSpatialGizmo::add_unscaled_billboard,DEFVAL(1)); ObjectTypeDB::bind_method(_MD("add_handles","handles","billboard","secondary"),&EditorSpatialGizmo::add_handles,DEFVAL(false),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("set_spatial_node","node:Spatial"),&EditorSpatialGizmo::_set_spatial_node); ObjectTypeDB::bind_method(_MD("clear"),&EditorSpatialGizmo::clear); BIND_VMETHOD( MethodInfo("redraw")); BIND_VMETHOD( MethodInfo(Variant::STRING,"get_handle_name",PropertyInfo(Variant::INT,"index"))); BIND_VMETHOD( MethodInfo("get_handle_value:Variant",PropertyInfo(Variant::INT,"index"))); BIND_VMETHOD( MethodInfo("set_handle",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::OBJECT,"camera:Camera"),PropertyInfo(Variant::VECTOR2,"point"))); MethodInfo cm = MethodInfo("commit_handle",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::NIL,"restore:Variant"),PropertyInfo(Variant::BOOL,"cancel")); cm.default_arguments.push_back(false); BIND_VMETHOD( cm ); } EditorSpatialGizmo::EditorSpatialGizmo() { valid=false; billboard_handle=false; base=NULL; spatial_node=NULL; } EditorSpatialGizmo::~EditorSpatialGizmo(){ clear(); } Vector3 EditorSpatialGizmo::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_param(Light::PARAM_RANGE); if (p_idx==1) return light->get_param(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;iget_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()) { 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_param(Light::PARAM_RANGE,d); } else if (light->cast_to()) { 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_param(Light::PARAM_RANGE,r); } } } else if (p_idx==1) { float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],light->get_param(Light::PARAM_RANGE),gt); light->set_param(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_param(p_idx==0?Light::PARAM_RANGE:Light::PARAM_SPOT_ANGLE,p_restore); } else if (p_idx==0) { UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Light Radius")); ur->add_do_method(light,"set_param",Light::PARAM_RANGE,light->get_param(Light::PARAM_RANGE)); ur->add_undo_method(light,"set_param",Light::PARAM_RANGE,p_restore); ur->commit_action(); } else if (p_idx==1) { UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Light Radius")); ur->add_do_method(light,"set_param",Light::PARAM_SPOT_ANGLE,light->get_param(Light::PARAM_SPOT_ANGLE)); ur->add_undo_method(light,"set_param",Light::PARAM_SPOT_ANGLE,p_restore); ur->commit_action(); } } void LightSpatialGizmo::redraw() { if (light->cast_to()) { 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 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;jlight_material); add_collision_segments(lines); add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_directional_icon,0.05); } if (light->cast_to()) { clear(); OmniLight *on = light->cast_to(); float r = on->get_param(Light::PARAM_RANGE); Vector 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 handles; handles.push_back(Vector3(r,0,0)); add_handles(handles,true); } if (light->cast_to()) { clear(); Vector points; SpotLight *on = light->cast_to(); float r = on->get_param(Light::PARAM_RANGE); float w = r*Math::sin(Math::deg2rad(on->get_param(Light::PARAM_SPOT_ANGLE))); float d = r*Math::cos(Math::deg2rad(on->get_param(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 handles; handles.push_back(Vector3(0,0,-r)); Vector 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); } ////// void ListenerSpatialGizmo::redraw() { clear(); add_unscaled_billboard(SpatialEditorGizmos::singleton->listener_icon, 0.05); add_mesh(SpatialEditorGizmos::singleton->listener_line_mesh); Vector cursor_points; cursor_points.push_back(Vector3(0, 0, 0)); cursor_points.push_back(Vector3(0, 0, -1.0)); add_collision_segments(cursor_points); } ListenerSpatialGizmo::ListenerSpatialGizmo(Listener* p_listener){ set_spatial_node(p_listener); listener = p_listener; } ////// 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(TTR("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(TTR("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 lines; Vector 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 m = mesh->get_mesh(); if (!m.is_valid()) return; //none Ref 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 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 surface_tool( memnew( SurfaceTool )); surface_tool->begin(Mesh::PRIMITIVE_LINES); surface_tool->set_material(SpatialEditorGizmos::singleton->skeleton_material); Vector grests; grests.resize(skel->get_bone_count()); Vector bones; Vector 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;iget_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 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()) { add_unscaled_billboard(SpatialEditorGizmos::singleton->stream_player_icon,0.05); } else if (splayer->cast_to()) { 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 roomie = room->get_room(); if (roomie.is_null()) return; DVector faces = roomie->get_geometry_hint(); Vector lines; int fc=faces.size(); DVector::Read r =faces.read(); Map<_EdgeKey,Vector3> edge_map; for(int i=0;i::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 points = portal->get_shape(); if (points.size()==0) { return; } Vector lines; Vector3 center; for(int i=0;iportal_material); add_collision_segments(lines); } PortalSpatialGizmo::PortalSpatialGizmo(Portal* p_portal){ set_spatial_node(p_portal); portal=p_portal; } ///// void RayCastSpatialGizmo::redraw() { clear(); Vector 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 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;jget_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 s = cs->get_shape(); if (s.is_null()) return ""; if (s->cast_to()) { return "Radius"; } if (s->cast_to()) { return "Extents"; } if (s->cast_to()) { return p_idx==0?"Radius":"Height"; } if (s->cast_to()) { return "Length"; } return ""; } Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const{ Ref s = cs->get_shape(); if (s.is_null()) return Variant(); if (s->cast_to()) { Ref ss = s; return ss->get_radius(); } if (s->cast_to()) { Ref bs = s; return bs->get_extents(); } if (s->cast_to()) { Ref cs = s; return p_idx==0?cs->get_radius():cs->get_height(); } if (s->cast_to()) { Ref cs = s; return cs->get_length(); } return Variant(); } void CollisionShapeSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){ Ref 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()) { Ref 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()) { Ref 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()) { Vector3 axis; axis[p_idx]=1.0; Ref 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()) { Vector3 axis; axis[p_idx==0?0:2]=1.0; Ref 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 s = cs->get_shape(); if (s.is_null()) return; if (s->cast_to()) { Ref ss=s; if (p_cancel) { ss->set_radius(p_restore); return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("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()) { Ref ss=s; if (p_cancel) { ss->set_extents(p_restore); return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("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()) { Ref 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(TTR("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(TTR("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()) { Ref ss=s; if (p_cancel) { ss->set_length(p_restore); return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("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 s = cs->get_shape(); if (s.is_null()) return; if (s->cast_to()) { Ref sp= s; float r=sp->get_radius(); Vector 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 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 handles; handles.push_back(Vector3(r,0,0)); add_handles(handles); } if (s->cast_to()) { Ref bs=s; Vector 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 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()) { Ref cs=s; float radius = cs->get_radius(); float height = cs->get_height(); Vector 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 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 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()) { Ref ps=s; Plane p = ps->get_plane(); Vector 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()) { DVector points = s->cast_to()->get_points(); if (points.size()>3) { QuickHull qh; Vector varr = Variant(points); Geometry::MeshData md; Error err = qh.build(varr,md); if (err==OK) { Vector points; points.resize(md.edges.size()*2); for(int i=0;ishape_material); add_collision_segments(points); } } } if (s->cast_to()) { Ref rs=s; Vector 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 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 points = polygon->get_polygon(); float depth = polygon->get_depth()*0.5; Vector lines; for(int i=0;ishape_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; 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(TTR("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 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 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); } //////// /// String ReflectionProbeGizmo::get_handle_name(int p_idx) const { switch(p_idx) { case 0: return "Extents X"; case 1: return "Extents Y"; case 2: return "Extents Z"; case 3: return "Origin X"; case 4: return "Origin Y"; case 5: return "Origin Z"; } return ""; } Variant ReflectionProbeGizmo::get_handle_value(int p_idx) const{ return AABB(probe->get_extents(),probe->get_origin_offset()); } void ReflectionProbeGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){ Transform gt = probe->get_global_transform(); //gt.orthonormalize(); Transform gi = gt.affine_inverse(); if (p_idx<3) { Vector3 extents = probe->get_extents(); 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*16384)}; Vector3 axis; axis[p_idx]=1.0; Vector3 ra,rb; Geometry::get_closest_points_between_segments(Vector3(),axis*16384,sg[0],sg[1],ra,rb); float d = ra[p_idx]; if (d<0.001) d=0.001; extents[p_idx]=d; probe->set_extents(extents); } else { p_idx-=3; Vector3 origin = probe->get_origin_offset(); origin[p_idx]=0; 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*16384)}; Vector3 axis; axis[p_idx]=1.0; Vector3 ra,rb; Geometry::get_closest_points_between_segments(origin-axis*16384,origin+axis*16384,sg[0],sg[1],ra,rb); float d = ra[p_idx]; d+=0.25; origin[p_idx]=d; probe->set_origin_offset(origin); } } void ReflectionProbeGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){ AABB restore = p_restore; if (p_cancel) { probe->set_extents(restore.pos); probe->set_origin_offset(restore.size); return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Probe Extents")); ur->add_do_method(probe,"set_extents",probe->get_extents()); ur->add_do_method(probe,"set_origin_offset",probe->get_origin_offset()); ur->add_undo_method(probe,"set_extents",restore.pos); ur->add_undo_method(probe,"set_origin_offset",restore.size); ur->commit_action(); } void ReflectionProbeGizmo::redraw(){ clear(); Vector lines; Vector internal_lines; Vector3 extents = probe->get_extents(); AABB aabb; aabb.pos=-extents; aabb.size=extents*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); } for(int i=0;i<8;i++) { Vector3 ep = aabb.get_endpoint(i); internal_lines.push_back(probe->get_origin_offset()); internal_lines.push_back(ep); } Vector handles; for(int i=0;i<3;i++) { Vector3 ax; ax[i]=aabb.pos[i]+aabb.size[i]; handles.push_back(ax); } for(int i=0;i<3;i++) { Vector3 orig_handle=probe->get_origin_offset(); orig_handle[i]-=0.25; lines.push_back(orig_handle); handles.push_back(orig_handle); orig_handle[i]+=0.5; lines.push_back(orig_handle); } add_lines(lines,SpatialEditorGizmos::singleton->reflection_probe_material); add_lines(internal_lines,SpatialEditorGizmos::singleton->reflection_probe_material_internal); //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05); add_collision_segments(lines); add_handles(handles); } ReflectionProbeGizmo::ReflectionProbeGizmo(ReflectionProbe* p_probe){ probe=p_probe; set_spatial_node(p_probe); } //////// /// String GIProbeGizmo::get_handle_name(int p_idx) const { switch(p_idx) { case 0: return "Extents X"; case 1: return "Extents Y"; case 2: return "Extents Z"; } return ""; } Variant GIProbeGizmo::get_handle_value(int p_idx) const{ return probe->get_extents(); } void GIProbeGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){ Transform gt = probe->get_global_transform(); //gt.orthonormalize(); Transform gi = gt.affine_inverse(); Vector3 extents = probe->get_extents(); 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*16384)}; Vector3 axis; axis[p_idx]=1.0; Vector3 ra,rb; Geometry::get_closest_points_between_segments(Vector3(),axis*16384,sg[0],sg[1],ra,rb); float d = ra[p_idx]; if (d<0.001) d=0.001; extents[p_idx]=d; probe->set_extents(extents); } void GIProbeGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){ Vector3 restore = p_restore; if (p_cancel) { probe->set_extents(restore); return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Probe Extents")); ur->add_do_method(probe,"set_extents",probe->get_extents()); ur->add_undo_method(probe,"set_extents",restore); ur->commit_action(); } void GIProbeGizmo::redraw(){ clear(); Vector lines; Vector3 extents = probe->get_extents(); static const int subdivs[GIProbe::SUBDIV_MAX]={64,128,256,512}; AABB aabb = AABB(-extents,extents*2); int subdiv = subdivs[probe->get_subdiv()]; float cell_size = aabb.get_longest_axis_size()/subdiv; for(int i=0;i<12;i++) { Vector3 a,b; aabb.get_edge(i,a,b); lines.push_back(a); lines.push_back(b); } add_lines(lines,SpatialEditorGizmos::singleton->gi_probe_material); add_collision_segments(lines); lines.clear(); for(int i=1;iaabb.size[j]) { continue; } Vector2 dir; dir[j]=1.0; Vector2 ta,tb; int j_n1=(j+1)%3; int j_n2=(j+2)%3; ta[j_n1]=1.0; tb[j_n2]=1.0; for(int k=0;k<4;k++) { Vector3 from=aabb.pos,to=aabb.pos; from[j]+= cell_size*i; to[j]+=cell_size*i; if (k&1) { to[j_n1]+=aabb.size[j_n1]; } else { to[j_n2]+=aabb.size[j_n2]; } if (k&2) { from[j_n1]+=aabb.size[j_n1]; from[j_n2]+=aabb.size[j_n2]; } lines.push_back(from); lines.push_back(to); } } } add_lines(lines,SpatialEditorGizmos::singleton->reflection_probe_material_internal); Vector handles; for(int i=0;i<3;i++) { Vector3 ax; ax[i]=aabb.pos[i]+aabb.size[i]; handles.push_back(ax); } add_handles(handles); } GIProbeGizmo::GIProbeGizmo(GIProbe* p_probe){ probe=p_probe; set_spatial_node(p_probe); } //////// void NavigationMeshSpatialGizmo::redraw() { clear(); Ref navmeshie = navmesh->get_navigation_mesh(); if (navmeshie.is_null()) return; DVector vertices = navmeshie->get_vertices(); DVector::Read vr=vertices.read(); List faces; for(int i=0;iget_polygon_count();i++) { Vector p = navmeshie->get_polygon(i); for(int j=2;j edge_map; DVector tmeshfaces; tmeshfaces.resize(faces.size()*3); { DVector::Write tw=tmeshfaces.write(); int tidx=0; for(List::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::Element *E=edge_map.find(ek); if (E) { E->get()=false; } else { edge_map[ek]=true; } } } } Vector 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 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 m = memnew( Mesh ); Array a; a.resize(Mesh::ARRAY_MAX); a[0]=tmeshfaces; m->add_surface_from_arrays(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 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 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) && lljoint_material); } HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint* p_p3d) { p3d=p_p3d; set_spatial_node(p3d); } /////// /// //// void SliderJointSpatialGizmo::redraw() { clear(); Vector 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 (lljoint_material); } SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint* p_p3d) { p3d=p_p3d; set_spatial_node(p3d); } /////// /// //// void ConeTwistJointSpatialGizmo::redraw() { clear(); Vector 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;ijoint_material); } ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d) { p3d=p_p3d; set_spatial_node(p3d); } //////// /// \brief SpatialEditorGizmos::singleton /// /////// /// //// void Generic6DOFJointSpatialGizmo::redraw() { clear(); Vector 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; for(int i=0;ijoint_material); } Generic6DOFJointSpatialGizmo::Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d) { p3d=p_p3d; set_spatial_node(p3d); } /////// /// //// SpatialEditorGizmos *SpatialEditorGizmos::singleton=NULL; Ref SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) { if (p_spatial->cast_to()) { Ref lsg = memnew( LightSpatialGizmo(p_spatial->cast_to()) ); return lsg; } if (p_spatial->cast_to()) { Ref misg = memnew(ListenerSpatialGizmo(p_spatial->cast_to())); return misg; } if (p_spatial->cast_to()) { Ref lsg = memnew( CameraSpatialGizmo(p_spatial->cast_to()) ); return lsg; } if (p_spatial->cast_to()) { Ref lsg = memnew( SkeletonSpatialGizmo(p_spatial->cast_to()) ); return lsg; } if (p_spatial->cast_to()) { Ref lsg = memnew( Position3DSpatialGizmo(p_spatial->cast_to()) ); return lsg; } if (p_spatial->cast_to()) { Ref misg = memnew( MeshInstanceSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( RoomSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( NavigationMeshSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( RayCastSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( PortalSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( TestCubeSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( SpatialPlayerSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( CollisionShapeSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( VisibilityNotifierGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( ReflectionProbeGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( GIProbeGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( VehicleWheelSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( PinJointSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( HingeJointSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( SliderJointSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( ConeTwistJointSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( Generic6DOFJointSpatialGizmo(p_spatial->cast_to()) ); return misg; } if (p_spatial->cast_to()) { Ref misg = memnew( CollisionPolygonSpatialGizmo(p_spatial->cast_to()) ); return misg; } return Ref(); } Ref SpatialEditorGizmos::create_line_material(const Color& p_base_color) { Ref line_material = Ref( memnew( FixedSpatialMaterial )); line_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); line_material->set_line_width(3.0); line_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); //line_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); //->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); line_material->set_albedo(p_base_color); return line_material; } Ref SpatialEditorGizmos::create_solid_material(const Color& p_base_color) { Ref line_material = Ref( memnew( FixedSpatialMaterial )); line_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); line_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); line_material->set_albedo(p_base_color); return line_material; } SpatialEditorGizmos::SpatialEditorGizmos() { singleton=this; handle_material = Ref( memnew( FixedSpatialMaterial )); handle_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); handle_material->set_albedo(Color(0.8,0.8,0.8)); handle2_material = Ref( memnew( FixedSpatialMaterial )); handle2_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); handle2_material->set_flag(FixedSpatialMaterial::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(FixedSpatialMaterial::TEXTURE_ALBEDO,handle_t); handle2_material->set_albedo(Color(1,1,1)); handle2_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); handle2_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); handle2_material->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); light_material = create_line_material(Color(1,1,0.2)); light_material_omni_icon = Ref( memnew( FixedSpatialMaterial )); light_material_omni_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); light_material_omni_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); light_material_omni_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); light_material_omni_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); light_material_omni_icon->set_albedo(Color(1,1,1,0.9)); light_material_omni_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoLight","EditorIcons")); light_material_directional_icon = Ref( memnew( FixedSpatialMaterial )); light_material_directional_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); light_material_directional_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); light_material_directional_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); light_material_directional_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); light_material_directional_icon->set_albedo(Color(1,1,1,0.9)); light_material_directional_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,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_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false); navmesh_edge_material->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false); navmesh_solid_material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); 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_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false); navmesh_edge_material_disabled->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false); navmesh_solid_material_disabled->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); skeleton_material = create_line_material(Color(0.6,1.0,0.3)); skeleton_material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); skeleton_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true); skeleton_material->set_flag(FixedSpatialMaterial::FLAG_ONTOP,true); skeleton_material->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); //position 3D Shared mesh pos3d_mesh = Ref( memnew( Mesh ) ); { DVector cursor_points; DVector 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 mat = memnew( FixedSpatialMaterial ); mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true); mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true); mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true); mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,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_from_arrays(Mesh::PRIMITIVE_LINES,d); pos3d_mesh->surface_set_material(0,mat); } listener_line_mesh = Ref(memnew(Mesh)); { DVector cursor_points; DVector cursor_colors; cursor_points.push_back(Vector3(0, 0, 0)); cursor_points.push_back(Vector3(0, 0, -1.0)); cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7)); cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7)); Ref mat = memnew(FixedSpatialMaterial); mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, 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; listener_line_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d); listener_line_mesh->surface_set_material(0, mat); } sample_player_icon = Ref( memnew( FixedSpatialMaterial )); sample_player_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); sample_player_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); sample_player_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); sample_player_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); sample_player_icon->set_albedo(Color(1,1,1,0.9)); sample_player_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,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)); reflection_probe_material = create_line_material(Color(0.5,1.0,0.7)); reflection_probe_material_internal = create_line_material(Color(0.3,0.8,0.5,0.15)); gi_probe_material = create_line_material(Color(0.7,1.0,0.5)); gi_probe_material_internal = create_line_material(Color(0.5,0.8,0.3,0.4)); joint_material = create_line_material(Color(0.6,0.8,1.0)); stream_player_icon = Ref( memnew( FixedSpatialMaterial )); stream_player_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); stream_player_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); stream_player_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); stream_player_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); stream_player_icon->set_albedo(Color(1,1,1,0.9)); stream_player_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer","EditorIcons")); visibility_notifier_icon = Ref( memnew( FixedSpatialMaterial )); visibility_notifier_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); visibility_notifier_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); visibility_notifier_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); visibility_notifier_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); visibility_notifier_icon->set_albedo(Color(1,1,1,0.9)); visibility_notifier_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("Visible","EditorIcons")); listener_icon = Ref(memnew(FixedSpatialMaterial)); listener_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); listener_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); listener_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); listener_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); listener_icon->set_albedo( Color(1, 1, 1, 0.9)); listener_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoListener", "EditorIcons")); { DVector 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( memnew( TriangleMesh ) ); test_cube_tm->create(vertices); } shape_material = create_line_material(Color(0.2,1,1.0)); }