1 /*************************************************************************/
2 /* spatial_editor_gizmos.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30 #include "spatial_editor_gizmos.h"
31 #include "geometry.h"
32 #include "quick_hull.h"
33 #include "scene/3d/camera.h"
34 #include "scene/resources/box_shape.h"
35 #include "scene/resources/capsule_shape.h"
36 #include "scene/resources/convex_polygon_shape.h"
37 #include "scene/resources/plane_shape.h"
38 #include "scene/resources/ray_shape.h"
39 #include "scene/resources/sphere_shape.h"
40 #include "scene/resources/surface_tool.h"
41
42 // Keep small children away from this file.
43 // It's so ugly it will eat them alive
44
45 #define HANDLE_HALF_SIZE 0.05
46
clear()47 void EditorSpatialGizmo::clear() {
48
49 for (int i = 0; i < instances.size(); i++) {
50
51 if (instances[i].instance.is_valid())
52 VS::get_singleton()->free(instances[i].instance);
53 }
54
55 billboard_handle = false;
56 collision_segments.clear();
57 collision_mesh = Ref<TriangleMesh>();
58 instances.clear();
59 handles.clear();
60 secondary_handles.clear();
61 }
62
redraw()63 void EditorSpatialGizmo::redraw() {
64
65 if (get_script_instance() && get_script_instance()->has_method("redraw"))
66 get_script_instance()->call("redraw");
67 }
68
create_instance(Spatial * p_base)69 void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base) {
70
71 instance = VS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario());
72 VS::get_singleton()->instance_attach_object_instance_ID(instance, p_base->get_instance_ID());
73 if (billboard)
74 VS::get_singleton()->instance_geometry_set_flag(instance, VS::INSTANCE_FLAG_BILLBOARD, true);
75 if (unscaled)
76 VS::get_singleton()->instance_geometry_set_flag(instance, VS::INSTANCE_FLAG_DEPH_SCALE, true);
77 if (skeleton.is_valid())
78 VS::get_singleton()->instance_attach_skeleton(instance, skeleton);
79 if (extra_margin)
80 VS::get_singleton()->instance_set_extra_visibility_margin(instance, 1);
81 VS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance, VS::SHADOW_CASTING_SETTING_OFF);
82 VS::get_singleton()->instance_geometry_set_flag(instance, VS::INSTANCE_FLAG_RECEIVE_SHADOWS, false);
83 VS::get_singleton()->instance_set_layer_mask(instance, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26
84 }
85
add_mesh(const Ref<Mesh> & p_mesh,bool p_billboard,const RID & p_skeleton)86 void EditorSpatialGizmo::add_mesh(const Ref<Mesh> &p_mesh, bool p_billboard, const RID &p_skeleton) {
87
88 ERR_FAIL_COND(!spatial_node);
89 Instance ins;
90
91 ins.billboard = p_billboard;
92 ins.mesh = p_mesh;
93 ins.skeleton = p_skeleton;
94 if (valid) {
95 ins.create_instance(spatial_node);
96 VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
97 }
98
99 instances.push_back(ins);
100 }
101
add_lines(const Vector<Vector3> & p_lines,const Ref<Material> & p_material,bool p_billboard)102 void EditorSpatialGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard) {
103
104 ERR_FAIL_COND(!spatial_node);
105 Instance ins;
106
107 Ref<Mesh> mesh = memnew(Mesh);
108 Array a;
109 a.resize(Mesh::ARRAY_MAX);
110
111 a[Mesh::ARRAY_VERTEX] = p_lines;
112
113 DVector<Color> color;
114 color.resize(p_lines.size());
115 {
116 DVector<Color>::Write w = color.write();
117 for (int i = 0; i < p_lines.size(); i++) {
118 if (is_selected())
119 w[i] = Color(1, 1, 1, 0.6);
120 else
121 w[i] = Color(1, 1, 1, 0.25);
122 }
123 }
124
125 a[Mesh::ARRAY_COLOR] = color;
126
127 mesh->add_surface(Mesh::PRIMITIVE_LINES, a);
128 mesh->surface_set_material(0, p_material);
129
130 if (p_billboard) {
131 float md = 0;
132 for (int i = 0; i < p_lines.size(); i++) {
133
134 md = MAX(0, p_lines[i].length());
135 }
136 if (md) {
137 mesh->set_custom_aabb(AABB(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
138 }
139 }
140
141 ins.billboard = p_billboard;
142 ins.mesh = mesh;
143 if (valid) {
144 ins.create_instance(spatial_node);
145 VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
146 }
147
148 instances.push_back(ins);
149 }
150
add_unscaled_billboard(const Ref<Material> & p_material,float p_scale)151 void EditorSpatialGizmo::add_unscaled_billboard(const Ref<Material> &p_material, float p_scale) {
152
153 ERR_FAIL_COND(!spatial_node);
154 Instance ins;
155
156 Vector<Vector3> vs;
157 Vector<Vector2> uv;
158
159 vs.push_back(Vector3(-p_scale, p_scale, 0));
160 vs.push_back(Vector3(p_scale, p_scale, 0));
161 vs.push_back(Vector3(p_scale, -p_scale, 0));
162 vs.push_back(Vector3(-p_scale, -p_scale, 0));
163
164 uv.push_back(Vector2(1, 0));
165 uv.push_back(Vector2(0, 0));
166 uv.push_back(Vector2(0, 1));
167 uv.push_back(Vector2(1, 1));
168
169 Ref<Mesh> mesh = memnew(Mesh);
170 Array a;
171 a.resize(Mesh::ARRAY_MAX);
172 a[Mesh::ARRAY_VERTEX] = vs;
173 a[Mesh::ARRAY_TEX_UV] = uv;
174 mesh->add_surface(Mesh::PRIMITIVE_TRIANGLE_FAN, a);
175 mesh->surface_set_material(0, p_material);
176
177 if (true) {
178 float md = 0;
179 for (int i = 0; i < vs.size(); i++) {
180
181 md = MAX(0, vs[i].length());
182 }
183 if (md) {
184 mesh->set_custom_aabb(AABB(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
185 }
186 }
187
188 ins.mesh = mesh;
189 ins.unscaled = true;
190 ins.billboard = true;
191 if (valid) {
192 ins.create_instance(spatial_node);
193 VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
194 }
195
196 instances.push_back(ins);
197 }
198
add_collision_triangles(const Ref<TriangleMesh> & p_tmesh)199 void EditorSpatialGizmo::add_collision_triangles(const Ref<TriangleMesh> &p_tmesh) {
200
201 collision_mesh = p_tmesh;
202 }
203
add_collision_segments(const Vector<Vector3> & p_lines)204 void EditorSpatialGizmo::add_collision_segments(const Vector<Vector3> &p_lines) {
205
206 int from = collision_segments.size();
207 collision_segments.resize(from + p_lines.size());
208 for (int i = 0; i < p_lines.size(); i++) {
209
210 collision_segments[from + i] = p_lines[i];
211 }
212 }
213
add_handles(const Vector<Vector3> & p_handles,bool p_billboard,bool p_secondary)214 void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_billboard, bool p_secondary) {
215
216 billboard_handle = p_billboard;
217
218 if (!is_selected())
219 return;
220
221 ERR_FAIL_COND(!spatial_node);
222
223 ERR_FAIL_COND(!spatial_node);
224 Instance ins;
225
226 Ref<Mesh> mesh = memnew(Mesh);
227 #if 1
228
229 Array a;
230 a.resize(VS::ARRAY_MAX);
231 a[VS::ARRAY_VERTEX] = p_handles;
232 DVector<Color> colors;
233 {
234 colors.resize(p_handles.size());
235 DVector<Color>::Write w = colors.write();
236 for (int i = 0; i < p_handles.size(); i++) {
237
238 Color col(1, 1, 1, 1);
239 if (SpatialEditor::get_singleton()->get_over_gizmo_handle() != i)
240 col = Color(0.9, 0.9, 0.9, 0.9);
241 w[i] = col;
242 }
243 }
244 a[VS::ARRAY_COLOR] = colors;
245 mesh->add_surface(Mesh::PRIMITIVE_POINTS, a);
246 mesh->surface_set_material(0, SpatialEditorGizmos::singleton->handle2_material);
247
248 if (p_billboard) {
249 float md = 0;
250 for (int i = 0; i < p_handles.size(); i++) {
251
252 md = MAX(0, p_handles[i].length());
253 }
254 if (md) {
255 mesh->set_custom_aabb(AABB(Vector3(-md, -md, -md), Vector3(md, md, md) * 2.0));
256 }
257 }
258
259 #else
260 for (int ih = 0; ih < p_handles.size(); ih++) {
261
262 Vector<Vector3> vertices;
263 Vector<Vector3> normals;
264
265 int vtx_idx = 0;
266
267 #define ADD_VTX(m_idx) \
268 vertices.push_back((face_points[m_idx] * HANDLE_HALF_SIZE + p_handles[ih])); \
269 normals.push_back(normal_points[m_idx]); \
270 vtx_idx++;
271
272 for (int i = 0; i < 6; i++) {
273
274 Vector3 face_points[4];
275 Vector3 normal_points[4];
276 float uv_points[8] = { 0, 0, 0, 1, 1, 1, 1, 0 };
277
278 for (int j = 0; j < 4; j++) {
279
280 float v[3];
281 v[0] = 1.0;
282 v[1] = 1 - 2 * ((j >> 1) & 1);
283 v[2] = v[1] * (1 - 2 * (j & 1));
284
285 for (int k = 0; k < 3; k++) {
286
287 if (i < 3)
288 face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
289 else
290 face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
291 }
292 normal_points[j] = Vector3();
293 normal_points[j][i % 3] = (i >= 3 ? -1 : 1);
294 }
295 //tri 1
296 ADD_VTX(0);
297 ADD_VTX(1);
298 ADD_VTX(2);
299 //tri 2
300 ADD_VTX(2);
301 ADD_VTX(3);
302 ADD_VTX(0);
303 }
304
305 Array d;
306 d.resize(VS::ARRAY_MAX);
307 d[VisualServer::ARRAY_NORMAL] = normals;
308 d[VisualServer::ARRAY_VERTEX] = vertices;
309
310 mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, d);
311 mesh->surface_set_material(ih, SpatialEditorGizmos::singleton->handle_material);
312 }
313 #endif
314 ins.mesh = mesh;
315 ins.billboard = p_billboard;
316 ins.extra_margin = true;
317 if (valid) {
318 ins.create_instance(spatial_node);
319 VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
320 }
321 instances.push_back(ins);
322 if (!p_secondary) {
323 int chs = handles.size();
324 handles.resize(chs + p_handles.size());
325 for (int i = 0; i < p_handles.size(); i++) {
326 handles[i + chs] = p_handles[i];
327 }
328 } else {
329
330 int chs = secondary_handles.size();
331 secondary_handles.resize(chs + p_handles.size());
332 for (int i = 0; i < p_handles.size(); i++) {
333 secondary_handles[i + chs] = p_handles[i];
334 }
335 }
336 }
337
set_spatial_node(Spatial * p_node)338 void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) {
339
340 ERR_FAIL_NULL(p_node);
341 spatial_node = p_node;
342 }
343
intersect_frustum(const Camera * p_camera,const Vector<Plane> & p_frustum)344 bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera, const Vector<Plane> &p_frustum) {
345
346 ERR_FAIL_COND_V(!spatial_node, false);
347 ERR_FAIL_COND_V(!valid, false);
348
349 if (collision_segments.size()) {
350
351 const Plane *p = p_frustum.ptr();
352 int fc = p_frustum.size();
353
354 int vc = collision_segments.size();
355 const Vector3 *vptr = collision_segments.ptr();
356 Transform t = spatial_node->get_global_transform();
357
358 for (int i = 0; i < vc / 2; i++) {
359
360 Vector3 a = t.xform(vptr[i * 2 + 0]);
361 Vector3 b = t.xform(vptr[i * 2 + 1]);
362
363 bool any_out = false;
364 for (int j = 0; j < fc; j++) {
365
366 if (p[j].distance_to(a) > 0 && p[j].distance_to(b) > 0) {
367
368 any_out = true;
369 break;
370 }
371 }
372
373 if (!any_out)
374 return true;
375 }
376
377 return false;
378 }
379
380 return false;
381 }
382
intersect_ray(const Camera * p_camera,const Point2 & p_point,Vector3 & r_pos,Vector3 & r_normal,int * r_gizmo_handle,bool p_sec_first)383 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) {
384
385 ERR_FAIL_COND_V(!spatial_node, false);
386 ERR_FAIL_COND_V(!valid, false);
387
388 if (r_gizmo_handle) {
389
390 Transform t = spatial_node->get_global_transform();
391 t.orthonormalize();
392 if (billboard_handle) {
393 t.set_look_at(t.origin, t.origin + p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1));
394 }
395 Transform ti = t.affine_inverse();
396
397 float min_d = 1e20;
398 int idx = -1;
399
400 for (int i = 0; i < secondary_handles.size(); i++) {
401
402 Vector3 hpos = t.xform(secondary_handles[i]);
403 Vector2 p = p_camera->unproject_position(hpos);
404 if (p.distance_to(p_point) < SpatialEditorGizmos::singleton->handle_t->get_width() * 0.6) {
405
406 real_t dp = p_camera->get_transform().origin.distance_to(hpos);
407 if (dp < min_d) {
408
409 r_pos = t.xform(hpos);
410 r_normal = p_camera->get_transform().basis.get_axis(2);
411 min_d = dp;
412 idx = i + handles.size();
413 }
414 }
415 }
416
417 if (p_sec_first && idx != -1) {
418
419 *r_gizmo_handle = idx;
420 return true;
421 }
422
423 min_d = 1e20;
424
425 for (int i = 0; i < handles.size(); i++) {
426
427 Vector3 hpos = t.xform(handles[i]);
428 Vector2 p = p_camera->unproject_position(hpos);
429 if (p.distance_to(p_point) < SpatialEditorGizmos::singleton->handle_t->get_width() * 0.6) {
430
431 real_t dp = p_camera->get_transform().origin.distance_to(hpos);
432 if (dp < min_d) {
433
434 r_pos = t.xform(hpos);
435 r_normal = p_camera->get_transform().basis.get_axis(2);
436 min_d = dp;
437 idx = i;
438 }
439 }
440 }
441
442 if (idx >= 0) {
443 *r_gizmo_handle = idx;
444 return true;
445 }
446 }
447
448 if (collision_segments.size()) {
449
450 Plane camp(p_camera->get_transform().origin, (-p_camera->get_transform().basis.get_axis(2)).normalized());
451
452 int vc = collision_segments.size();
453 const Vector3 *vptr = collision_segments.ptr();
454 Transform t = spatial_node->get_global_transform();
455 if (billboard_handle) {
456 t.set_look_at(t.origin, t.origin + p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1));
457 }
458
459 Vector3 cp;
460 float cpd = 1e20;
461
462 for (int i = 0; i < vc / 2; i++) {
463
464 Vector3 a = t.xform(vptr[i * 2 + 0]);
465 Vector3 b = t.xform(vptr[i * 2 + 1]);
466 Vector2 s[2];
467 s[0] = p_camera->unproject_position(a);
468 s[1] = p_camera->unproject_position(b);
469
470 Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, s);
471
472 float pd = p.distance_to(p_point);
473
474 if (pd < cpd) {
475
476 float d = s[0].distance_to(s[1]);
477 Vector3 tcp;
478 if (d > 0) {
479
480 float d2 = s[0].distance_to(p) / d;
481 tcp = a + (b - a) * d2;
482
483 } else {
484 tcp = a;
485 }
486
487 if (camp.distance_to(tcp) < p_camera->get_znear())
488 continue;
489 cp = tcp;
490 cpd = pd;
491 }
492 }
493
494 if (cpd < 8) {
495
496 r_pos = cp;
497 r_normal = -p_camera->project_ray_normal(p_point);
498 return true;
499 }
500
501 return false;
502 }
503
504 if (collision_mesh.is_valid()) {
505 Transform gt = spatial_node->get_global_transform();
506
507 if (billboard_handle) {
508 gt.set_look_at(gt.origin, gt.origin + p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1));
509 }
510
511 Transform ai = gt.affine_inverse();
512 Vector3 ray_from = ai.xform(p_camera->project_ray_origin(p_point));
513 Vector3 ray_dir = ai.basis.xform(p_camera->project_ray_normal(p_point)).normalized();
514 Vector3 rpos, rnorm;
515
516 if (collision_mesh->intersect_ray(ray_from, ray_dir, rpos, rnorm)) {
517
518 r_pos = gt.xform(rpos);
519 r_normal = gt.basis.xform(rnorm).normalized();
520 return true;
521 }
522 }
523
524 return false;
525 }
526
create()527 void EditorSpatialGizmo::create() {
528
529 ERR_FAIL_COND(!spatial_node);
530 ERR_FAIL_COND(valid);
531 valid = true;
532
533 for (int i = 0; i < instances.size(); i++) {
534
535 instances[i].create_instance(spatial_node);
536 }
537
538 transform();
539 }
540
transform()541 void EditorSpatialGizmo::transform() {
542
543 ERR_FAIL_COND(!spatial_node);
544 ERR_FAIL_COND(!valid);
545 for (int i = 0; i < instances.size(); i++) {
546 VS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform());
547 }
548 }
549
free()550 void EditorSpatialGizmo::free() {
551
552 ERR_FAIL_COND(!spatial_node);
553 ERR_FAIL_COND(!valid);
554
555 for (int i = 0; i < instances.size(); i++) {
556
557 if (instances[i].instance.is_valid())
558 VS::get_singleton()->free(instances[i].instance);
559 instances[i].instance = RID();
560 }
561
562 valid = false;
563 }
564
_bind_methods()565 void EditorSpatialGizmo::_bind_methods() {
566
567 ObjectTypeDB::bind_method(_MD("add_lines", "lines", "material:Material", "billboard"), &EditorSpatialGizmo::add_lines, DEFVAL(false));
568 ObjectTypeDB::bind_method(_MD("add_mesh", "mesh:Mesh", "billboard", "skeleton"), &EditorSpatialGizmo::add_mesh, DEFVAL(false), DEFVAL(RID()));
569 ObjectTypeDB::bind_method(_MD("add_collision_segments", "segments"), &EditorSpatialGizmo::add_collision_segments);
570 ObjectTypeDB::bind_method(_MD("add_collision_triangles", "triangles:TriangleMesh"), &EditorSpatialGizmo::add_collision_triangles);
571 ObjectTypeDB::bind_method(_MD("add_unscaled_billboard", "material:Material", "default_scale"), &EditorSpatialGizmo::add_unscaled_billboard, DEFVAL(1));
572 ObjectTypeDB::bind_method(_MD("add_handles", "handles", "billboard", "secondary"), &EditorSpatialGizmo::add_handles, DEFVAL(false), DEFVAL(false));
573 ObjectTypeDB::bind_method(_MD("set_spatial_node", "node:Spatial"), &EditorSpatialGizmo::_set_spatial_node);
574 ObjectTypeDB::bind_method(_MD("clear"), &EditorSpatialGizmo::clear);
575
576 BIND_VMETHOD(MethodInfo("redraw"));
577 BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", PropertyInfo(Variant::INT, "index")));
578 BIND_VMETHOD(MethodInfo("get_handle_value:Variant", PropertyInfo(Variant::INT, "index")));
579 BIND_VMETHOD(MethodInfo("set_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera:Camera"), PropertyInfo(Variant::VECTOR2, "point")));
580 MethodInfo cm = MethodInfo("commit_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore:Variant"), PropertyInfo(Variant::BOOL, "cancel"));
581 cm.default_arguments.push_back(false);
582 BIND_VMETHOD(cm);
583 }
584
EditorSpatialGizmo()585 EditorSpatialGizmo::EditorSpatialGizmo() {
586 valid = false;
587 billboard_handle = false;
588 base = NULL;
589 spatial_node = NULL;
590 }
591
~EditorSpatialGizmo()592 EditorSpatialGizmo::~EditorSpatialGizmo() {
593
594 clear();
595 }
596
get_handle_pos(int p_idx) const597 Vector3 EditorSpatialGizmo::get_handle_pos(int p_idx) const {
598
599 ERR_FAIL_INDEX_V(p_idx, handles.size(), Vector3());
600
601 return handles[p_idx];
602 }
603
604 //// light gizmo
605
get_handle_name(int p_idx) const606 String LightSpatialGizmo::get_handle_name(int p_idx) const {
607
608 if (p_idx == 0)
609 return "Radius";
610 else
611 return "Aperture";
612 }
613
get_handle_value(int p_idx) const614 Variant LightSpatialGizmo::get_handle_value(int p_idx) const {
615
616 if (p_idx == 0)
617 return light->get_parameter(Light::PARAM_RADIUS);
618 if (p_idx == 1)
619 return light->get_parameter(Light::PARAM_SPOT_ANGLE);
620
621 return Variant();
622 }
623
_find_closest_angle_to_half_pi_arc(const Vector3 & p_from,const Vector3 & p_to,float p_arc_radius,const Transform & p_arc_xform)624 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) {
625
626 //bleh, discrete is simpler
627 static const int arc_test_points = 64;
628 float min_d = 1e20;
629 Vector3 min_p;
630
631 for (int i = 0; i < arc_test_points; i++) {
632
633 float a = i * Math_PI * 0.5 / arc_test_points;
634 float an = (i + 1) * Math_PI * 0.5 / arc_test_points;
635 Vector3 p = Vector3(Math::cos(a), 0, -Math::sin(a)) * p_arc_radius;
636 Vector3 n = Vector3(Math::cos(an), 0, -Math::sin(an)) * p_arc_radius;
637
638 Vector3 ra, rb;
639 Geometry::get_closest_points_between_segments(p, n, p_from, p_to, ra, rb);
640
641 float d = ra.distance_to(rb);
642 if (d < min_d) {
643 min_d = d;
644 min_p = ra;
645 }
646 }
647
648 //min_p = p_arc_xform.affine_inverse().xform(min_p);
649 float a = Vector2(min_p.x, -min_p.z).angle();
650 return a * 180.0 / Math_PI;
651 }
652
set_handle(int p_idx,Camera * p_camera,const Point2 & p_point)653 void LightSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) {
654
655 Transform gt = light->get_global_transform();
656 gt.orthonormalize();
657 Transform gi = gt.affine_inverse();
658
659 Vector3 ray_from = p_camera->project_ray_origin(p_point);
660 Vector3 ray_dir = p_camera->project_ray_normal(p_point);
661
662 Vector3 s[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
663 if (p_idx == 0) {
664
665 if (light->cast_to<SpotLight>()) {
666 Vector3 ra, rb;
667 Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, -4096), s[0], s[1], ra, rb);
668
669 float d = -ra.z;
670 if (d < 0)
671 d = 0;
672
673 light->set_parameter(Light::PARAM_RADIUS, d);
674 } else if (light->cast_to<OmniLight>()) {
675
676 Plane cp = Plane(gt.origin, p_camera->get_transform().basis.get_axis(2));
677
678 Vector3 inters;
679 if (cp.intersects_ray(ray_from, ray_dir, &inters)) {
680
681 float r = inters.distance_to(gt.origin);
682 light->set_parameter(Light::PARAM_RADIUS, r);
683 }
684 }
685
686 } else if (p_idx == 1) {
687
688 float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], light->get_parameter(Light::PARAM_RADIUS), gt);
689 light->set_parameter(Light::PARAM_SPOT_ANGLE, CLAMP(a, 0.01, 89.99));
690 }
691 }
692
commit_handle(int p_idx,const Variant & p_restore,bool p_cancel)693 void LightSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
694
695 if (p_cancel) {
696
697 light->set_parameter(p_idx == 0 ? Light::PARAM_RADIUS : Light::PARAM_SPOT_ANGLE, p_restore);
698
699 } else if (p_idx == 0) {
700
701 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
702 ur->create_action(TTR("Change Light Radius"));
703 ur->add_do_method(light, "set_parameter", Light::PARAM_RADIUS, light->get_parameter(Light::PARAM_RADIUS));
704 ur->add_undo_method(light, "set_parameter", Light::PARAM_RADIUS, p_restore);
705 ur->commit_action();
706 } else if (p_idx == 1) {
707
708 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
709 ur->create_action(TTR("Change Light Radius"));
710 ur->add_do_method(light, "set_parameter", Light::PARAM_SPOT_ANGLE, light->get_parameter(Light::PARAM_SPOT_ANGLE));
711 ur->add_undo_method(light, "set_parameter", Light::PARAM_SPOT_ANGLE, p_restore);
712 ur->commit_action();
713 }
714 }
715
redraw()716 void LightSpatialGizmo::redraw() {
717
718 if (light->cast_to<DirectionalLight>()) {
719
720 const int arrow_points = 5;
721 Vector3 arrow[arrow_points] = {
722 Vector3(0, 0, 2),
723 Vector3(1, 1, 2),
724 Vector3(1, 1, -1),
725 Vector3(2, 2, -1),
726 Vector3(0, 0, -3)
727 };
728
729 int arrow_sides = 4;
730
731 Vector<Vector3> lines;
732
733 for (int i = 0; i < arrow_sides; i++) {
734
735 Matrix3 ma(Vector3(0, 0, 1), Math_PI * 2 * float(i) / arrow_sides);
736 Matrix3 mb(Vector3(0, 0, 1), Math_PI * 2 * float(i + 1) / arrow_sides);
737
738 for (int j = 1; j < arrow_points - 1; j++) {
739
740 if (j != 2) {
741 lines.push_back(ma.xform(arrow[j]));
742 lines.push_back(ma.xform(arrow[j + 1]));
743 }
744 if (j < arrow_points - 1) {
745 lines.push_back(ma.xform(arrow[j]));
746 lines.push_back(mb.xform(arrow[j]));
747 }
748 }
749 }
750
751 add_lines(lines, SpatialEditorGizmos::singleton->light_material);
752 add_collision_segments(lines);
753 add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_directional_icon, 0.05);
754 }
755
756 if (light->cast_to<OmniLight>()) {
757
758 clear();
759
760 OmniLight *on = light->cast_to<OmniLight>();
761
762 float r = on->get_parameter(Light::PARAM_RADIUS);
763
764 Vector<Vector3> points;
765
766 for (int i = 0; i <= 360; i++) {
767
768 float ra = Math::deg2rad(i);
769 float rb = Math::deg2rad(i + 1);
770 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
771 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
772
773 /*points.push_back(Vector3(a.x,0,a.y));
774 points.push_back(Vector3(b.x,0,b.y));
775 points.push_back(Vector3(0,a.x,a.y));
776 points.push_back(Vector3(0,b.x,b.y));*/
777 points.push_back(Vector3(a.x, a.y, 0));
778 points.push_back(Vector3(b.x, b.y, 0));
779 }
780
781 add_lines(points, SpatialEditorGizmos::singleton->light_material, true);
782 add_collision_segments(points);
783
784 add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon, 0.05);
785
786 Vector<Vector3> handles;
787 handles.push_back(Vector3(r, 0, 0));
788 add_handles(handles, true);
789 }
790
791 if (light->cast_to<SpotLight>()) {
792
793 clear();
794
795 Vector<Vector3> points;
796 SpotLight *on = light->cast_to<SpotLight>();
797
798 float r = on->get_parameter(Light::PARAM_RADIUS);
799 float w = r * Math::sin(Math::deg2rad(on->get_parameter(Light::PARAM_SPOT_ANGLE)));
800 float d = r * Math::cos(Math::deg2rad(on->get_parameter(Light::PARAM_SPOT_ANGLE)));
801
802 for (int i = 0; i < 360; i++) {
803
804 float ra = Math::deg2rad(i);
805 float rb = Math::deg2rad(i + 1);
806 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
807 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
808
809 /*points.push_back(Vector3(a.x,0,a.y));
810 points.push_back(Vector3(b.x,0,b.y));
811 points.push_back(Vector3(0,a.x,a.y));
812 points.push_back(Vector3(0,b.x,b.y));*/
813 points.push_back(Vector3(a.x, a.y, -d));
814 points.push_back(Vector3(b.x, b.y, -d));
815
816 if (i % 90 == 0) {
817
818 points.push_back(Vector3(a.x, a.y, -d));
819 points.push_back(Vector3());
820 }
821 }
822
823 points.push_back(Vector3(0, 0, -r));
824 points.push_back(Vector3());
825
826 add_lines(points, SpatialEditorGizmos::singleton->light_material);
827
828 Vector<Vector3> handles;
829 handles.push_back(Vector3(0, 0, -r));
830
831 Vector<Vector3> collision_segments;
832
833 for (int i = 0; i < 64; i++) {
834
835 float ra = i * Math_PI * 2.0 / 64.0;
836 float rb = (i + 1) * Math_PI * 2.0 / 64.0;
837 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
838 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
839
840 collision_segments.push_back(Vector3(a.x, a.y, -d));
841 collision_segments.push_back(Vector3(b.x, b.y, -d));
842
843 if (i % 16 == 0) {
844
845 collision_segments.push_back(Vector3(a.x, a.y, -d));
846 collision_segments.push_back(Vector3());
847 }
848
849 if (i == 16) {
850
851 handles.push_back(Vector3(a.x, a.y, -d));
852 }
853 }
854
855 collision_segments.push_back(Vector3(0, 0, -r));
856 collision_segments.push_back(Vector3());
857
858 add_handles(handles);
859 add_collision_segments(collision_segments);
860 add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon, 0.05);
861 }
862 }
863
LightSpatialGizmo(Light * p_light)864 LightSpatialGizmo::LightSpatialGizmo(Light *p_light) {
865
866 light = p_light;
867 set_spatial_node(p_light);
868 }
869 //////
870
redraw()871 void ListenerSpatialGizmo::redraw() {
872
873 clear();
874
875 add_unscaled_billboard(SpatialEditorGizmos::singleton->listener_icon, 0.05);
876
877 add_mesh(SpatialEditorGizmos::singleton->listener_line_mesh);
878 Vector<Vector3> cursor_points;
879 cursor_points.push_back(Vector3(0, 0, 0));
880 cursor_points.push_back(Vector3(0, 0, -1.0));
881 add_collision_segments(cursor_points);
882 }
883
ListenerSpatialGizmo(Listener * p_listener)884 ListenerSpatialGizmo::ListenerSpatialGizmo(Listener *p_listener) {
885
886 set_spatial_node(p_listener);
887 listener = p_listener;
888 }
889
890 //////
891
get_handle_name(int p_idx) const892 String CameraSpatialGizmo::get_handle_name(int p_idx) const {
893
894 if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) {
895 return "FOV";
896 } else {
897 return "Size";
898 }
899 }
get_handle_value(int p_idx) const900 Variant CameraSpatialGizmo::get_handle_value(int p_idx) const {
901
902 if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) {
903 return camera->get_fov();
904 } else {
905
906 return camera->get_size();
907 }
908 }
set_handle(int p_idx,Camera * p_camera,const Point2 & p_point)909 void CameraSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) {
910
911 Transform gt = camera->get_global_transform();
912 gt.orthonormalize();
913 Transform gi = gt.affine_inverse();
914
915 Vector3 ray_from = p_camera->project_ray_origin(p_point);
916 Vector3 ray_dir = p_camera->project_ray_normal(p_point);
917
918 Vector3 s[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
919
920 if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) {
921 Transform gt = camera->get_global_transform();
922 float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], 1.0, gt);
923 camera->set("fov", a);
924 } else {
925
926 Vector3 ra, rb;
927 Geometry::get_closest_points_between_segments(Vector3(0, 0, -1), Vector3(4096, 0, -1), s[0], s[1], ra, rb);
928 float d = ra.x * 2.0;
929 if (d < 0)
930 d = 0;
931
932 camera->set("size", d);
933 }
934 }
commit_handle(int p_idx,const Variant & p_restore,bool p_cancel)935 void CameraSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
936
937 if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) {
938
939 if (p_cancel) {
940
941 camera->set("fov", p_restore);
942 } else {
943 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
944 ur->create_action(TTR("Change Camera FOV"));
945 ur->add_do_property(camera, "fov", camera->get_fov());
946 ur->add_undo_property(camera, "fov", p_restore);
947 ur->commit_action();
948 }
949
950 } else {
951
952 if (p_cancel) {
953
954 camera->set("size", p_restore);
955 } else {
956 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
957 ur->create_action(TTR("Change Camera Size"));
958 ur->add_do_property(camera, "size", camera->get_size());
959 ur->add_undo_property(camera, "size", p_restore);
960 ur->commit_action();
961 }
962 }
963 }
964
redraw()965 void CameraSpatialGizmo::redraw() {
966
967 clear();
968
969 Vector<Vector3> lines;
970 Vector<Vector3> handles;
971
972 switch (camera->get_projection()) {
973
974 case Camera::PROJECTION_PERSPECTIVE: {
975
976 float fov = camera->get_fov();
977
978 Vector3 side = Vector3(Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov)));
979 Vector3 nside = side;
980 nside.x = -nside.x;
981 Vector3 up = Vector3(0, side.x, 0);
982
983 #define ADD_TRIANGLE(m_a, m_b, m_c) \
984 { \
985 lines.push_back(m_a); \
986 lines.push_back(m_b); \
987 lines.push_back(m_b); \
988 lines.push_back(m_c); \
989 lines.push_back(m_c); \
990 lines.push_back(m_a); \
991 }
992
993 ADD_TRIANGLE(Vector3(), side + up, side - up);
994 ADD_TRIANGLE(Vector3(), nside + up, nside - up);
995 ADD_TRIANGLE(Vector3(), side + up, nside + up);
996 ADD_TRIANGLE(Vector3(), side - up, nside - up);
997
998 handles.push_back(side);
999 side.x *= 0.25;
1000 nside.x *= 0.25;
1001 Vector3 tup(0, up.y * 3 / 2, side.z);
1002 ADD_TRIANGLE(tup, side + up, nside + up);
1003
1004 } break;
1005 case Camera::PROJECTION_ORTHOGONAL: {
1006
1007 #define ADD_QUAD(m_a, m_b, m_c, m_d) \
1008 { \
1009 lines.push_back(m_a); \
1010 lines.push_back(m_b); \
1011 lines.push_back(m_b); \
1012 lines.push_back(m_c); \
1013 lines.push_back(m_c); \
1014 lines.push_back(m_d); \
1015 lines.push_back(m_d); \
1016 lines.push_back(m_a); \
1017 }
1018 float size = camera->get_size();
1019
1020 float hsize = size * 0.5;
1021 Vector3 right(hsize, 0, 0);
1022 Vector3 up(0, hsize, 0);
1023 Vector3 back(0, 0, -1.0);
1024 Vector3 front(0, 0, 0);
1025
1026 ADD_QUAD(-up - right, -up + right, up + right, up - right);
1027 ADD_QUAD(-up - right + back, -up + right + back, up + right + back, up - right + back);
1028 ADD_QUAD(up + right, up + right + back, up - right + back, up - right);
1029 ADD_QUAD(-up + right, -up + right + back, -up - right + back, -up - right);
1030 handles.push_back(right + back);
1031
1032 right.x *= 0.25;
1033 Vector3 tup(0, up.y * 3 / 2, back.z);
1034 ADD_TRIANGLE(tup, right + up + back, -right + up + back);
1035
1036 } break;
1037 }
1038
1039 add_lines(lines, SpatialEditorGizmos::singleton->camera_material);
1040 add_collision_segments(lines);
1041 add_handles(handles);
1042 }
1043
CameraSpatialGizmo(Camera * p_camera)1044 CameraSpatialGizmo::CameraSpatialGizmo(Camera *p_camera) {
1045
1046 camera = p_camera;
1047 set_spatial_node(camera);
1048 }
1049
1050 //////
1051
redraw()1052 void MeshInstanceSpatialGizmo::redraw() {
1053
1054 Ref<Mesh> m = mesh->get_mesh();
1055 if (!m.is_valid())
1056 return; //none
1057
1058 Ref<TriangleMesh> tm = m->generate_triangle_mesh();
1059 if (tm.is_valid())
1060 add_collision_triangles(tm);
1061 }
1062
MeshInstanceSpatialGizmo(MeshInstance * p_mesh)1063 MeshInstanceSpatialGizmo::MeshInstanceSpatialGizmo(MeshInstance *p_mesh) {
1064
1065 mesh = p_mesh;
1066 set_spatial_node(p_mesh);
1067 }
1068
1069 /////
1070
redraw()1071 void Position3DSpatialGizmo::redraw() {
1072
1073 clear();
1074 add_mesh(SpatialEditorGizmos::singleton->pos3d_mesh);
1075 Vector<Vector3> cursor_points;
1076 float cs = 0.25;
1077 cursor_points.push_back(Vector3(+cs, 0, 0));
1078 cursor_points.push_back(Vector3(-cs, 0, 0));
1079 cursor_points.push_back(Vector3(0, +cs, 0));
1080 cursor_points.push_back(Vector3(0, -cs, 0));
1081 cursor_points.push_back(Vector3(0, 0, +cs));
1082 cursor_points.push_back(Vector3(0, 0, -cs));
1083 add_collision_segments(cursor_points);
1084 }
1085
Position3DSpatialGizmo(Position3D * p_p3d)1086 Position3DSpatialGizmo::Position3DSpatialGizmo(Position3D *p_p3d) {
1087
1088 p3d = p_p3d;
1089 set_spatial_node(p3d);
1090 }
1091
1092 /////
1093
redraw()1094 void SkeletonSpatialGizmo::redraw() {
1095
1096 clear();
1097
1098 Ref<SurfaceTool> surface_tool(memnew(SurfaceTool));
1099
1100 surface_tool->begin(Mesh::PRIMITIVE_LINES);
1101 surface_tool->set_material(SpatialEditorGizmos::singleton->skeleton_material);
1102 Vector<Transform> grests;
1103 grests.resize(skel->get_bone_count());
1104
1105 Vector<int> bones;
1106 Vector<float> weights;
1107 bones.resize(4);
1108 weights.resize(4);
1109
1110 for (int i = 0; i < 4; i++) {
1111 bones[i] = 0;
1112 weights[i] = 0;
1113 }
1114
1115 weights[0] = 1;
1116
1117 AABB aabb;
1118
1119 Color bonecolor = Color(1.0, 0.4, 0.4, 0.3);
1120 Color rootcolor = Color(0.4, 1.0, 0.4, 0.1);
1121
1122 for (int i = 0; i < skel->get_bone_count(); i++) {
1123
1124 int parent = skel->get_bone_parent(i);
1125
1126 if (parent >= 0) {
1127 grests[i] = grests[parent] * skel->get_bone_rest(i);
1128
1129 Vector3 v0 = grests[parent].origin;
1130 Vector3 v1 = grests[i].origin;
1131 Vector3 d = (v1 - v0).normalized();
1132 float dist = v0.distance_to(v1);
1133
1134 //find closest axis
1135 int closest = -1;
1136 float closest_d = 0.0;
1137
1138 for (int j = 0; j < 3; j++) {
1139 float dp = Math::abs(grests[parent].basis[j].normalized().dot(d));
1140 if (j == 0 || dp > closest_d)
1141 closest = j;
1142 }
1143
1144 //find closest other
1145 Vector3 first;
1146 Vector3 points[4];
1147 int pointidx = 0;
1148 for (int j = 0; j < 3; j++) {
1149
1150 bones[0] = parent;
1151 surface_tool->add_bones(bones);
1152 surface_tool->add_weights(weights);
1153 surface_tool->add_color(rootcolor);
1154 surface_tool->add_vertex(v0 - grests[parent].basis[j].normalized() * dist * 0.05);
1155 surface_tool->add_bones(bones);
1156 surface_tool->add_weights(weights);
1157 surface_tool->add_color(rootcolor);
1158 surface_tool->add_vertex(v0 + grests[parent].basis[j].normalized() * dist * 0.05);
1159
1160 if (j == closest)
1161 continue;
1162
1163 Vector3 axis;
1164 if (first == Vector3()) {
1165 axis = d.cross(d.cross(grests[parent].basis[j])).normalized();
1166 first = axis;
1167 } else {
1168 axis = d.cross(first).normalized();
1169 }
1170
1171 for (int k = 0; k < 2; k++) {
1172
1173 if (k == 1)
1174 axis = -axis;
1175 Vector3 point = v0 + d * dist * 0.2;
1176 point += axis * dist * 0.1;
1177
1178 bones[0] = parent;
1179 surface_tool->add_bones(bones);
1180 surface_tool->add_weights(weights);
1181 surface_tool->add_color(bonecolor);
1182 surface_tool->add_vertex(v0);
1183 surface_tool->add_bones(bones);
1184 surface_tool->add_weights(weights);
1185 surface_tool->add_color(bonecolor);
1186 surface_tool->add_vertex(point);
1187
1188 bones[0] = parent;
1189 surface_tool->add_bones(bones);
1190 surface_tool->add_weights(weights);
1191 surface_tool->add_color(bonecolor);
1192 surface_tool->add_vertex(point);
1193 bones[0] = i;
1194 surface_tool->add_bones(bones);
1195 surface_tool->add_weights(weights);
1196 surface_tool->add_color(bonecolor);
1197 surface_tool->add_vertex(v1);
1198 points[pointidx++] = point;
1199 }
1200 }
1201
1202 SWAP(points[1], points[2]);
1203 for (int j = 0; j < 4; j++) {
1204
1205 bones[0] = parent;
1206 surface_tool->add_bones(bones);
1207 surface_tool->add_weights(weights);
1208 surface_tool->add_color(bonecolor);
1209 surface_tool->add_vertex(points[j]);
1210 surface_tool->add_bones(bones);
1211 surface_tool->add_weights(weights);
1212 surface_tool->add_color(bonecolor);
1213 surface_tool->add_vertex(points[(j + 1) % 4]);
1214 }
1215
1216 /*
1217 bones[0]=parent;
1218 surface_tool->add_bones(bones);
1219 surface_tool->add_weights(weights);
1220 surface_tool->add_color(Color(0.4,1,0.4,0.4));
1221 surface_tool->add_vertex(v0);
1222 bones[0]=i;
1223 surface_tool->add_bones(bones);
1224 surface_tool->add_weights(weights);
1225 surface_tool->add_color(Color(0.4,1,0.4,0.4));
1226 surface_tool->add_vertex(v1);
1227 */
1228 } else {
1229
1230 grests[i] = skel->get_bone_rest(i);
1231 bones[0] = i;
1232 }
1233 /*
1234 Transform t = grests[i];
1235 t.orthonormalize();
1236
1237 for (int i=0;i<6;i++) {
1238
1239
1240 Vector3 face_points[4];
1241
1242 for (int j=0;j<4;j++) {
1243
1244 float v[3];
1245 v[0]=1.0;
1246 v[1]=1-2*((j>>1)&1);
1247 v[2]=v[1]*(1-2*(j&1));
1248
1249 for (int k=0;k<3;k++) {
1250
1251 if (i<3)
1252 face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
1253 else
1254 face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
1255 }
1256 }
1257
1258 for(int j=0;j<4;j++) {
1259 surface_tool->add_bones(bones);
1260 surface_tool->add_weights(weights);
1261 surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
1262 surface_tool->add_vertex(t.xform(face_points[j]*0.04));
1263 surface_tool->add_bones(bones);
1264 surface_tool->add_weights(weights);
1265 surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
1266 surface_tool->add_vertex(t.xform(face_points[(j+1)%4]*0.04));
1267 }
1268
1269 }
1270 */
1271 }
1272
1273 Ref<Mesh> m = surface_tool->commit();
1274 add_mesh(m, false, skel->get_skeleton());
1275 }
1276
SkeletonSpatialGizmo(Skeleton * p_skel)1277 SkeletonSpatialGizmo::SkeletonSpatialGizmo(Skeleton *p_skel) {
1278
1279 skel = p_skel;
1280 set_spatial_node(p_skel);
1281 }
1282
1283 /////
1284
redraw()1285 void SpatialPlayerSpatialGizmo::redraw() {
1286
1287 clear();
1288 if (splayer->cast_to<SpatialStreamPlayer>()) {
1289
1290 add_unscaled_billboard(SpatialEditorGizmos::singleton->stream_player_icon, 0.05);
1291
1292 } else if (splayer->cast_to<SpatialSamplePlayer>()) {
1293
1294 add_unscaled_billboard(SpatialEditorGizmos::singleton->sample_player_icon, 0.05);
1295 }
1296 }
1297
SpatialPlayerSpatialGizmo(SpatialPlayer * p_splayer)1298 SpatialPlayerSpatialGizmo::SpatialPlayerSpatialGizmo(SpatialPlayer *p_splayer) {
1299
1300 set_spatial_node(p_splayer);
1301 splayer = p_splayer;
1302 }
1303
1304 /////
1305
redraw()1306 void RoomSpatialGizmo::redraw() {
1307
1308 clear();
1309 Ref<RoomBounds> roomie = room->get_room();
1310 if (roomie.is_null())
1311 return;
1312 DVector<Face3> faces = roomie->get_geometry_hint();
1313
1314 Vector<Vector3> lines;
1315 int fc = faces.size();
1316 DVector<Face3>::Read r = faces.read();
1317
1318 Map<_EdgeKey, Vector3> edge_map;
1319
1320 for (int i = 0; i < fc; i++) {
1321
1322 Vector3 fn = r[i].get_plane().normal;
1323
1324 for (int j = 0; j < 3; j++) {
1325
1326 _EdgeKey ek;
1327 ek.from = r[i].vertex[j].snapped(CMP_EPSILON);
1328 ek.to = r[i].vertex[(j + 1) % 3].snapped(CMP_EPSILON);
1329 if (ek.from < ek.to)
1330 SWAP(ek.from, ek.to);
1331
1332 Map<_EdgeKey, Vector3>::Element *E = edge_map.find(ek);
1333
1334 if (E) {
1335
1336 if (E->get().dot(fn) > 0.9) {
1337
1338 E->get() = Vector3();
1339 }
1340
1341 } else {
1342
1343 edge_map[ek] = fn;
1344 }
1345 }
1346 }
1347
1348 for (Map<_EdgeKey, Vector3>::Element *E = edge_map.front(); E; E = E->next()) {
1349
1350 if (E->get() != Vector3()) {
1351 lines.push_back(E->key().from);
1352 lines.push_back(E->key().to);
1353 }
1354 }
1355
1356 add_lines(lines, SpatialEditorGizmos::singleton->room_material);
1357 add_collision_segments(lines);
1358 }
1359
RoomSpatialGizmo(Room * p_room)1360 RoomSpatialGizmo::RoomSpatialGizmo(Room *p_room) {
1361
1362 set_spatial_node(p_room);
1363 room = p_room;
1364 }
1365
1366 /////
1367
redraw()1368 void PortalSpatialGizmo::redraw() {
1369
1370 clear();
1371
1372 Vector<Point2> points = portal->get_shape();
1373 if (points.size() == 0) {
1374 return;
1375 }
1376
1377 Vector<Vector3> lines;
1378
1379 Vector3 center;
1380 for (int i = 0; i < points.size(); i++) {
1381
1382 Vector3 f;
1383 f.x = points[i].x;
1384 f.y = points[i].y;
1385 Vector3 fn;
1386 fn.x = points[(i + 1) % points.size()].x;
1387 fn.y = points[(i + 1) % points.size()].y;
1388 center += f;
1389
1390 lines.push_back(f);
1391 lines.push_back(fn);
1392 }
1393
1394 center /= points.size();
1395 lines.push_back(center);
1396 lines.push_back(center + Vector3(0, 0, 1));
1397
1398 add_lines(lines, SpatialEditorGizmos::singleton->portal_material);
1399 add_collision_segments(lines);
1400 }
1401
PortalSpatialGizmo(Portal * p_portal)1402 PortalSpatialGizmo::PortalSpatialGizmo(Portal *p_portal) {
1403
1404 set_spatial_node(p_portal);
1405 portal = p_portal;
1406 }
1407
1408 /////
1409
redraw()1410 void RayCastSpatialGizmo::redraw() {
1411
1412 clear();
1413
1414 Vector<Vector3> lines;
1415
1416 lines.push_back(Vector3());
1417 lines.push_back(raycast->get_cast_to());
1418
1419 add_lines(lines, SpatialEditorGizmos::singleton->raycast_material);
1420 add_collision_segments(lines);
1421 }
1422
RayCastSpatialGizmo(RayCast * p_raycast)1423 RayCastSpatialGizmo::RayCastSpatialGizmo(RayCast *p_raycast) {
1424
1425 set_spatial_node(p_raycast);
1426 raycast = p_raycast;
1427 }
1428
1429 /////
1430
redraw()1431 void VehicleWheelSpatialGizmo::redraw() {
1432
1433 clear();
1434
1435 Vector<Vector3> points;
1436
1437 float r = car_wheel->get_radius();
1438 const int skip = 10;
1439 for (int i = 0; i <= 360; i += skip) {
1440
1441 float ra = Math::deg2rad(i);
1442 float rb = Math::deg2rad(i + skip);
1443 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
1444 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
1445
1446 points.push_back(Vector3(0, a.x, a.y));
1447 points.push_back(Vector3(0, b.x, b.y));
1448
1449 const int springsec = 4;
1450
1451 for (int j = 0; j < springsec; j++) {
1452 float t = car_wheel->get_suspension_rest_length() * 5;
1453 points.push_back(Vector3(a.x, i / 360.0 * t / springsec + j * (t / springsec), a.y) * 0.2);
1454 points.push_back(Vector3(b.x, (i + skip) / 360.0 * t / springsec + j * (t / springsec), b.y) * 0.2);
1455 }
1456 }
1457
1458 //travel
1459 points.push_back(Vector3(0, 0, 0));
1460 points.push_back(Vector3(0, car_wheel->get_suspension_rest_length(), 0));
1461
1462 //axis
1463 points.push_back(Vector3(r * 0.2, car_wheel->get_suspension_rest_length(), 0));
1464 points.push_back(Vector3(-r * 0.2, car_wheel->get_suspension_rest_length(), 0));
1465 //axis
1466 points.push_back(Vector3(r * 0.2, 0, 0));
1467 points.push_back(Vector3(-r * 0.2, 0, 0));
1468
1469 //forward line
1470 points.push_back(Vector3(0, -r, 0));
1471 points.push_back(Vector3(0, -r, r * 2));
1472 points.push_back(Vector3(0, -r, r * 2));
1473 points.push_back(Vector3(r * 2 * 0.2, -r, r * 2 * 0.8));
1474 points.push_back(Vector3(0, -r, r * 2));
1475 points.push_back(Vector3(-r * 2 * 0.2, -r, r * 2 * 0.8));
1476
1477 add_lines(points, SpatialEditorGizmos::singleton->car_wheel_material);
1478 add_collision_segments(points);
1479 }
1480
VehicleWheelSpatialGizmo(VehicleWheel * p_car_wheel)1481 VehicleWheelSpatialGizmo::VehicleWheelSpatialGizmo(VehicleWheel *p_car_wheel) {
1482
1483 set_spatial_node(p_car_wheel);
1484 car_wheel = p_car_wheel;
1485 }
1486
1487 ///
1488
redraw()1489 void TestCubeSpatialGizmo::redraw() {
1490
1491 clear();
1492 add_collision_triangles(SpatialEditorGizmos::singleton->test_cube_tm);
1493 }
1494
TestCubeSpatialGizmo(TestCube * p_tc)1495 TestCubeSpatialGizmo::TestCubeSpatialGizmo(TestCube *p_tc) {
1496
1497 tc = p_tc;
1498 set_spatial_node(p_tc);
1499 }
1500
1501 ///////////
1502
get_handle_name(int p_idx) const1503 String CollisionShapeSpatialGizmo::get_handle_name(int p_idx) const {
1504
1505 Ref<Shape> s = cs->get_shape();
1506 if (s.is_null())
1507 return "";
1508
1509 if (s->cast_to<SphereShape>()) {
1510
1511 return "Radius";
1512 }
1513
1514 if (s->cast_to<BoxShape>()) {
1515
1516 return "Extents";
1517 }
1518
1519 if (s->cast_to<CapsuleShape>()) {
1520
1521 return p_idx == 0 ? "Radius" : "Height";
1522 }
1523
1524 if (s->cast_to<RayShape>()) {
1525
1526 return "Length";
1527 }
1528
1529 return "";
1530 }
get_handle_value(int p_idx) const1531 Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const {
1532
1533 Ref<Shape> s = cs->get_shape();
1534 if (s.is_null())
1535 return Variant();
1536
1537 if (s->cast_to<SphereShape>()) {
1538
1539 Ref<SphereShape> ss = s;
1540 return ss->get_radius();
1541 }
1542
1543 if (s->cast_to<BoxShape>()) {
1544
1545 Ref<BoxShape> bs = s;
1546 return bs->get_extents();
1547 }
1548
1549 if (s->cast_to<CapsuleShape>()) {
1550
1551 Ref<CapsuleShape> cs = s;
1552 return p_idx == 0 ? cs->get_radius() : cs->get_height();
1553 }
1554
1555 if (s->cast_to<RayShape>()) {
1556
1557 Ref<RayShape> cs = s;
1558 return cs->get_length();
1559 }
1560
1561 return Variant();
1562 }
set_handle(int p_idx,Camera * p_camera,const Point2 & p_point)1563 void CollisionShapeSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) {
1564 Ref<Shape> s = cs->get_shape();
1565 if (s.is_null())
1566 return;
1567
1568 Transform gt = cs->get_global_transform();
1569 gt.orthonormalize();
1570 Transform gi = gt.affine_inverse();
1571
1572 Vector3 ray_from = p_camera->project_ray_origin(p_point);
1573 Vector3 ray_dir = p_camera->project_ray_normal(p_point);
1574
1575 Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
1576
1577 if (s->cast_to<SphereShape>()) {
1578
1579 Ref<SphereShape> ss = s;
1580 Vector3 ra, rb;
1581 Geometry::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb);
1582 float d = ra.x;
1583 if (d < 0.001)
1584 d = 0.001;
1585
1586 ss->set_radius(d);
1587 }
1588
1589 if (s->cast_to<RayShape>()) {
1590
1591 Ref<RayShape> rs = s;
1592 Vector3 ra, rb;
1593 Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, 4096), sg[0], sg[1], ra, rb);
1594 float d = ra.z;
1595 if (d < 0.001)
1596 d = 0.001;
1597
1598 rs->set_length(d);
1599 }
1600
1601 if (s->cast_to<BoxShape>()) {
1602
1603 Vector3 axis;
1604 axis[p_idx] = 1.0;
1605 Ref<BoxShape> bs = s;
1606 Vector3 ra, rb;
1607 Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
1608 float d = ra[p_idx];
1609 if (d < 0.001)
1610 d = 0.001;
1611
1612 Vector3 he = bs->get_extents();
1613 he[p_idx] = d;
1614 bs->set_extents(he);
1615 }
1616
1617 if (s->cast_to<CapsuleShape>()) {
1618
1619 Vector3 axis;
1620 axis[p_idx == 0 ? 0 : 2] = 1.0;
1621 Ref<CapsuleShape> cs = s;
1622 Vector3 ra, rb;
1623 Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
1624 float d = axis.dot(ra);
1625 if (p_idx == 1)
1626 d -= cs->get_radius();
1627 if (d < 0.001)
1628 d = 0.001;
1629
1630 if (p_idx == 0)
1631 cs->set_radius(d);
1632 else if (p_idx == 1)
1633 cs->set_height(d * 2.0);
1634 }
1635 }
commit_handle(int p_idx,const Variant & p_restore,bool p_cancel)1636 void CollisionShapeSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
1637 Ref<Shape> s = cs->get_shape();
1638 if (s.is_null())
1639 return;
1640
1641 if (s->cast_to<SphereShape>()) {
1642
1643 Ref<SphereShape> ss = s;
1644 if (p_cancel) {
1645 ss->set_radius(p_restore);
1646 return;
1647 }
1648
1649 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
1650 ur->create_action(TTR("Change Sphere Shape Radius"));
1651 ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
1652 ur->add_undo_method(ss.ptr(), "set_radius", p_restore);
1653 ur->commit_action();
1654 }
1655
1656 if (s->cast_to<BoxShape>()) {
1657
1658 Ref<BoxShape> ss = s;
1659 if (p_cancel) {
1660 ss->set_extents(p_restore);
1661 return;
1662 }
1663
1664 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
1665 ur->create_action(TTR("Change Box Shape Extents"));
1666 ur->add_do_method(ss.ptr(), "set_extents", ss->get_extents());
1667 ur->add_undo_method(ss.ptr(), "set_extents", p_restore);
1668 ur->commit_action();
1669 }
1670
1671 if (s->cast_to<CapsuleShape>()) {
1672
1673 Ref<CapsuleShape> ss = s;
1674 if (p_cancel) {
1675 if (p_idx == 0)
1676 ss->set_radius(p_restore);
1677 else
1678 ss->set_height(p_restore);
1679 return;
1680 }
1681
1682 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
1683 if (p_idx == 0) {
1684 ur->create_action(TTR("Change Capsule Shape Radius"));
1685 ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
1686 ur->add_undo_method(ss.ptr(), "set_radius", p_restore);
1687 } else {
1688 ur->create_action(TTR("Change Capsule Shape Height"));
1689 ur->add_do_method(ss.ptr(), "set_height", ss->get_height());
1690 ur->add_undo_method(ss.ptr(), "set_height", p_restore);
1691 }
1692
1693 ur->commit_action();
1694 }
1695
1696 if (s->cast_to<RayShape>()) {
1697
1698 Ref<RayShape> ss = s;
1699 if (p_cancel) {
1700 ss->set_length(p_restore);
1701 return;
1702 }
1703
1704 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
1705 ur->create_action(TTR("Change Ray Shape Length"));
1706 ur->add_do_method(ss.ptr(), "set_length", ss->get_length());
1707 ur->add_undo_method(ss.ptr(), "set_length", p_restore);
1708 ur->commit_action();
1709 }
1710 }
redraw()1711 void CollisionShapeSpatialGizmo::redraw() {
1712
1713 clear();
1714
1715 Ref<Shape> s = cs->get_shape();
1716 if (s.is_null())
1717 return;
1718
1719 if (s->cast_to<SphereShape>()) {
1720
1721 Ref<SphereShape> sp = s;
1722 float r = sp->get_radius();
1723
1724 Vector<Vector3> points;
1725
1726 for (int i = 0; i <= 360; i++) {
1727
1728 float ra = Math::deg2rad(i);
1729 float rb = Math::deg2rad(i + 1);
1730 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
1731 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
1732
1733 points.push_back(Vector3(a.x, 0, a.y));
1734 points.push_back(Vector3(b.x, 0, b.y));
1735 points.push_back(Vector3(0, a.x, a.y));
1736 points.push_back(Vector3(0, b.x, b.y));
1737 points.push_back(Vector3(a.x, a.y, 0));
1738 points.push_back(Vector3(b.x, b.y, 0));
1739 }
1740
1741 Vector<Vector3> collision_segments;
1742
1743 for (int i = 0; i < 64; i++) {
1744
1745 float ra = i * Math_PI * 2.0 / 64.0;
1746 float rb = (i + 1) * Math_PI * 2.0 / 64.0;
1747 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
1748 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
1749
1750 collision_segments.push_back(Vector3(a.x, 0, a.y));
1751 collision_segments.push_back(Vector3(b.x, 0, b.y));
1752 collision_segments.push_back(Vector3(0, a.x, a.y));
1753 collision_segments.push_back(Vector3(0, b.x, b.y));
1754 collision_segments.push_back(Vector3(a.x, a.y, 0));
1755 collision_segments.push_back(Vector3(b.x, b.y, 0));
1756 }
1757
1758 add_lines(points, SpatialEditorGizmos::singleton->shape_material);
1759 add_collision_segments(collision_segments);
1760 Vector<Vector3> handles;
1761 handles.push_back(Vector3(r, 0, 0));
1762 add_handles(handles);
1763 }
1764
1765 if (s->cast_to<BoxShape>()) {
1766
1767 Ref<BoxShape> bs = s;
1768 Vector<Vector3> lines;
1769 AABB aabb;
1770 aabb.pos = -bs->get_extents();
1771 aabb.size = aabb.pos * -2;
1772
1773 for (int i = 0; i < 12; i++) {
1774 Vector3 a, b;
1775 aabb.get_edge(i, a, b);
1776 lines.push_back(a);
1777 lines.push_back(b);
1778 }
1779
1780 Vector<Vector3> handles;
1781
1782 for (int i = 0; i < 3; i++) {
1783
1784 Vector3 ax;
1785 ax[i] = bs->get_extents()[i];
1786 handles.push_back(ax);
1787 }
1788
1789 add_lines(lines, SpatialEditorGizmos::singleton->shape_material);
1790 add_collision_segments(lines);
1791 add_handles(handles);
1792 }
1793
1794 if (s->cast_to<CapsuleShape>()) {
1795
1796 Ref<CapsuleShape> cs = s;
1797 float radius = cs->get_radius();
1798 float height = cs->get_height();
1799
1800 Vector<Vector3> points;
1801
1802 Vector3 d(0, 0, height * 0.5);
1803 for (int i = 0; i < 360; i++) {
1804
1805 float ra = Math::deg2rad(i);
1806 float rb = Math::deg2rad(i + 1);
1807 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius;
1808 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius;
1809
1810 points.push_back(Vector3(a.x, a.y, 0) + d);
1811 points.push_back(Vector3(b.x, b.y, 0) + d);
1812
1813 points.push_back(Vector3(a.x, a.y, 0) - d);
1814 points.push_back(Vector3(b.x, b.y, 0) - d);
1815
1816 if (i % 90 == 0) {
1817
1818 points.push_back(Vector3(a.x, a.y, 0) + d);
1819 points.push_back(Vector3(a.x, a.y, 0) - d);
1820 }
1821
1822 Vector3 dud = i < 180 ? d : -d;
1823
1824 points.push_back(Vector3(0, a.y, a.x) + dud);
1825 points.push_back(Vector3(0, b.y, b.x) + dud);
1826 points.push_back(Vector3(a.y, 0, a.x) + dud);
1827 points.push_back(Vector3(b.y, 0, b.x) + dud);
1828 }
1829
1830 add_lines(points, SpatialEditorGizmos::singleton->shape_material);
1831
1832 Vector<Vector3> collision_segments;
1833
1834 for (int i = 0; i < 64; i++) {
1835
1836 float ra = i * Math_PI * 2.0 / 64.0;
1837 float rb = (i + 1) * Math_PI * 2.0 / 64.0;
1838 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius;
1839 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius;
1840
1841 collision_segments.push_back(Vector3(a.x, a.y, 0) + d);
1842 collision_segments.push_back(Vector3(b.x, b.y, 0) + d);
1843
1844 collision_segments.push_back(Vector3(a.x, a.y, 0) - d);
1845 collision_segments.push_back(Vector3(b.x, b.y, 0) - d);
1846
1847 if (i % 16 == 0) {
1848
1849 collision_segments.push_back(Vector3(a.x, a.y, 0) + d);
1850 collision_segments.push_back(Vector3(a.x, a.y, 0) - d);
1851 }
1852
1853 Vector3 dud = i < 32 ? d : -d;
1854
1855 collision_segments.push_back(Vector3(0, a.y, a.x) + dud);
1856 collision_segments.push_back(Vector3(0, b.y, b.x) + dud);
1857 collision_segments.push_back(Vector3(a.y, 0, a.x) + dud);
1858 collision_segments.push_back(Vector3(b.y, 0, b.x) + dud);
1859 }
1860
1861 add_collision_segments(collision_segments);
1862
1863 Vector<Vector3> handles;
1864 handles.push_back(Vector3(cs->get_radius(), 0, 0));
1865 handles.push_back(Vector3(0, 0, cs->get_height() * 0.5 + cs->get_radius()));
1866 add_handles(handles);
1867 }
1868
1869 if (s->cast_to<PlaneShape>()) {
1870
1871 Ref<PlaneShape> ps = s;
1872 Plane p = ps->get_plane();
1873 Vector<Vector3> points;
1874
1875 Vector3 n1 = p.get_any_perpendicular_normal();
1876 Vector3 n2 = p.normal.cross(n1).normalized();
1877
1878 Vector3 pface[4] = {
1879 p.normal * p.d + n1 * 10.0 + n2 * 10.0,
1880 p.normal * p.d + n1 * 10.0 + n2 * -10.0,
1881 p.normal * p.d + n1 * -10.0 + n2 * -10.0,
1882 p.normal * p.d + n1 * -10.0 + n2 * 10.0,
1883 };
1884
1885 points.push_back(pface[0]);
1886 points.push_back(pface[1]);
1887 points.push_back(pface[1]);
1888 points.push_back(pface[2]);
1889 points.push_back(pface[2]);
1890 points.push_back(pface[3]);
1891 points.push_back(pface[3]);
1892 points.push_back(pface[0]);
1893 points.push_back(p.normal * p.d);
1894 points.push_back(p.normal * p.d + p.normal * 3);
1895
1896 add_lines(points, SpatialEditorGizmos::singleton->shape_material);
1897 add_collision_segments(points);
1898 }
1899
1900 if (s->cast_to<ConvexPolygonShape>()) {
1901
1902 DVector<Vector3> points = s->cast_to<ConvexPolygonShape>()->get_points();
1903
1904 if (points.size() > 3) {
1905
1906 QuickHull qh;
1907 Vector<Vector3> varr = Variant(points);
1908 Geometry::MeshData md;
1909 Error err = qh.build(varr, md);
1910 if (err == OK) {
1911 Vector<Vector3> points;
1912 points.resize(md.edges.size() * 2);
1913 for (int i = 0; i < md.edges.size(); i++) {
1914 points[i * 2 + 0] = md.vertices[md.edges[i].a];
1915 points[i * 2 + 1] = md.vertices[md.edges[i].b];
1916 }
1917
1918 add_lines(points, SpatialEditorGizmos::singleton->shape_material);
1919 add_collision_segments(points);
1920 }
1921 }
1922 }
1923
1924 if (s->cast_to<RayShape>()) {
1925
1926 Ref<RayShape> rs = s;
1927
1928 Vector<Vector3> points;
1929 points.push_back(Vector3());
1930 points.push_back(Vector3(0, 0, rs->get_length()));
1931 add_lines(points, SpatialEditorGizmos::singleton->shape_material);
1932 add_collision_segments(points);
1933 Vector<Vector3> handles;
1934 handles.push_back(Vector3(0, 0, rs->get_length()));
1935 add_handles(handles);
1936 }
1937 }
CollisionShapeSpatialGizmo(CollisionShape * p_cs)1938 CollisionShapeSpatialGizmo::CollisionShapeSpatialGizmo(CollisionShape *p_cs) {
1939
1940 cs = p_cs;
1941 set_spatial_node(p_cs);
1942 }
1943
1944 /////
1945
redraw()1946 void CollisionPolygonSpatialGizmo::redraw() {
1947
1948 clear();
1949
1950 Vector<Vector2> points = polygon->get_polygon();
1951 float depth = polygon->get_depth() * 0.5;
1952
1953 Vector<Vector3> lines;
1954 for (int i = 0; i < points.size(); i++) {
1955
1956 int n = (i + 1) % points.size();
1957 lines.push_back(Vector3(points[i].x, points[i].y, depth));
1958 lines.push_back(Vector3(points[n].x, points[n].y, depth));
1959 lines.push_back(Vector3(points[i].x, points[i].y, -depth));
1960 lines.push_back(Vector3(points[n].x, points[n].y, -depth));
1961 lines.push_back(Vector3(points[i].x, points[i].y, depth));
1962 lines.push_back(Vector3(points[i].x, points[i].y, -depth));
1963 }
1964
1965 add_lines(lines, SpatialEditorGizmos::singleton->shape_material);
1966 add_collision_segments(lines);
1967 }
1968
CollisionPolygonSpatialGizmo(CollisionPolygon * p_polygon)1969 CollisionPolygonSpatialGizmo::CollisionPolygonSpatialGizmo(CollisionPolygon *p_polygon) {
1970
1971 set_spatial_node(p_polygon);
1972 polygon = p_polygon;
1973 }
1974 ///
1975
get_handle_name(int p_idx) const1976 String VisibilityNotifierGizmo::get_handle_name(int p_idx) const {
1977
1978 switch (p_idx) {
1979 case 0: return "X";
1980 case 1: return "Y";
1981 case 2: return "Z";
1982 }
1983
1984 return "";
1985 }
get_handle_value(int p_idx) const1986 Variant VisibilityNotifierGizmo::get_handle_value(int p_idx) const {
1987
1988 return notifier->get_aabb();
1989 }
set_handle(int p_idx,Camera * p_camera,const Point2 & p_point)1990 void VisibilityNotifierGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) {
1991
1992 Transform gt = notifier->get_global_transform();
1993 //gt.orthonormalize();
1994 Transform gi = gt.affine_inverse();
1995
1996 AABB aabb = notifier->get_aabb();
1997 Vector3 ray_from = p_camera->project_ray_origin(p_point);
1998 Vector3 ray_dir = p_camera->project_ray_normal(p_point);
1999
2000 Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
2001 Vector3 ofs = aabb.pos + aabb.size * 0.5;
2002
2003 Vector3 axis;
2004 axis[p_idx] = 1.0;
2005
2006 Vector3 ra, rb;
2007 Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
2008 float d = ra[p_idx];
2009 if (d < 0.001)
2010 d = 0.001;
2011
2012 aabb.pos[p_idx] = (aabb.pos[p_idx] + aabb.size[p_idx] * 0.5) - d;
2013 aabb.size[p_idx] = d * 2;
2014 notifier->set_aabb(aabb);
2015 }
2016
commit_handle(int p_idx,const Variant & p_restore,bool p_cancel)2017 void VisibilityNotifierGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
2018
2019 if (p_cancel) {
2020 notifier->set_aabb(p_restore);
2021 return;
2022 }
2023
2024 UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
2025 ur->create_action(TTR("Change Notifier Extents"));
2026 ur->add_do_method(notifier, "set_aabb", notifier->get_aabb());
2027 ur->add_undo_method(notifier, "set_aabb", p_restore);
2028 ur->commit_action();
2029 }
2030
redraw()2031 void VisibilityNotifierGizmo::redraw() {
2032
2033 clear();
2034
2035 Vector<Vector3> lines;
2036 AABB aabb = notifier->get_aabb();
2037
2038 for (int i = 0; i < 12; i++) {
2039 Vector3 a, b;
2040 aabb.get_edge(i, a, b);
2041 lines.push_back(a);
2042 lines.push_back(b);
2043 }
2044
2045 Vector<Vector3> handles;
2046
2047 for (int i = 0; i < 3; i++) {
2048
2049 Vector3 ax;
2050 ax[i] = aabb.pos[i] + aabb.size[i];
2051 handles.push_back(ax);
2052 }
2053
2054 add_lines(lines, SpatialEditorGizmos::singleton->visibility_notifier_material);
2055 //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
2056 add_collision_segments(lines);
2057 add_handles(handles);
2058 }
VisibilityNotifierGizmo(VisibilityNotifier * p_notifier)2059 VisibilityNotifierGizmo::VisibilityNotifierGizmo(VisibilityNotifier *p_notifier) {
2060
2061 notifier = p_notifier;
2062 set_spatial_node(p_notifier);
2063 }
2064
2065 ////////
2066
redraw()2067 void NavigationMeshSpatialGizmo::redraw() {
2068
2069 clear();
2070 Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh();
2071 if (navmeshie.is_null())
2072 return;
2073
2074 DVector<Vector3> vertices = navmeshie->get_vertices();
2075 DVector<Vector3>::Read vr = vertices.read();
2076 List<Face3> faces;
2077 for (int i = 0; i < navmeshie->get_polygon_count(); i++) {
2078 Vector<int> p = navmeshie->get_polygon(i);
2079
2080 for (int j = 2; j < p.size(); j++) {
2081 Face3 f;
2082 f.vertex[0] = vr[p[0]];
2083 f.vertex[1] = vr[p[j - 1]];
2084 f.vertex[2] = vr[p[j]];
2085
2086 faces.push_back(f);
2087 }
2088 }
2089
2090 if (faces.empty())
2091 return;
2092
2093 Map<_EdgeKey, bool> edge_map;
2094 DVector<Vector3> tmeshfaces;
2095 tmeshfaces.resize(faces.size() * 3);
2096
2097 {
2098 DVector<Vector3>::Write tw = tmeshfaces.write();
2099 int tidx = 0;
2100
2101 for (List<Face3>::Element *E = faces.front(); E; E = E->next()) {
2102
2103 const Face3 &f = E->get();
2104
2105 for (int j = 0; j < 3; j++) {
2106
2107 tw[tidx++] = f.vertex[j];
2108 _EdgeKey ek;
2109 ek.from = f.vertex[j].snapped(CMP_EPSILON);
2110 ek.to = f.vertex[(j + 1) % 3].snapped(CMP_EPSILON);
2111 if (ek.from < ek.to)
2112 SWAP(ek.from, ek.to);
2113
2114 Map<_EdgeKey, bool>::Element *E = edge_map.find(ek);
2115
2116 if (E) {
2117
2118 E->get() = false;
2119
2120 } else {
2121
2122 edge_map[ek] = true;
2123 }
2124 }
2125 }
2126 }
2127 Vector<Vector3> lines;
2128
2129 for (Map<_EdgeKey, bool>::Element *E = edge_map.front(); E; E = E->next()) {
2130
2131 if (E->get()) {
2132 lines.push_back(E->key().from);
2133 lines.push_back(E->key().to);
2134 }
2135 }
2136
2137 Ref<TriangleMesh> tmesh = memnew(TriangleMesh);
2138 tmesh->create(tmeshfaces);
2139
2140 if (lines.size())
2141 add_lines(lines, navmesh->is_enabled() ? SpatialEditorGizmos::singleton->navmesh_edge_material : SpatialEditorGizmos::singleton->navmesh_edge_material_disabled);
2142 add_collision_triangles(tmesh);
2143 Ref<Mesh> m = memnew(Mesh);
2144 Array a;
2145 a.resize(Mesh::ARRAY_MAX);
2146 a[0] = tmeshfaces;
2147 m->add_surface(Mesh::PRIMITIVE_TRIANGLES, a);
2148 m->surface_set_material(0, navmesh->is_enabled() ? SpatialEditorGizmos::singleton->navmesh_solid_material : SpatialEditorGizmos::singleton->navmesh_solid_material_disabled);
2149 add_mesh(m);
2150 add_collision_segments(lines);
2151 }
2152
NavigationMeshSpatialGizmo(NavigationMeshInstance * p_navmesh)2153 NavigationMeshSpatialGizmo::NavigationMeshSpatialGizmo(NavigationMeshInstance *p_navmesh) {
2154
2155 set_spatial_node(p_navmesh);
2156 navmesh = p_navmesh;
2157 }
2158
2159 //////
2160 ///
2161 ///
2162
redraw()2163 void PinJointSpatialGizmo::redraw() {
2164
2165 clear();
2166 Vector<Vector3> cursor_points;
2167 float cs = 0.25;
2168 cursor_points.push_back(Vector3(+cs, 0, 0));
2169 cursor_points.push_back(Vector3(-cs, 0, 0));
2170 cursor_points.push_back(Vector3(0, +cs, 0));
2171 cursor_points.push_back(Vector3(0, -cs, 0));
2172 cursor_points.push_back(Vector3(0, 0, +cs));
2173 cursor_points.push_back(Vector3(0, 0, -cs));
2174 add_collision_segments(cursor_points);
2175 add_lines(cursor_points, SpatialEditorGizmos::singleton->joint_material);
2176 }
2177
PinJointSpatialGizmo(PinJoint * p_p3d)2178 PinJointSpatialGizmo::PinJointSpatialGizmo(PinJoint *p_p3d) {
2179
2180 p3d = p_p3d;
2181 set_spatial_node(p3d);
2182 }
2183
2184 ////
2185
redraw()2186 void HingeJointSpatialGizmo::redraw() {
2187
2188 clear();
2189 Vector<Vector3> cursor_points;
2190 float cs = 0.25;
2191 /*cursor_points.push_back(Vector3(+cs,0,0));
2192 cursor_points.push_back(Vector3(-cs,0,0));
2193 cursor_points.push_back(Vector3(0,+cs,0));
2194 cursor_points.push_back(Vector3(0,-cs,0));*/
2195 cursor_points.push_back(Vector3(0, 0, +cs * 2));
2196 cursor_points.push_back(Vector3(0, 0, -cs * 2));
2197
2198 float ll = p3d->get_param(HingeJoint::PARAM_LIMIT_LOWER);
2199 float ul = p3d->get_param(HingeJoint::PARAM_LIMIT_UPPER);
2200
2201 if (p3d->get_flag(HingeJoint::FLAG_USE_LIMIT) && ll < ul) {
2202
2203 const int points = 32;
2204
2205 for (int i = 0; i < points; i++) {
2206
2207 float s = ll + i * (ul - ll) / points;
2208 float n = ll + (i + 1) * (ul - ll) / points;
2209
2210 Vector3 from = Vector3(-Math::sin(s), Math::cos(s), 0) * cs;
2211 Vector3 to = Vector3(-Math::sin(n), Math::cos(n), 0) * cs;
2212
2213 if (i == points - 1) {
2214 cursor_points.push_back(to);
2215 cursor_points.push_back(Vector3());
2216 }
2217 if (i == 0) {
2218 cursor_points.push_back(from);
2219 cursor_points.push_back(Vector3());
2220 }
2221
2222 cursor_points.push_back(from);
2223 cursor_points.push_back(to);
2224 }
2225
2226 cursor_points.push_back(Vector3(0, cs * 1.5, 0));
2227 cursor_points.push_back(Vector3());
2228
2229 } else {
2230
2231 const int points = 32;
2232
2233 for (int i = 0; i < points; i++) {
2234
2235 float s = ll + i * (Math_PI * 2.0) / points;
2236 float n = ll + (i + 1) * (Math_PI * 2.0) / points;
2237
2238 Vector3 from = Vector3(-Math::sin(s), Math::cos(s), 0) * cs;
2239 Vector3 to = Vector3(-Math::sin(n), Math::cos(n), 0) * cs;
2240
2241 cursor_points.push_back(from);
2242 cursor_points.push_back(to);
2243 }
2244 }
2245 add_collision_segments(cursor_points);
2246 add_lines(cursor_points, SpatialEditorGizmos::singleton->joint_material);
2247 }
2248
HingeJointSpatialGizmo(HingeJoint * p_p3d)2249 HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint *p_p3d) {
2250
2251 p3d = p_p3d;
2252 set_spatial_node(p3d);
2253 }
2254
2255 ///////
2256 ///
2257 ////
2258
redraw()2259 void SliderJointSpatialGizmo::redraw() {
2260
2261 clear();
2262 Vector<Vector3> cursor_points;
2263 float cs = 0.25;
2264 /*cursor_points.push_back(Vector3(+cs,0,0));
2265 cursor_points.push_back(Vector3(-cs,0,0));
2266 cursor_points.push_back(Vector3(0,+cs,0));
2267 cursor_points.push_back(Vector3(0,-cs,0));*/
2268 cursor_points.push_back(Vector3(0, 0, +cs * 2));
2269 cursor_points.push_back(Vector3(0, 0, -cs * 2));
2270
2271 float ll = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER);
2272 float ul = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER);
2273 float lll = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER);
2274 float lul = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER);
2275
2276 if (lll > lul) {
2277
2278 cursor_points.push_back(Vector3(lul, 0, 0));
2279 cursor_points.push_back(Vector3(lll, 0, 0));
2280
2281 cursor_points.push_back(Vector3(lul, -cs, -cs));
2282 cursor_points.push_back(Vector3(lul, -cs, cs));
2283 cursor_points.push_back(Vector3(lul, -cs, cs));
2284 cursor_points.push_back(Vector3(lul, cs, cs));
2285 cursor_points.push_back(Vector3(lul, cs, cs));
2286 cursor_points.push_back(Vector3(lul, cs, -cs));
2287 cursor_points.push_back(Vector3(lul, cs, -cs));
2288 cursor_points.push_back(Vector3(lul, -cs, -cs));
2289
2290 cursor_points.push_back(Vector3(lll, -cs, -cs));
2291 cursor_points.push_back(Vector3(lll, -cs, cs));
2292 cursor_points.push_back(Vector3(lll, -cs, cs));
2293 cursor_points.push_back(Vector3(lll, cs, cs));
2294 cursor_points.push_back(Vector3(lll, cs, cs));
2295 cursor_points.push_back(Vector3(lll, cs, -cs));
2296 cursor_points.push_back(Vector3(lll, cs, -cs));
2297 cursor_points.push_back(Vector3(lll, -cs, -cs));
2298
2299 } else {
2300
2301 cursor_points.push_back(Vector3(+cs * 2, 0, 0));
2302 cursor_points.push_back(Vector3(-cs * 2, 0, 0));
2303 }
2304
2305 if (ll < ul) {
2306
2307 const int points = 32;
2308
2309 for (int i = 0; i < points; i++) {
2310
2311 float s = ll + i * (ul - ll) / points;
2312 float n = ll + (i + 1) * (ul - ll) / points;
2313
2314 Vector3 from = Vector3(0, Math::cos(s), -Math::sin(s)) * cs;
2315 Vector3 to = Vector3(0, Math::cos(n), -Math::sin(n)) * cs;
2316
2317 if (i == points - 1) {
2318 cursor_points.push_back(to);
2319 cursor_points.push_back(Vector3());
2320 }
2321 if (i == 0) {
2322 cursor_points.push_back(from);
2323 cursor_points.push_back(Vector3());
2324 }
2325
2326 cursor_points.push_back(from);
2327 cursor_points.push_back(to);
2328 }
2329
2330 cursor_points.push_back(Vector3(0, cs * 1.5, 0));
2331 cursor_points.push_back(Vector3());
2332
2333 } else {
2334
2335 const int points = 32;
2336
2337 for (int i = 0; i < points; i++) {
2338
2339 float s = ll + i * (Math_PI * 2.0) / points;
2340 float n = ll + (i + 1) * (Math_PI * 2.0) / points;
2341
2342 Vector3 from = Vector3(0, Math::cos(s), -Math::sin(s)) * cs;
2343 Vector3 to = Vector3(0, Math::cos(n), -Math::sin(n)) * cs;
2344
2345 cursor_points.push_back(from);
2346 cursor_points.push_back(to);
2347 }
2348 }
2349 add_collision_segments(cursor_points);
2350 add_lines(cursor_points, SpatialEditorGizmos::singleton->joint_material);
2351 }
2352
SliderJointSpatialGizmo(SliderJoint * p_p3d)2353 SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint *p_p3d) {
2354
2355 p3d = p_p3d;
2356 set_spatial_node(p3d);
2357 }
2358
2359 ///////
2360 ///
2361 ////
2362
redraw()2363 void ConeTwistJointSpatialGizmo::redraw() {
2364
2365 clear();
2366 Vector<Vector3> points;
2367
2368 float r = 1.0;
2369 float w = r * Math::sin(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
2370 float d = r * Math::cos(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
2371
2372 //swing
2373 for (int i = 0; i < 360; i += 10) {
2374
2375 float ra = Math::deg2rad(i);
2376 float rb = Math::deg2rad(i + 10);
2377 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
2378 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
2379
2380 /*points.push_back(Vector3(a.x,0,a.y));
2381 points.push_back(Vector3(b.x,0,b.y));
2382 points.push_back(Vector3(0,a.x,a.y));
2383 points.push_back(Vector3(0,b.x,b.y));*/
2384 points.push_back(Vector3(d, a.x, a.y));
2385 points.push_back(Vector3(d, b.x, b.y));
2386
2387 if (i % 90 == 0) {
2388
2389 points.push_back(Vector3(d, a.x, a.y));
2390 points.push_back(Vector3());
2391 }
2392 }
2393
2394 points.push_back(Vector3());
2395 points.push_back(Vector3(1, 0, 0));
2396
2397 //twist
2398 /*
2399 */
2400 float ts = Math::rad2deg(p3d->get_param(ConeTwistJoint::PARAM_TWIST_SPAN));
2401 ts = MIN(ts, 720);
2402
2403 for (int i = 0; i < int(ts); i += 5) {
2404
2405 float ra = Math::deg2rad(i);
2406 float rb = Math::deg2rad(i + 5);
2407 float c = i / 720.0;
2408 float cn = (i + 5) / 720.0;
2409 Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w * c;
2410 Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w * cn;
2411
2412 /*points.push_back(Vector3(a.x,0,a.y));
2413 points.push_back(Vector3(b.x,0,b.y));
2414 points.push_back(Vector3(0,a.x,a.y));
2415 points.push_back(Vector3(0,b.x,b.y));*/
2416
2417 points.push_back(Vector3(c, a.x, a.y));
2418 points.push_back(Vector3(cn, b.x, b.y));
2419 }
2420
2421 add_collision_segments(points);
2422 add_lines(points, SpatialEditorGizmos::singleton->joint_material);
2423 }
2424
ConeTwistJointSpatialGizmo(ConeTwistJoint * p_p3d)2425 ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint *p_p3d) {
2426
2427 p3d = p_p3d;
2428 set_spatial_node(p3d);
2429 }
2430
2431 ////////
2432 /// \brief SpatialEditorGizmos::singleton
2433 ///
2434 ///////
2435 ///
2436 ////
2437
redraw()2438 void Generic6DOFJointSpatialGizmo::redraw() {
2439
2440 clear();
2441 Vector<Vector3> cursor_points;
2442 float cs = 0.25;
2443
2444 for (int ax = 0; ax < 3; ax++) {
2445 /*cursor_points.push_back(Vector3(+cs,0,0));
2446 cursor_points.push_back(Vector3(-cs,0,0));
2447 cursor_points.push_back(Vector3(0,+cs,0));
2448 cursor_points.push_back(Vector3(0,-cs,0));
2449 cursor_points.push_back(Vector3(0,0,+cs*2));
2450 cursor_points.push_back(Vector3(0,0,-cs*2)); */
2451
2452 float ll;
2453 float ul;
2454 float lll;
2455 float lul;
2456
2457 int a1, a2, a3;
2458 bool enable_ang;
2459 bool enable_lin;
2460
2461 switch (ax) {
2462 case 0:
2463 ll = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
2464 ul = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
2465 lll = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
2466 lul = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
2467 enable_ang = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
2468 enable_lin = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
2469 a1 = 0;
2470 a2 = 1;
2471 a3 = 2;
2472 break;
2473 case 1:
2474 ll = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
2475 ul = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
2476 lll = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
2477 lul = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
2478 enable_ang = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
2479 enable_lin = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
2480 a1 = 2;
2481 a2 = 0;
2482 a3 = 1;
2483 break;
2484 case 2:
2485 ll = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
2486 ul = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
2487 lll = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
2488 lul = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
2489 enable_ang = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
2490 enable_lin = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
2491
2492 a1 = 1;
2493 a2 = 2;
2494 a3 = 0;
2495 break;
2496 }
2497
2498 #define ADD_VTX(x, y, z) \
2499 { \
2500 Vector3 v; \
2501 v[a1] = (x); \
2502 v[a2] = (y); \
2503 v[a3] = (z); \
2504 cursor_points.push_back(v); \
2505 }
2506
2507 #define SET_VTX(what, x, y, z) \
2508 { \
2509 Vector3 v; \
2510 v[a1] = (x); \
2511 v[a2] = (y); \
2512 v[a3] = (z); \
2513 what = v; \
2514 }
2515
2516 if (enable_lin && lll >= lul) {
2517
2518 ADD_VTX(lul, 0, 0);
2519 ADD_VTX(lll, 0, 0);
2520
2521 ADD_VTX(lul, -cs, -cs);
2522 ADD_VTX(lul, -cs, cs);
2523 ADD_VTX(lul, -cs, cs);
2524 ADD_VTX(lul, cs, cs);
2525 ADD_VTX(lul, cs, cs);
2526 ADD_VTX(lul, cs, -cs);
2527 ADD_VTX(lul, cs, -cs);
2528 ADD_VTX(lul, -cs, -cs);
2529
2530 ADD_VTX(lll, -cs, -cs);
2531 ADD_VTX(lll, -cs, cs);
2532 ADD_VTX(lll, -cs, cs);
2533 ADD_VTX(lll, cs, cs);
2534 ADD_VTX(lll, cs, cs);
2535 ADD_VTX(lll, cs, -cs);
2536 ADD_VTX(lll, cs, -cs);
2537 ADD_VTX(lll, -cs, -cs);
2538
2539 } else {
2540
2541 ADD_VTX(+cs * 2, 0, 0);
2542 ADD_VTX(-cs * 2, 0, 0);
2543 }
2544
2545 if (enable_ang && ll <= ul) {
2546
2547 const int points = 32;
2548
2549 for (int i = 0; i < points; i++) {
2550
2551 float s = ll + i * (ul - ll) / points;
2552 float n = ll + (i + 1) * (ul - ll) / points;
2553
2554 Vector3 from;
2555 SET_VTX(from, 0, Math::cos(s), -Math::sin(s));
2556 from *= cs;
2557 Vector3 to;
2558 SET_VTX(to, 0, Math::cos(n), -Math::sin(n));
2559 to *= cs;
2560
2561 if (i == points - 1) {
2562 cursor_points.push_back(to);
2563 cursor_points.push_back(Vector3());
2564 }
2565 if (i == 0) {
2566 cursor_points.push_back(from);
2567 cursor_points.push_back(Vector3());
2568 }
2569
2570 cursor_points.push_back(from);
2571 cursor_points.push_back(to);
2572 }
2573
2574 ADD_VTX(0, cs * 1.5, 0);
2575 cursor_points.push_back(Vector3());
2576
2577 } else {
2578
2579 const int points = 32;
2580
2581 for (int i = 0; i < points; i++) {
2582
2583 float s = ll + i * (Math_PI * 2.0) / points;
2584 float n = ll + (i + 1) * (Math_PI * 2.0) / points;
2585
2586 // Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs;
2587 // Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs;
2588
2589 Vector3 from;
2590 SET_VTX(from, 0, Math::cos(s), -Math::sin(s));
2591 from *= cs;
2592 Vector3 to;
2593 SET_VTX(to, 0, Math::cos(n), -Math::sin(n));
2594 to *= cs;
2595
2596 cursor_points.push_back(from);
2597 cursor_points.push_back(to);
2598 }
2599 }
2600 }
2601
2602 #undef ADD_VTX
2603 #undef SET_VTX
2604
2605 add_collision_segments(cursor_points);
2606 add_lines(cursor_points, SpatialEditorGizmos::singleton->joint_material);
2607 }
2608
Generic6DOFJointSpatialGizmo(Generic6DOFJoint * p_p3d)2609 Generic6DOFJointSpatialGizmo::Generic6DOFJointSpatialGizmo(Generic6DOFJoint *p_p3d) {
2610
2611 p3d = p_p3d;
2612 set_spatial_node(p3d);
2613 }
2614
2615 ///////
2616 ///
2617 ////
2618
2619 SpatialEditorGizmos *SpatialEditorGizmos::singleton = NULL;
2620
get_gizmo(Spatial * p_spatial)2621 Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) {
2622
2623 if (p_spatial->cast_to<Light>()) {
2624
2625 Ref<LightSpatialGizmo> lsg = memnew(LightSpatialGizmo(p_spatial->cast_to<Light>()));
2626 return lsg;
2627 }
2628
2629 if (p_spatial->cast_to<Listener>()) {
2630
2631 Ref<ListenerSpatialGizmo> misg = memnew(ListenerSpatialGizmo(p_spatial->cast_to<Listener>()));
2632 return misg;
2633 }
2634
2635 if (p_spatial->cast_to<Camera>()) {
2636
2637 Ref<CameraSpatialGizmo> lsg = memnew(CameraSpatialGizmo(p_spatial->cast_to<Camera>()));
2638 return lsg;
2639 }
2640
2641 if (p_spatial->cast_to<Skeleton>()) {
2642
2643 Ref<SkeletonSpatialGizmo> lsg = memnew(SkeletonSpatialGizmo(p_spatial->cast_to<Skeleton>()));
2644 return lsg;
2645 }
2646
2647 if (p_spatial->cast_to<Position3D>()) {
2648
2649 Ref<Position3DSpatialGizmo> lsg = memnew(Position3DSpatialGizmo(p_spatial->cast_to<Position3D>()));
2650 return lsg;
2651 }
2652
2653 if (p_spatial->cast_to<MeshInstance>()) {
2654
2655 Ref<MeshInstanceSpatialGizmo> misg = memnew(MeshInstanceSpatialGizmo(p_spatial->cast_to<MeshInstance>()));
2656 return misg;
2657 }
2658
2659 if (p_spatial->cast_to<Room>()) {
2660
2661 Ref<RoomSpatialGizmo> misg = memnew(RoomSpatialGizmo(p_spatial->cast_to<Room>()));
2662 return misg;
2663 }
2664
2665 if (p_spatial->cast_to<NavigationMeshInstance>()) {
2666
2667 Ref<NavigationMeshSpatialGizmo> misg = memnew(NavigationMeshSpatialGizmo(p_spatial->cast_to<NavigationMeshInstance>()));
2668 return misg;
2669 }
2670
2671 if (p_spatial->cast_to<RayCast>()) {
2672
2673 Ref<RayCastSpatialGizmo> misg = memnew(RayCastSpatialGizmo(p_spatial->cast_to<RayCast>()));
2674 return misg;
2675 }
2676
2677 if (p_spatial->cast_to<Portal>()) {
2678
2679 Ref<PortalSpatialGizmo> misg = memnew(PortalSpatialGizmo(p_spatial->cast_to<Portal>()));
2680 return misg;
2681 }
2682
2683 if (p_spatial->cast_to<TestCube>()) {
2684
2685 Ref<TestCubeSpatialGizmo> misg = memnew(TestCubeSpatialGizmo(p_spatial->cast_to<TestCube>()));
2686 return misg;
2687 }
2688
2689 if (p_spatial->cast_to<SpatialPlayer>()) {
2690
2691 Ref<SpatialPlayerSpatialGizmo> misg = memnew(SpatialPlayerSpatialGizmo(p_spatial->cast_to<SpatialPlayer>()));
2692 return misg;
2693 }
2694
2695 if (p_spatial->cast_to<CollisionShape>()) {
2696
2697 Ref<CollisionShapeSpatialGizmo> misg = memnew(CollisionShapeSpatialGizmo(p_spatial->cast_to<CollisionShape>()));
2698 return misg;
2699 }
2700
2701 if (p_spatial->cast_to<VisibilityNotifier>()) {
2702
2703 Ref<VisibilityNotifierGizmo> misg = memnew(VisibilityNotifierGizmo(p_spatial->cast_to<VisibilityNotifier>()));
2704 return misg;
2705 }
2706
2707 if (p_spatial->cast_to<VehicleWheel>()) {
2708
2709 Ref<VehicleWheelSpatialGizmo> misg = memnew(VehicleWheelSpatialGizmo(p_spatial->cast_to<VehicleWheel>()));
2710 return misg;
2711 }
2712 if (p_spatial->cast_to<PinJoint>()) {
2713
2714 Ref<PinJointSpatialGizmo> misg = memnew(PinJointSpatialGizmo(p_spatial->cast_to<PinJoint>()));
2715 return misg;
2716 }
2717
2718 if (p_spatial->cast_to<HingeJoint>()) {
2719
2720 Ref<HingeJointSpatialGizmo> misg = memnew(HingeJointSpatialGizmo(p_spatial->cast_to<HingeJoint>()));
2721 return misg;
2722 }
2723
2724 if (p_spatial->cast_to<SliderJoint>()) {
2725
2726 Ref<SliderJointSpatialGizmo> misg = memnew(SliderJointSpatialGizmo(p_spatial->cast_to<SliderJoint>()));
2727 return misg;
2728 }
2729
2730 if (p_spatial->cast_to<ConeTwistJoint>()) {
2731
2732 Ref<ConeTwistJointSpatialGizmo> misg = memnew(ConeTwistJointSpatialGizmo(p_spatial->cast_to<ConeTwistJoint>()));
2733 return misg;
2734 }
2735
2736 if (p_spatial->cast_to<Generic6DOFJoint>()) {
2737
2738 Ref<Generic6DOFJointSpatialGizmo> misg = memnew(Generic6DOFJointSpatialGizmo(p_spatial->cast_to<Generic6DOFJoint>()));
2739 return misg;
2740 }
2741
2742 if (p_spatial->cast_to<CollisionPolygon>()) {
2743
2744 Ref<CollisionPolygonSpatialGizmo> misg = memnew(CollisionPolygonSpatialGizmo(p_spatial->cast_to<CollisionPolygon>()));
2745 return misg;
2746 }
2747
2748 return Ref<SpatialEditorGizmo>();
2749 }
2750
create_line_material(const Color & p_base_color)2751 Ref<FixedMaterial> SpatialEditorGizmos::create_line_material(const Color &p_base_color) {
2752
2753 Ref<FixedMaterial> line_material = Ref<FixedMaterial>(memnew(FixedMaterial));
2754 line_material->set_flag(Material::FLAG_UNSHADED, true);
2755 line_material->set_line_width(3.0);
2756 line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2757 line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
2758 line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE, p_base_color);
2759
2760 return line_material;
2761 }
2762
create_solid_material(const Color & p_base_color)2763 Ref<FixedMaterial> SpatialEditorGizmos::create_solid_material(const Color &p_base_color) {
2764
2765 Ref<FixedMaterial> line_material = Ref<FixedMaterial>(memnew(FixedMaterial));
2766 line_material->set_flag(Material::FLAG_UNSHADED, true);
2767 line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2768 line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE, p_base_color);
2769
2770 return line_material;
2771 }
2772
SpatialEditorGizmos()2773 SpatialEditorGizmos::SpatialEditorGizmos() {
2774
2775 singleton = this;
2776
2777 handle_material = Ref<FixedMaterial>(memnew(FixedMaterial));
2778 handle_material->set_flag(Material::FLAG_UNSHADED, true);
2779 handle_material->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(0.8, 0.8, 0.8));
2780
2781 handle2_material = Ref<FixedMaterial>(memnew(FixedMaterial));
2782 handle2_material->set_flag(Material::FLAG_UNSHADED, true);
2783 handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_POINT_SIZE, true);
2784 handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle", "EditorIcons");
2785 handle2_material->set_point_size(handle_t->get_width());
2786 handle2_material->set_texture(FixedMaterial::PARAM_DIFFUSE, handle_t);
2787 handle2_material->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1));
2788 handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2789 handle2_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
2790
2791 light_material = create_line_material(Color(1, 1, 0.2));
2792
2793 light_material_omni_icon = Ref<FixedMaterial>(memnew(FixedMaterial));
2794 light_material_omni_icon->set_flag(Material::FLAG_UNSHADED, true);
2795 light_material_omni_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2796 light_material_omni_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
2797 light_material_omni_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2798 light_material_omni_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1, 0.9));
2799 light_material_omni_icon->set_texture(FixedMaterial::PARAM_DIFFUSE, SpatialEditor::get_singleton()->get_icon("GizmoLight", "EditorIcons"));
2800
2801 light_material_directional_icon = Ref<FixedMaterial>(memnew(FixedMaterial));
2802 light_material_directional_icon->set_flag(Material::FLAG_UNSHADED, true);
2803 light_material_directional_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2804 light_material_directional_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
2805 light_material_directional_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2806 light_material_directional_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1, 0.9));
2807 light_material_directional_icon->set_texture(FixedMaterial::PARAM_DIFFUSE, SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons"));
2808
2809 camera_material = create_line_material(Color(1.0, 0.5, 1.0));
2810
2811 navmesh_edge_material = create_line_material(Color(0.1, 0.8, 1.0));
2812 navmesh_solid_material = create_solid_material(Color(0.1, 0.8, 1.0, 0.4));
2813 navmesh_edge_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, false);
2814 navmesh_solid_material->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2815
2816 navmesh_edge_material_disabled = create_line_material(Color(1.0, 0.8, 0.1));
2817 navmesh_solid_material_disabled = create_solid_material(Color(1.0, 0.8, 0.1, 0.4));
2818 navmesh_edge_material_disabled->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, false);
2819 navmesh_solid_material_disabled->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2820
2821 skeleton_material = create_line_material(Color(0.6, 1.0, 0.3));
2822 skeleton_material->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2823 skeleton_material->set_flag(Material::FLAG_UNSHADED, true);
2824 skeleton_material->set_flag(Material::FLAG_ONTOP, true);
2825 skeleton_material->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
2826
2827 //position 3D Shared mesh
2828
2829 pos3d_mesh = Ref<Mesh>(memnew(Mesh));
2830 {
2831
2832 DVector<Vector3> cursor_points;
2833 DVector<Color> cursor_colors;
2834 float cs = 0.25;
2835 cursor_points.push_back(Vector3(+cs, 0, 0));
2836 cursor_points.push_back(Vector3(-cs, 0, 0));
2837 cursor_points.push_back(Vector3(0, +cs, 0));
2838 cursor_points.push_back(Vector3(0, -cs, 0));
2839 cursor_points.push_back(Vector3(0, 0, +cs));
2840 cursor_points.push_back(Vector3(0, 0, -cs));
2841 cursor_colors.push_back(Color(1, 0.5, 0.5, 0.7));
2842 cursor_colors.push_back(Color(1, 0.5, 0.5, 0.7));
2843 cursor_colors.push_back(Color(0.5, 1, 0.5, 0.7));
2844 cursor_colors.push_back(Color(0.5, 1, 0.5, 0.7));
2845 cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7));
2846 cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7));
2847
2848 Ref<FixedMaterial> mat = memnew(FixedMaterial);
2849 mat->set_flag(Material::FLAG_UNSHADED, true);
2850 mat->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
2851 mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2852 mat->set_line_width(3);
2853 Array d;
2854 d.resize(VS::ARRAY_MAX);
2855 d[Mesh::ARRAY_VERTEX] = cursor_points;
2856 d[Mesh::ARRAY_COLOR] = cursor_colors;
2857 pos3d_mesh->add_surface(Mesh::PRIMITIVE_LINES, d);
2858 pos3d_mesh->surface_set_material(0, mat);
2859 }
2860
2861 listener_line_mesh = Ref<Mesh>(memnew(Mesh));
2862 {
2863
2864 DVector<Vector3> cursor_points;
2865 DVector<Color> cursor_colors;
2866 cursor_points.push_back(Vector3(0, 0, 0));
2867 cursor_points.push_back(Vector3(0, 0, -1.0));
2868 cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7));
2869 cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7));
2870
2871 Ref<FixedMaterial> mat = memnew(FixedMaterial);
2872 mat->set_flag(Material::FLAG_UNSHADED, true);
2873 mat->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
2874 mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2875 mat->set_line_width(3);
2876 Array d;
2877 d.resize(VS::ARRAY_MAX);
2878 d[Mesh::ARRAY_VERTEX] = cursor_points;
2879 d[Mesh::ARRAY_COLOR] = cursor_colors;
2880 listener_line_mesh->add_surface(Mesh::PRIMITIVE_LINES, d);
2881 listener_line_mesh->surface_set_material(0, mat);
2882 }
2883
2884 sample_player_icon = Ref<FixedMaterial>(memnew(FixedMaterial));
2885 sample_player_icon->set_flag(Material::FLAG_UNSHADED, true);
2886 sample_player_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2887 sample_player_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
2888 sample_player_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2889 sample_player_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1, 0.9));
2890 sample_player_icon->set_texture(FixedMaterial::PARAM_DIFFUSE, SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer", "EditorIcons"));
2891
2892 room_material = create_line_material(Color(1.0, 0.6, 0.9));
2893 portal_material = create_line_material(Color(1.0, 0.8, 0.6));
2894 raycast_material = create_line_material(Color(1.0, 0.8, 0.6));
2895 car_wheel_material = create_line_material(Color(0.6, 0.8, 1.0));
2896 visibility_notifier_material = create_line_material(Color(1.0, 0.5, 1.0));
2897 joint_material = create_line_material(Color(0.6, 0.8, 1.0));
2898
2899 stream_player_icon = Ref<FixedMaterial>(memnew(FixedMaterial));
2900 stream_player_icon->set_flag(Material::FLAG_UNSHADED, true);
2901 stream_player_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2902 stream_player_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
2903 stream_player_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2904 stream_player_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1, 0.9));
2905 stream_player_icon->set_texture(FixedMaterial::PARAM_DIFFUSE, SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer", "EditorIcons"));
2906
2907 visibility_notifier_icon = Ref<FixedMaterial>(memnew(FixedMaterial));
2908 visibility_notifier_icon->set_flag(Material::FLAG_UNSHADED, true);
2909 visibility_notifier_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2910 visibility_notifier_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
2911 visibility_notifier_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2912 visibility_notifier_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1, 0.9));
2913 visibility_notifier_icon->set_texture(FixedMaterial::PARAM_DIFFUSE, SpatialEditor::get_singleton()->get_icon("Visible", "EditorIcons"));
2914
2915 listener_icon = Ref<FixedMaterial>(memnew(FixedMaterial));
2916 listener_icon->set_flag(Material::FLAG_UNSHADED, true);
2917 listener_icon->set_flag(Material::FLAG_DOUBLE_SIDED, true);
2918 listener_icon->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
2919 listener_icon->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2920 listener_icon->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1, 0.9));
2921 listener_icon->set_texture(FixedMaterial::PARAM_DIFFUSE, SpatialEditor::get_singleton()->get_icon("GizmoListener", "EditorIcons"));
2922
2923 {
2924
2925 DVector<Vector3> vertices;
2926
2927 #undef ADD_VTX
2928 #define ADD_VTX(m_idx) \
2929 vertices.push_back(face_points[m_idx]);
2930
2931 for (int i = 0; i < 6; i++) {
2932
2933 Vector3 face_points[4];
2934
2935 for (int j = 0; j < 4; j++) {
2936
2937 float v[3];
2938 v[0] = 1.0;
2939 v[1] = 1 - 2 * ((j >> 1) & 1);
2940 v[2] = v[1] * (1 - 2 * (j & 1));
2941
2942 for (int k = 0; k < 3; k++) {
2943
2944 if (i < 3)
2945 face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
2946 else
2947 face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
2948 }
2949 }
2950 //tri 1
2951 ADD_VTX(0);
2952 ADD_VTX(1);
2953 ADD_VTX(2);
2954 //tri 2
2955 ADD_VTX(2);
2956 ADD_VTX(3);
2957 ADD_VTX(0);
2958 }
2959
2960 test_cube_tm = Ref<TriangleMesh>(memnew(TriangleMesh));
2961 test_cube_tm->create(vertices);
2962 }
2963
2964 shape_material = create_line_material(Color(0.2, 1, 1.0));
2965 }
2966