1 /*************************************************************************/
2 /* spatial_editor_plugin.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_plugin.h"
31 #include "print_string.h"
32
33 #include "camera_matrix.h"
34 #include "core/os/input.h"
35 #include "editor/animation_editor.h"
36 #include "editor/editor_node.h"
37 #include "editor/editor_settings.h"
38 #include "editor/plugins/animation_player_editor_plugin.h"
39 #include "editor/spatial_editor_gizmos.h"
40 #include "globals.h"
41 #include "os/keyboard.h"
42 #include "scene/3d/camera.h"
43 #include "scene/3d/visual_instance.h"
44 #include "scene/resources/surface_tool.h"
45 #include "sort.h"
46
47 #define DISTANCE_DEFAULT 4
48
49 #define GIZMO_ARROW_SIZE 0.3
50 #define GIZMO_RING_HALF_WIDTH 0.1
51 //#define GIZMO_SCALE_DEFAULT 0.28
52 #define GIZMO_SCALE_DEFAULT 0.15
53
_update_camera()54 void SpatialEditorViewport::_update_camera() {
55 if (orthogonal) {
56 //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar());
57 camera->set_orthogonal(2 * cursor.distance, 0.1, 8192);
58 } else
59 camera->set_perspective(get_fov(), get_znear(), get_zfar());
60
61 Transform camera_transform;
62 camera_transform.translate(cursor.pos);
63 camera_transform.basis.rotate(Vector3(0, 1, 0), cursor.y_rot);
64 camera_transform.basis.rotate(Vector3(1, 0, 0), cursor.x_rot);
65
66 if (orthogonal)
67 camera_transform.translate(0, 0, 4096);
68 else
69 camera_transform.translate(0, 0, cursor.distance);
70
71 if (camera->get_global_transform() != camera_transform) {
72 camera->set_global_transform(camera_transform);
73 update_transform_gizmo_view();
74 }
75 }
76
get_handle_name(int p_idx) const77 String SpatialEditorGizmo::get_handle_name(int p_idx) const {
78
79 if (get_script_instance() && get_script_instance()->has_method("get_handle_name"))
80 return get_script_instance()->call("get_handle_name", p_idx);
81
82 return "";
83 }
84
get_handle_value(int p_idx) const85 Variant SpatialEditorGizmo::get_handle_value(int p_idx) const {
86
87 if (get_script_instance() && get_script_instance()->has_method("get_handle_value"))
88 return get_script_instance()->call("get_handle_value", p_idx);
89
90 return Variant();
91 }
92
set_handle(int p_idx,Camera * p_camera,const Point2 & p_point)93 void SpatialEditorGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) {
94
95 if (get_script_instance() && get_script_instance()->has_method("set_handle"))
96 get_script_instance()->call("set_handle", p_idx, p_camera, p_point);
97 }
98
commit_handle(int p_idx,const Variant & p_restore,bool p_cancel)99 void SpatialEditorGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
100
101 if (get_script_instance() && get_script_instance()->has_method("commit_handle"))
102 get_script_instance()->call("commit_handle", p_idx, p_restore, p_cancel);
103 }
104
intersect_frustum(const Camera * p_camera,const Vector<Plane> & p_frustum)105 bool SpatialEditorGizmo::intersect_frustum(const Camera *p_camera, const Vector<Plane> &p_frustum) {
106
107 return false;
108 }
109
intersect_ray(const Camera * p_camera,const Point2 & p_point,Vector3 & r_pos,Vector3 & r_normal,int * r_gizmo_handle,bool p_sec_first)110 bool SpatialEditorGizmo::intersect_ray(const Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle, bool p_sec_first) {
111
112 return false;
113 }
114
SpatialEditorGizmo()115 SpatialEditorGizmo::SpatialEditorGizmo() {
116
117 selected = false;
118 }
119
get_selected_count() const120 int SpatialEditorViewport::get_selected_count() const {
121
122 Map<Node *, Object *> &selection = editor_selection->get_selection();
123
124 int count = 0;
125
126 for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
127
128 Spatial *sp = E->key()->cast_to<Spatial>();
129 if (!sp)
130 continue;
131
132 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
133 if (!se)
134 continue;
135
136 count++;
137 }
138
139 return count;
140 }
141
get_znear() const142 float SpatialEditorViewport::get_znear() const {
143
144 float val = spatial_editor->get_znear();
145 if (val < 0.001)
146 val = 0.001;
147 return val;
148 }
get_zfar() const149 float SpatialEditorViewport::get_zfar() const {
150
151 float val = spatial_editor->get_zfar();
152 if (val < 0.001)
153 val = 0.001;
154 return val;
155 }
get_fov() const156 float SpatialEditorViewport::get_fov() const {
157
158 float val = spatial_editor->get_fov();
159 if (val < 0.001)
160 val = 0.001;
161 if (val > 89)
162 val = 89;
163 return val;
164 }
165
_get_camera_transform() const166 Transform SpatialEditorViewport::_get_camera_transform() const {
167
168 return camera->get_global_transform();
169 }
170
_get_camera_pos() const171 Vector3 SpatialEditorViewport::_get_camera_pos() const {
172
173 return _get_camera_transform().origin;
174 }
175
_point_to_screen(const Vector3 & p_point)176 Point2 SpatialEditorViewport::_point_to_screen(const Vector3 &p_point) {
177
178 return camera->unproject_position(p_point);
179 }
180
_get_ray_pos(const Vector2 & p_pos) const181 Vector3 SpatialEditorViewport::_get_ray_pos(const Vector2 &p_pos) const {
182
183 return camera->project_ray_origin(p_pos);
184 }
185
_get_camera_normal() const186 Vector3 SpatialEditorViewport::_get_camera_normal() const {
187
188 return -_get_camera_transform().basis.get_axis(2);
189 }
190
_get_ray(const Vector2 & p_pos)191 Vector3 SpatialEditorViewport::_get_ray(const Vector2 &p_pos) {
192
193 return camera->project_ray_normal(p_pos);
194 }
195 /*
196 void SpatialEditorViewport::_clear_id(Spatial *p_node) {
197
198
199 editor_selection->remove_node(p_node);
200
201
202 }
203 */
_clear_selected()204 void SpatialEditorViewport::_clear_selected() {
205
206 editor_selection->clear();
207 }
208
_select_clicked(bool p_append,bool p_single)209 void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single) {
210
211 if (!clicked)
212 return;
213
214 Object *obj = ObjectDB::get_instance(clicked);
215 if (!obj)
216 return;
217
218 Spatial *sp = obj->cast_to<Spatial>();
219 if (!sp)
220 return;
221
222 _select(sp, clicked_wants_append, true);
223 }
224
_select(Spatial * p_node,bool p_append,bool p_single)225 void SpatialEditorViewport::_select(Spatial *p_node, bool p_append, bool p_single) {
226
227 if (!p_append) {
228
229 // should not modify the selection..
230
231 editor_selection->clear();
232 editor_selection->add_node(p_node);
233
234 } else {
235
236 if (editor_selection->is_selected(p_node) && p_single) {
237 //erase
238 editor_selection->remove_node(p_node);
239 } else {
240
241 editor_selection->add_node(p_node);
242 }
243 }
244 }
245
_select_ray(const Point2 & p_pos,bool p_append,bool & r_includes_current,int * r_gizmo_handle,bool p_alt_select)246 ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle, bool p_alt_select) {
247
248 if (r_gizmo_handle)
249 *r_gizmo_handle = -1;
250
251 Vector3 ray = _get_ray(p_pos);
252 Vector3 pos = _get_ray_pos(p_pos);
253
254 Vector<RID> instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario());
255 Set<Ref<SpatialEditorGizmo> > found_gizmos;
256
257 //uint32_t closest=0;
258 // float closest_dist=0;
259
260 r_includes_current = false;
261
262 List<_RayResult> results;
263 Vector<Spatial *> subscenes = Vector<Spatial *>();
264 Vector<Vector3> subscenes_positions = Vector<Vector3>();
265
266 for (int i = 0; i < instances.size(); i++) {
267
268 uint32_t id = VisualServer::get_singleton()->instance_get_object_instance_ID(instances[i]);
269 Object *obj = ObjectDB::get_instance(id);
270 if (!obj)
271 continue;
272
273 Spatial *spat = obj->cast_to<Spatial>();
274
275 if (!spat)
276 continue;
277
278 Ref<SpatialEditorGizmo> seg = spat->get_gizmo();
279
280 if (!seg.is_valid() || found_gizmos.has(seg)) {
281 Node *subscene_candidate = spat;
282 Vector3 source_click_spatial_pos = spat->get_global_transform().origin;
283
284 while ((subscene_candidate->get_owner() != NULL) && (subscene_candidate->get_owner() != editor->get_edited_scene()))
285 subscene_candidate = subscene_candidate->get_owner();
286
287 spat = subscene_candidate->cast_to<Spatial>();
288 if (spat && (spat->get_filename() != "") && (subscene_candidate->get_owner() != NULL)) {
289 subscenes.push_back(spat);
290 subscenes_positions.push_back(source_click_spatial_pos);
291 }
292
293 continue;
294 }
295
296 found_gizmos.insert(seg);
297 Vector3 point;
298 Vector3 normal;
299
300 int handle = -1;
301 bool inters = seg->intersect_ray(camera, p_pos, point, normal, NULL, p_alt_select);
302
303 if (!inters)
304 continue;
305
306 float dist = pos.distance_to(point);
307
308 if (dist < 0)
309 continue;
310
311 if (editor_selection->is_selected(spat))
312 r_includes_current = true;
313
314 _RayResult res;
315 res.item = spat;
316 res.depth = dist;
317 res.handle = handle;
318 results.push_back(res);
319 }
320 for (int idx_subscene = 0; idx_subscene < subscenes.size(); idx_subscene++) {
321
322 Spatial *subscene = subscenes.get(idx_subscene);
323 float dist = ray.cross(subscenes_positions.get(idx_subscene) - pos).length();
324
325 if ((dist < 0) || (dist > 1.2))
326 continue;
327
328 if (editor_selection->is_selected(subscene))
329 r_includes_current = true;
330
331 _RayResult res;
332 res.item = subscene;
333 res.depth = dist;
334 res.handle = -1;
335 results.push_back(res);
336 }
337
338 if (results.empty())
339 return 0;
340
341 results.sort();
342 Spatial *s = NULL;
343
344 if (!r_includes_current || results.size() == 1 || (r_gizmo_handle && results.front()->get().handle >= 0)) {
345
346 //return the nearest one
347 s = results.front()->get().item;
348 if (r_gizmo_handle)
349 *r_gizmo_handle = results.front()->get().handle;
350
351 } else {
352
353 //returns the next one from a curent selection
354 List<_RayResult>::Element *E = results.front();
355 List<_RayResult>::Element *S = NULL;
356
357 while (true) {
358
359 //very strange loop algorithm that complies with object selection standards (tm).
360
361 if (S == E) {
362 //went all around and anothing was found
363 //since can't rotate the selection
364 //just return the first one
365
366 s = results.front()->get().item;
367 break;
368 }
369
370 if (!S && editor_selection->is_selected(E->get().item)) {
371 //found an item currently in the selection,
372 //so start from this one
373 S = E;
374 }
375
376 if (S && !editor_selection->is_selected(E->get().item)) {
377 // free item after a selected item, this one is desired.
378 s = E->get().item;
379 break;
380 }
381
382 E = E->next();
383 if (!E) {
384
385 if (!S) {
386 //did a loop but nothing was selected, select first
387 s = results.front()->get().item;
388 break;
389 }
390 E = results.front();
391 }
392 }
393 }
394
395 if (!s)
396 return 0;
397
398 return s->get_instance_ID();
399 }
400
_find_items_at_pos(const Point2 & p_pos,bool & r_includes_current,Vector<_RayResult> & results,bool p_alt_select)401 void SpatialEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select) {
402
403 Vector3 ray = _get_ray(p_pos);
404 Vector3 pos = _get_ray_pos(p_pos);
405
406 Vector<RID> instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario());
407 Set<Ref<SpatialEditorGizmo> > found_gizmos;
408
409 r_includes_current = false;
410
411 for (int i = 0; i < instances.size(); i++) {
412
413 uint32_t id = VisualServer::get_singleton()->instance_get_object_instance_ID(instances[i]);
414 Object *obj = ObjectDB::get_instance(id);
415 if (!obj)
416 continue;
417
418 Spatial *spat = obj->cast_to<Spatial>();
419
420 if (!spat)
421 continue;
422
423 Ref<SpatialEditorGizmo> seg = spat->get_gizmo();
424
425 if (!seg.is_valid())
426 continue;
427
428 if (found_gizmos.has(seg))
429 continue;
430
431 found_gizmos.insert(seg);
432 Vector3 point;
433 Vector3 normal;
434
435 int handle = -1;
436 bool inters = seg->intersect_ray(camera, p_pos, point, normal, NULL, p_alt_select);
437
438 if (!inters)
439 continue;
440
441 float dist = pos.distance_to(point);
442
443 if (dist < 0)
444 continue;
445
446 if (editor_selection->is_selected(spat))
447 r_includes_current = true;
448
449 _RayResult res;
450 res.item = spat;
451 res.depth = dist;
452 res.handle = handle;
453 results.push_back(res);
454 }
455
456 if (results.empty())
457 return;
458
459 results.sort();
460 }
461
_get_screen_to_space(const Vector3 & p_pos)462 Vector3 SpatialEditorViewport::_get_screen_to_space(const Vector3 &p_pos) {
463
464 CameraMatrix cm;
465 cm.set_perspective(get_fov(), get_size().get_aspect(), get_znear(), get_zfar());
466 float screen_w, screen_h;
467 cm.get_viewport_size(screen_w, screen_h);
468
469 Transform camera_transform;
470 camera_transform.translate(cursor.pos);
471 camera_transform.basis.rotate(Vector3(0, 1, 0), cursor.y_rot);
472 camera_transform.basis.rotate(Vector3(1, 0, 0), cursor.x_rot);
473 camera_transform.translate(0, 0, cursor.distance);
474
475 return camera_transform.xform(Vector3(((p_pos.x / get_size().width) * 2.0 - 1.0) * screen_w, ((1.0 - (p_pos.y / get_size().height)) * 2.0 - 1.0) * screen_h, -get_znear()));
476 }
477
_select_region()478 void SpatialEditorViewport::_select_region() {
479
480 if (cursor.region_begin == cursor.region_end)
481 return; //nothing really
482
483 Vector3 box[4] = {
484 Vector3(
485 MIN(cursor.region_begin.x, cursor.region_end.x),
486 MIN(cursor.region_begin.y, cursor.region_end.y),
487 0),
488 Vector3(
489 MAX(cursor.region_begin.x, cursor.region_end.x),
490 MIN(cursor.region_begin.y, cursor.region_end.y),
491 0),
492 Vector3(
493 MAX(cursor.region_begin.x, cursor.region_end.x),
494 MAX(cursor.region_begin.y, cursor.region_end.y),
495 0),
496 Vector3(
497 MIN(cursor.region_begin.x, cursor.region_end.x),
498 MAX(cursor.region_begin.y, cursor.region_end.y),
499 0)
500 };
501
502 Vector<Plane> frustum;
503
504 Vector3 cam_pos = _get_camera_pos();
505 Set<Ref<SpatialEditorGizmo> > found_gizmos;
506
507 for (int i = 0; i < 4; i++) {
508
509 Vector3 a = _get_screen_to_space(box[i]);
510 Vector3 b = _get_screen_to_space(box[(i + 1) % 4]);
511 frustum.push_back(Plane(a, b, cam_pos));
512 }
513
514 Plane near(cam_pos, -_get_camera_normal());
515 near.d -= get_znear();
516
517 frustum.push_back(near);
518
519 Plane far = -near;
520 far.d += 500.0;
521
522 frustum.push_back(far);
523
524 Vector<RID> instances = VisualServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world()->get_scenario());
525
526 for (int i = 0; i < instances.size(); i++) {
527
528 uint32_t id = VisualServer::get_singleton()->instance_get_object_instance_ID(instances[i]);
529
530 Object *obj = ObjectDB::get_instance(id);
531 if (!obj)
532 continue;
533 Spatial *sp = obj->cast_to<Spatial>();
534 if (!sp)
535 continue;
536
537 Ref<SpatialEditorGizmo> seg = sp->get_gizmo();
538
539 if (!seg.is_valid())
540 continue;
541
542 if (found_gizmos.has(seg))
543 continue;
544
545 if (seg->intersect_frustum(camera, frustum))
546 _select(sp, true, false);
547 }
548 }
549
_update_name()550 void SpatialEditorViewport::_update_name() {
551
552 String ortho = orthogonal ? TTR("Orthogonal") : TTR("Perspective");
553
554 if (name != "")
555 view_menu->set_text("[ " + name + " " + ortho + " ]");
556 else
557 view_menu->set_text("[ " + ortho + " ]");
558 }
559
_compute_edit(const Point2 & p_point)560 void SpatialEditorViewport::_compute_edit(const Point2 &p_point) {
561
562 _edit.click_ray = _get_ray(Vector2(p_point.x, p_point.y));
563 _edit.click_ray_pos = _get_ray_pos(Vector2(p_point.x, p_point.y));
564 _edit.plane = TRANSFORM_VIEW;
565 spatial_editor->update_transform_gizmo();
566 _edit.center = spatial_editor->get_gizmo_transform().origin;
567
568 List<Node *> &selection = editor_selection->get_selected_node_list();
569
570 // Vector3 center;
571 // int nc=0;
572 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
573
574 Spatial *sp = E->get()->cast_to<Spatial>();
575 if (!sp)
576 continue;
577
578 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
579 if (!se)
580 continue;
581
582 se->original = se->sp->get_global_transform();
583 // center+=se->original.origin;
584 // nc++;
585 }
586
587 // if (nc)
588 // _edit.center=center/float(nc);
589 }
590
_get_key_modifier(const String & p_property)591 static int _get_key_modifier(const String &p_property) {
592
593 switch (EditorSettings::get_singleton()->get(p_property).operator int()) {
594
595 case 0: return 0;
596 case 1: return KEY_SHIFT;
597 case 2: return KEY_ALT;
598 case 3: return KEY_META;
599 case 4: return KEY_CONTROL;
600 }
601 return 0;
602 }
603
_get_navigation_schema(const String & p_property)604 SpatialEditorViewport::NavigationScheme SpatialEditorViewport::_get_navigation_schema(const String &p_property) {
605 switch (EditorSettings::get_singleton()->get(p_property).operator int()) {
606 case 0: return NAVIGATION_GODOT;
607 case 1: return NAVIGATION_MAYA;
608 case 2: return NAVIGATION_MODO;
609 }
610 return NAVIGATION_GODOT;
611 }
612
_get_navigation_zoom_style(const String & p_property)613 SpatialEditorViewport::NavigationZoomStyle SpatialEditorViewport::_get_navigation_zoom_style(const String &p_property) {
614 switch (EditorSettings::get_singleton()->get(p_property).operator int()) {
615 case 0: return NAVIGATION_ZOOM_VERTICAL;
616 case 1: return NAVIGATION_ZOOM_HORIZONTAL;
617 }
618 return NAVIGATION_ZOOM_VERTICAL;
619 }
620
_gizmo_select(const Vector2 & p_screenpos,bool p_hilite_only)621 bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hilite_only) {
622
623 if (!spatial_editor->is_gizmo_visible())
624 return false;
625 if (get_selected_count() == 0) {
626 if (p_hilite_only)
627 spatial_editor->select_gizmo_highlight_axis(-1);
628 return false;
629 }
630
631 Vector3 ray_pos = _get_ray_pos(Vector2(p_screenpos.x, p_screenpos.y));
632 Vector3 ray = _get_ray(Vector2(p_screenpos.x, p_screenpos.y));
633
634 Transform gt = spatial_editor->get_gizmo_transform();
635 float gs = gizmo_scale;
636
637 if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE) {
638
639 int col_axis = -1;
640 float col_d = 1e20;
641
642 for (int i = 0; i < 3; i++) {
643
644 Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs;
645 float grabber_radius = gs * GIZMO_ARROW_SIZE;
646
647 Vector3 r;
648 if (Geometry::segment_intersects_sphere(ray_pos, ray_pos + ray * 10000.0, grabber_pos, grabber_radius, &r)) {
649 float d = r.distance_to(ray_pos);
650 if (d < col_d) {
651 col_d = d;
652 col_axis = i;
653 }
654 }
655 }
656
657 if (col_axis != -1) {
658
659 if (p_hilite_only) {
660
661 spatial_editor->select_gizmo_highlight_axis(col_axis);
662
663 } else {
664 //handle rotate
665 _edit.mode = TRANSFORM_TRANSLATE;
666 _compute_edit(Point2(p_screenpos.x, p_screenpos.y));
667 _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis);
668 }
669 return true;
670 }
671 }
672
673 if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE) {
674
675 int col_axis = -1;
676 float col_d = 1e20;
677
678 for (int i = 0; i < 3; i++) {
679
680 Plane plane(gt.origin, gt.basis.get_axis(i).normalized());
681 Vector3 r;
682 if (!plane.intersects_ray(ray_pos, ray, &r))
683 continue;
684
685 float dist = r.distance_to(gt.origin);
686
687 if (dist > gs * (1 - GIZMO_RING_HALF_WIDTH) && dist < gs * (1 + GIZMO_RING_HALF_WIDTH)) {
688
689 float d = ray_pos.distance_to(r);
690 if (d < col_d) {
691 col_d = d;
692 col_axis = i;
693 }
694 }
695 }
696
697 if (col_axis != -1) {
698
699 if (p_hilite_only) {
700
701 spatial_editor->select_gizmo_highlight_axis(col_axis + 3);
702 } else {
703 //handle rotate
704 _edit.mode = TRANSFORM_ROTATE;
705 _compute_edit(Point2(p_screenpos.x, p_screenpos.y));
706 _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis);
707 }
708 return true;
709 }
710 }
711
712 if (p_hilite_only)
713 spatial_editor->select_gizmo_highlight_axis(-1);
714
715 return false;
716 }
717
_smouseenter()718 void SpatialEditorViewport::_smouseenter() {
719
720 if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
721 surface->grab_focus();
722 }
723
_list_select(InputEventMouseButton b)724 void SpatialEditorViewport::_list_select(InputEventMouseButton b) {
725
726 _find_items_at_pos(Vector2(b.x, b.y), clicked_includes_current, selection_results, b.mod.shift);
727
728 Node *scene = editor->get_edited_scene();
729
730 for (int i = 0; i < selection_results.size(); i++) {
731 Spatial *item = selection_results[i].item;
732 if (item != scene && item->get_owner() != scene && !scene->is_editable_instance(item->get_owner())) {
733 //invalid result
734 selection_results.remove(i);
735 i--;
736 }
737 }
738
739 clicked_wants_append = b.mod.shift;
740
741 if (selection_results.size() == 1) {
742
743 clicked = selection_results[0].item->get_instance_ID();
744 selection_results.clear();
745
746 if (clicked) {
747 _select_clicked(clicked_wants_append, true);
748 clicked = 0;
749 }
750
751 } else if (!selection_results.empty()) {
752
753 NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
754 StringName root_name = root_path.get_name(root_path.get_name_count() - 1);
755
756 for (int i = 0; i < selection_results.size(); i++) {
757
758 Spatial *spat = selection_results[i].item;
759
760 Ref<Texture> icon;
761 if (spat->has_meta("_editor_icon"))
762 icon = spat->get_meta("_editor_icon");
763 else
764 icon = get_icon(has_icon(spat->get_type(), "EditorIcons") ? spat->get_type() : String("Object"), "EditorIcons");
765
766 String node_path = "/" + root_name + "/" + root_path.rel_path_to(spat->get_path());
767
768 selection_menu->add_item(spat->get_name());
769 selection_menu->set_item_icon(i, icon);
770 selection_menu->set_item_metadata(i, node_path);
771 selection_menu->set_item_tooltip(i, String(spat->get_name()) + "\nType: " + spat->get_type() + "\nPath: " + node_path);
772 }
773
774 selection_menu->set_global_pos(Vector2(b.global_x, b.global_y));
775 selection_menu->popup();
776 selection_menu->call_deferred("grab_click_focus");
777 selection_menu->set_invalidate_click_until_motion();
778 }
779 }
_sinput(const InputEvent & p_event)780 void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
781
782 if (previewing)
783 return; //do NONE
784
785 {
786
787 EditorNode *en = editor;
788 EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
789
790 if (!over_plugin_list->empty()) {
791 bool discard = over_plugin_list->forward_spatial_input_event(camera, p_event);
792 if (discard)
793 return;
794 }
795 }
796
797 switch (p_event.type) {
798 case InputEvent::MOUSE_BUTTON: {
799
800 const InputEventMouseButton &b = p_event.mouse_button;
801
802 switch (b.button_index) {
803
804 case BUTTON_WHEEL_UP: {
805
806 cursor.distance /= 1.08;
807 if (cursor.distance < 0.001)
808 cursor.distance = 0.001;
809
810 } break;
811 case BUTTON_WHEEL_DOWN: {
812
813 if (cursor.distance < 0.001)
814 cursor.distance = 0.001;
815 cursor.distance *= 1.08;
816
817 } break;
818 case BUTTON_RIGHT: {
819
820 NavigationScheme nav_scheme = _get_navigation_schema("3d_editor/navigation_scheme");
821
822 if (b.pressed && _edit.gizmo.is_valid()) {
823 //restore
824 _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_initial_value, true);
825 _edit.gizmo = Ref<SpatialEditorGizmo>();
826 }
827
828 if (_edit.mode == TRANSFORM_NONE && b.pressed) {
829
830 Plane cursor_plane(cursor.cursor_pos, _get_camera_normal());
831
832 Vector3 ray_origin = _get_ray_pos(Vector2(b.x, b.y));
833 Vector3 ray_dir = _get_ray(Vector2(b.x, b.y));
834
835 //gizmo modify
836
837 if (b.mod.control) {
838
839 Vector<RID> instances = VisualServer::get_singleton()->instances_cull_ray(ray_origin, ray_dir, get_tree()->get_root()->get_world()->get_scenario());
840
841 Plane p(ray_origin, _get_camera_normal());
842
843 float min_d = 1e10;
844 bool found = false;
845
846 for (int i = 0; i < instances.size(); i++) {
847
848 uint32_t id = VisualServer::get_singleton()->instance_get_object_instance_ID(instances[i]);
849 Object *obj = ObjectDB::get_instance(id);
850 if (!obj)
851 continue;
852
853 VisualInstance *vi = obj->cast_to<VisualInstance>();
854 if (!vi)
855 continue;
856
857 //optimize by checking AABB (although should pre sort by distance)
858 AABB aabb = vi->get_global_transform().xform(vi->get_aabb());
859 if (p.distance_to(aabb.get_support(-ray_dir)) > min_d)
860 continue;
861
862 DVector<Face3> faces = vi->get_faces(VisualInstance::FACES_SOLID);
863 int c = faces.size();
864 if (c > 0) {
865 DVector<Face3>::Read r = faces.read();
866
867 for (int j = 0; j < c; j++) {
868
869 Vector3 inters;
870 if (r[j].intersects_ray(ray_origin, ray_dir, &inters)) {
871
872 float d = p.distance_to(inters);
873 if (d < 0)
874 continue;
875
876 if (d < min_d) {
877 min_d = d;
878 found = true;
879 }
880 }
881 }
882 }
883 }
884
885 if (found) {
886
887 //cursor.cursor_pos=ray_origin+ray_dir*min_d;
888 //VisualServer::get_singleton()->instance_set_transform(cursor_instance,Transform(Matrix3(),cursor.cursor_pos));
889 }
890
891 } else {
892 Vector3 new_pos;
893 if (cursor_plane.intersects_ray(ray_origin, ray_dir, &new_pos)) {
894
895 //cursor.cursor_pos=new_pos;
896 //VisualServer::get_singleton()->instance_set_transform(cursor_instance,Transform(Matrix3(),cursor.cursor_pos));
897 }
898 }
899
900 if (b.mod.alt) {
901
902 if (nav_scheme == NAVIGATION_MAYA)
903 break;
904
905 _list_select(b);
906 return;
907 }
908 }
909
910 if (_edit.mode != TRANSFORM_NONE && b.pressed) {
911 //cancel motion
912 _edit.mode = TRANSFORM_NONE;
913 //_validate_selection();
914
915 List<Node *> &selection = editor_selection->get_selected_node_list();
916
917 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
918
919 Spatial *sp = E->get()->cast_to<Spatial>();
920 if (!sp)
921 continue;
922
923 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
924 if (!se)
925 continue;
926
927 sp->set_global_transform(se->original);
928 }
929 surface->update();
930 //VisualServer::get_singleton()->poly_clear(indicators);
931 set_message(TTR("Transform Aborted."), 3);
932 }
933 } break;
934 case BUTTON_MIDDLE: {
935
936 if (b.pressed && _edit.mode != TRANSFORM_NONE) {
937
938 switch (_edit.plane) {
939
940 case TRANSFORM_VIEW: {
941
942 _edit.plane = TRANSFORM_X_AXIS;
943 set_message(TTR("X-Axis Transform."), 2);
944 name = "";
945 _update_name();
946 } break;
947 case TRANSFORM_X_AXIS: {
948
949 _edit.plane = TRANSFORM_Y_AXIS;
950 set_message(TTR("Y-Axis Transform."), 2);
951
952 } break;
953 case TRANSFORM_Y_AXIS: {
954
955 _edit.plane = TRANSFORM_Z_AXIS;
956 set_message(TTR("Z-Axis Transform."), 2);
957
958 } break;
959 case TRANSFORM_Z_AXIS: {
960
961 _edit.plane = TRANSFORM_VIEW;
962 set_message(TTR("View Plane Transform."), 2);
963
964 } break;
965 }
966 }
967 } break;
968 case BUTTON_LEFT: {
969
970 if (b.pressed) {
971
972 NavigationScheme nav_scheme = _get_navigation_schema("3d_editor/navigation_scheme");
973 if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b.mod.alt) {
974 break;
975 }
976
977 if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_LIST_SELECT) {
978 _list_select(b);
979 break;
980 }
981
982 _edit.mouse_pos = Point2(b.x, b.y);
983 _edit.snap = false;
984 _edit.mode = TRANSFORM_NONE;
985
986 //gizmo has priority over everything
987
988 bool can_select_gizmos = true;
989
990 {
991 int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
992 can_select_gizmos = view_menu->get_popup()->is_item_checked(idx);
993 }
994
995 if (can_select_gizmos && spatial_editor->get_selected()) {
996
997 Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo();
998 if (seg.is_valid()) {
999 int handle = -1;
1000 Vector3 point;
1001 Vector3 normal;
1002 bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, b.mod.shift);
1003 if (inters && handle != -1) {
1004
1005 _edit.gizmo = seg;
1006 _edit.gizmo_handle = handle;
1007 //_edit.gizmo_initial_pos=seg->get_handle_pos(gizmo_handle);
1008 _edit.gizmo_initial_value = seg->get_handle_value(handle);
1009 break;
1010 }
1011 }
1012 }
1013
1014 if (_gizmo_select(_edit.mouse_pos))
1015 break;
1016
1017 clicked = 0;
1018 clicked_includes_current = false;
1019
1020 if ((spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT && b.mod.control) || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE) {
1021
1022 /* HANDLE ROTATION */
1023 if (get_selected_count() == 0)
1024 break; //bye
1025 //handle rotate
1026 _edit.mode = TRANSFORM_ROTATE;
1027 _compute_edit(Point2(b.x, b.y));
1028 break;
1029 }
1030
1031 if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE) {
1032
1033 if (get_selected_count() == 0)
1034 break; //bye
1035 //handle rotate
1036 _edit.mode = TRANSFORM_TRANSLATE;
1037 _compute_edit(Point2(b.x, b.y));
1038 break;
1039 }
1040
1041 if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE) {
1042
1043 if (get_selected_count() == 0)
1044 break; //bye
1045 //handle rotate
1046 _edit.mode = TRANSFORM_SCALE;
1047 _compute_edit(Point2(b.x, b.y));
1048 break;
1049 }
1050
1051 // todo scale
1052
1053 int gizmo_handle = -1;
1054
1055 clicked = _select_ray(Vector2(b.x, b.y), b.mod.shift, clicked_includes_current, &gizmo_handle, b.mod.shift);
1056
1057 //clicking is always deferred to either move or release
1058
1059 clicked_wants_append = b.mod.shift;
1060
1061 if (!clicked) {
1062
1063 if (!clicked_wants_append)
1064 _clear_selected();
1065
1066 //default to regionselect
1067 cursor.region_select = true;
1068 cursor.region_begin = Point2(b.x, b.y);
1069 cursor.region_end = Point2(b.x, b.y);
1070 }
1071
1072 if (clicked && gizmo_handle >= 0) {
1073
1074 Object *obj = ObjectDB::get_instance(clicked);
1075 if (obj) {
1076
1077 Spatial *spa = obj->cast_to<Spatial>();
1078 if (spa) {
1079
1080 Ref<SpatialEditorGizmo> seg = spa->get_gizmo();
1081 if (seg.is_valid()) {
1082
1083 _edit.gizmo = seg;
1084 _edit.gizmo_handle = gizmo_handle;
1085 //_edit.gizmo_initial_pos=seg->get_handle_pos(gizmo_handle);
1086 _edit.gizmo_initial_value = seg->get_handle_value(gizmo_handle);
1087 //print_line("GIZMO: "+itos(gizmo_handle)+" FROMPOS: "+_edit.orig_gizmo_pos);
1088 break;
1089 }
1090 }
1091 }
1092 //_compute_edit(Point2(b.x,b.y)); //in case a motion happens..
1093 }
1094
1095 surface->update();
1096 } else {
1097
1098 if (_edit.gizmo.is_valid()) {
1099
1100 _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_initial_value, false);
1101 _edit.gizmo = Ref<SpatialEditorGizmo>();
1102 break;
1103 }
1104 if (clicked) {
1105 _select_clicked(clicked_wants_append, true);
1106 //clickd processing was deferred
1107 clicked = 0;
1108 }
1109
1110 if (cursor.region_select) {
1111 _select_region();
1112 cursor.region_select = false;
1113 surface->update();
1114 }
1115
1116 if (_edit.mode != TRANSFORM_NONE) {
1117
1118 static const char *_transform_name[4] = { "None", "Rotate", "Translate", "Scale" };
1119 undo_redo->create_action(_transform_name[_edit.mode]);
1120
1121 List<Node *> &selection = editor_selection->get_selected_node_list();
1122
1123 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
1124
1125 Spatial *sp = E->get()->cast_to<Spatial>();
1126 if (!sp)
1127 continue;
1128
1129 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
1130 if (!se)
1131 continue;
1132
1133 undo_redo->add_do_method(sp, "set_global_transform", sp->get_global_transform());
1134 undo_redo->add_undo_method(sp, "set_global_transform", se->original);
1135 }
1136 undo_redo->commit_action();
1137 _edit.mode = TRANSFORM_NONE;
1138 //VisualServer::get_singleton()->poly_clear(indicators);
1139 set_message("");
1140 }
1141
1142 surface->update();
1143 }
1144 } break;
1145 }
1146 } break;
1147 case InputEvent::MOUSE_MOTION: {
1148 const InputEventMouseMotion &m = p_event.mouse_motion;
1149 _edit.mouse_pos = Point2(p_event.mouse_motion.x, p_event.mouse_motion.y);
1150
1151 if (spatial_editor->get_selected()) {
1152
1153 Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo();
1154 if (seg.is_valid()) {
1155
1156 int selected_handle = -1;
1157
1158 int handle = -1;
1159 Vector3 point;
1160 Vector3 normal;
1161 bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, false);
1162 if (inters && handle != -1) {
1163
1164 selected_handle = handle;
1165 }
1166
1167 if (selected_handle != spatial_editor->get_over_gizmo_handle()) {
1168 spatial_editor->set_over_gizmo_handle(selected_handle);
1169 spatial_editor->get_selected()->update_gizmo();
1170 if (selected_handle != -1)
1171 spatial_editor->select_gizmo_highlight_axis(-1);
1172 }
1173 }
1174 }
1175
1176 if (spatial_editor->get_over_gizmo_handle() == -1 && !(m.button_mask & 1) && !_edit.gizmo.is_valid()) {
1177
1178 _gizmo_select(_edit.mouse_pos, true);
1179 }
1180
1181 NavigationScheme nav_scheme = _get_navigation_schema("3d_editor/navigation_scheme");
1182 NavigationMode nav_mode = NAVIGATION_NONE;
1183
1184 if (_edit.gizmo.is_valid()) {
1185
1186 _edit.gizmo->set_handle(_edit.gizmo_handle, camera, Vector2(m.x, m.y));
1187 Variant v = _edit.gizmo->get_handle_value(_edit.gizmo_handle);
1188 String n = _edit.gizmo->get_handle_name(_edit.gizmo_handle);
1189 set_message(n + ": " + String(v));
1190
1191 } else if (m.button_mask & 1) {
1192
1193 if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
1194 nav_mode = NAVIGATION_ORBIT;
1195 } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt && m.mod.shift) {
1196 nav_mode = NAVIGATION_PAN;
1197 } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt && m.mod.control) {
1198 nav_mode = NAVIGATION_ZOOM;
1199 } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt) {
1200 nav_mode = NAVIGATION_ORBIT;
1201 } else {
1202 if (clicked) {
1203
1204 if (!clicked_includes_current) {
1205
1206 _select_clicked(clicked_wants_append, true);
1207 //clickd processing was deferred
1208 }
1209
1210 _compute_edit(_edit.mouse_pos);
1211 clicked = 0;
1212
1213 _edit.mode = TRANSFORM_TRANSLATE;
1214 }
1215
1216 if (cursor.region_select && nav_mode == NAVIGATION_NONE) {
1217
1218 cursor.region_end = Point2(m.x, m.y);
1219 surface->update();
1220 return;
1221 }
1222
1223 if (_edit.mode == TRANSFORM_NONE && nav_mode == NAVIGATION_NONE)
1224 break;
1225
1226 Vector3 ray_pos = _get_ray_pos(Vector2(m.x, m.y));
1227 Vector3 ray = _get_ray(Vector2(m.x, m.y));
1228
1229 switch (_edit.mode) {
1230
1231 case TRANSFORM_SCALE: {
1232
1233 Plane plane = Plane(_edit.center, _get_camera_normal());
1234
1235 Vector3 intersection;
1236 if (!plane.intersects_ray(ray_pos, ray, &intersection))
1237 break;
1238
1239 Vector3 click;
1240 if (!plane.intersects_ray(_edit.click_ray_pos, _edit.click_ray, &click))
1241 break;
1242
1243 float center_click_dist = click.distance_to(_edit.center);
1244 float center_inters_dist = intersection.distance_to(_edit.center);
1245 if (center_click_dist == 0)
1246 break;
1247
1248 float scale = (center_inters_dist / center_click_dist) * 100.0;
1249
1250 if (_edit.snap || spatial_editor->is_snap_enabled()) {
1251
1252 scale = Math::stepify(scale, spatial_editor->get_scale_snap());
1253 }
1254
1255 set_message(vformat(TTR("Scaling to %s%%."), String::num(scale, 1)));
1256 scale /= 100.0;
1257
1258 Transform r;
1259 r.basis.scale(Vector3(scale, scale, scale));
1260
1261 List<Node *> &selection = editor_selection->get_selected_node_list();
1262
1263 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
1264
1265 Spatial *sp = E->get()->cast_to<Spatial>();
1266 if (!sp)
1267 continue;
1268
1269 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
1270 if (!se)
1271 continue;
1272
1273 Transform original = se->original;
1274
1275 Transform base = Transform(Matrix3(), _edit.center);
1276 Transform t = base * (r * (base.inverse() * original));
1277
1278 sp->set_global_transform(t);
1279 }
1280
1281 surface->update();
1282
1283 } break;
1284
1285 case TRANSFORM_TRANSLATE: {
1286
1287 Vector3 motion_mask;
1288 Plane plane;
1289
1290 switch (_edit.plane) {
1291 case TRANSFORM_VIEW:
1292 motion_mask = Vector3(0, 0, 0);
1293 plane = Plane(_edit.center, _get_camera_normal());
1294 break;
1295 case TRANSFORM_X_AXIS:
1296 motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0);
1297 plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
1298 break;
1299 case TRANSFORM_Y_AXIS:
1300 motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1);
1301 plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
1302 break;
1303 case TRANSFORM_Z_AXIS:
1304 motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2);
1305 plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
1306 break;
1307 }
1308
1309 Vector3 intersection;
1310 if (!plane.intersects_ray(ray_pos, ray, &intersection))
1311 break;
1312
1313 Vector3 click;
1314 if (!plane.intersects_ray(_edit.click_ray_pos, _edit.click_ray, &click))
1315 break;
1316
1317 //_validate_selection();
1318 Vector3 motion = intersection - click;
1319 if (motion_mask != Vector3()) {
1320 motion = motion_mask.dot(motion) * motion_mask;
1321 }
1322
1323 float snap = 0;
1324
1325 if (_edit.snap || spatial_editor->is_snap_enabled()) {
1326
1327 snap = spatial_editor->get_translate_snap();
1328 motion.snap(snap);
1329 }
1330
1331 //set_message("Translating: "+motion);
1332
1333 List<Node *> &selection = editor_selection->get_selected_node_list();
1334
1335 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
1336
1337 Spatial *sp = E->get()->cast_to<Spatial>();
1338 if (!sp) {
1339 continue;
1340 }
1341
1342 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
1343 if (!se) {
1344 continue;
1345 }
1346
1347 Transform t = se->original;
1348 t.origin += motion;
1349 sp->set_global_transform(t);
1350 }
1351 } break;
1352
1353 case TRANSFORM_ROTATE: {
1354
1355 Plane plane;
1356
1357 switch (_edit.plane) {
1358 case TRANSFORM_VIEW:
1359 plane = Plane(_edit.center, _get_camera_normal());
1360 break;
1361 case TRANSFORM_X_AXIS:
1362 plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(0));
1363 break;
1364 case TRANSFORM_Y_AXIS:
1365 plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(1));
1366 break;
1367 case TRANSFORM_Z_AXIS:
1368 plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2));
1369 break;
1370 }
1371
1372 Vector3 intersection;
1373 if (!plane.intersects_ray(ray_pos, ray, &intersection))
1374 break;
1375
1376 Vector3 click;
1377 if (!plane.intersects_ray(_edit.click_ray_pos, _edit.click_ray, &click))
1378 break;
1379
1380 Vector3 y_axis = (click - _edit.center).normalized();
1381 Vector3 x_axis = plane.normal.cross(y_axis).normalized();
1382
1383 float angle = Math::atan2(x_axis.dot(intersection - _edit.center), y_axis.dot(intersection - _edit.center));
1384 if (_edit.snap || spatial_editor->is_snap_enabled()) {
1385
1386 float snap = spatial_editor->get_rotate_snap();
1387
1388 if (snap) {
1389 angle = Math::rad2deg(angle) + snap * 0.5; //else it wont reach +180
1390 angle -= Math::fmod(angle, snap);
1391 set_message(vformat(TTR("Rotating %s degrees."), rtos(angle)));
1392 angle = Math::deg2rad(angle);
1393 } else
1394 set_message(vformat(TTR("Rotating %s degrees."), rtos(Math::rad2deg(angle))));
1395
1396 } else {
1397 set_message(vformat(TTR("Rotating %s degrees."), rtos(Math::rad2deg(angle))));
1398 }
1399
1400 Transform r;
1401 r.basis.rotate(plane.normal, -angle);
1402
1403 List<Node *> &selection = editor_selection->get_selected_node_list();
1404
1405 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
1406
1407 Spatial *sp = E->get()->cast_to<Spatial>();
1408 if (!sp)
1409 continue;
1410
1411 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
1412 if (!se)
1413 continue;
1414
1415 Transform original = se->original;
1416
1417 Transform base = Transform(Matrix3(), _edit.center);
1418 Transform t = base * (r * (base.inverse() * original));
1419
1420 sp->set_global_transform(t);
1421 }
1422
1423 surface->update();
1424 /*
1425 VisualServer::get_singleton()->poly_clear(indicators);
1426
1427 Vector<Vector3> points;
1428 Vector<Vector3> empty;
1429 Vector<Color> colors;
1430 points.push_back(intersection);
1431 points.push_back(_edit.original.origin);
1432 colors.push_back( Color(255,155,100) );
1433 colors.push_back( Color(255,155,100) );
1434 VisualServer::get_singleton()->poly_add_primitive(indicators,points,empty,colors,empty);
1435 */
1436 } break;
1437 default: {}
1438 }
1439 }
1440
1441 } else if (m.button_mask & 2) {
1442
1443 if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
1444 nav_mode = NAVIGATION_ZOOM;
1445 }
1446
1447 } else if (m.button_mask & 4) {
1448
1449 if (nav_scheme == NAVIGATION_GODOT) {
1450
1451 int mod = 0;
1452 if (m.mod.shift)
1453 mod = KEY_SHIFT;
1454 if (m.mod.alt)
1455 mod = KEY_ALT;
1456 if (m.mod.control)
1457 mod = KEY_CONTROL;
1458 if (m.mod.meta)
1459 mod = KEY_META;
1460
1461 if (mod == _get_key_modifier("3d_editor/pan_modifier"))
1462 nav_mode = NAVIGATION_PAN;
1463 else if (mod == _get_key_modifier("3d_editor/zoom_modifier"))
1464 nav_mode = NAVIGATION_ZOOM;
1465 else if (mod == _get_key_modifier("3d_editor/orbit_modifier"))
1466 nav_mode = NAVIGATION_ORBIT;
1467
1468 } else if (nav_scheme == NAVIGATION_MAYA) {
1469 if (m.mod.alt)
1470 nav_mode = NAVIGATION_PAN;
1471 }
1472
1473 } else if (EditorSettings::get_singleton()->get("3d_editor/emulate_3_button_mouse")) {
1474 // Handle trackpad (no external mouse) use case
1475 int mod = 0;
1476 if (m.mod.shift)
1477 mod = KEY_SHIFT;
1478 if (m.mod.alt)
1479 mod = KEY_ALT;
1480 if (m.mod.control)
1481 mod = KEY_CONTROL;
1482 if (m.mod.meta)
1483 mod = KEY_META;
1484
1485 if (mod) {
1486 if (mod == _get_key_modifier("3d_editor/pan_modifier"))
1487 nav_mode = NAVIGATION_PAN;
1488 else if (mod == _get_key_modifier("3d_editor/zoom_modifier"))
1489 nav_mode = NAVIGATION_ZOOM;
1490 else if (mod == _get_key_modifier("3d_editor/orbit_modifier"))
1491 nav_mode = NAVIGATION_ORBIT;
1492 }
1493 }
1494
1495 switch (nav_mode) {
1496 case NAVIGATION_PAN: {
1497
1498 real_t pan_speed = 1 / 150.0;
1499 int pan_speed_modifier = 10;
1500 if (nav_scheme == NAVIGATION_MAYA && m.mod.shift)
1501 pan_speed *= pan_speed_modifier;
1502
1503 Point2i relative;
1504 if (bool(EditorSettings::get_singleton()->get("3d_editor/warped_mouse_panning"))) {
1505 relative = Input::get_singleton()->warp_mouse_motion(m, surface->get_global_rect());
1506 } else {
1507 relative = Point2i(m.relative_x, m.relative_y);
1508 }
1509
1510 Transform camera_transform;
1511
1512 camera_transform.translate(cursor.pos);
1513 camera_transform.basis.rotate(Vector3(0, 1, 0), cursor.y_rot);
1514 camera_transform.basis.rotate(Vector3(1, 0, 0), cursor.x_rot);
1515 Vector3 translation(-relative.x * pan_speed, relative.y * pan_speed, 0);
1516 translation *= cursor.distance / DISTANCE_DEFAULT;
1517 camera_transform.translate(translation);
1518 cursor.pos = camera_transform.origin;
1519
1520 } break;
1521
1522 case NAVIGATION_ZOOM: {
1523 real_t zoom_speed = 1 / 80.0;
1524 int zoom_speed_modifier = 10;
1525 if (nav_scheme == NAVIGATION_MAYA && m.mod.shift)
1526 zoom_speed *= zoom_speed_modifier;
1527
1528 NavigationZoomStyle zoom_style = _get_navigation_zoom_style("3d_editor/zoom_style");
1529 if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) {
1530 if (m.relative_x > 0)
1531 cursor.distance *= 1 - m.relative_x * zoom_speed;
1532 else if (m.relative_x < 0)
1533 cursor.distance /= 1 + m.relative_x * zoom_speed;
1534 } else {
1535 if (m.relative_y > 0)
1536 cursor.distance *= 1 + m.relative_y * zoom_speed;
1537 else if (m.relative_y < 0)
1538 cursor.distance /= 1 - m.relative_y * zoom_speed;
1539 }
1540
1541 } break;
1542
1543 case NAVIGATION_ORBIT: {
1544 cursor.x_rot += m.relative_y / 80.0;
1545 cursor.y_rot += m.relative_x / 80.0;
1546 if (cursor.x_rot > Math_PI / 2.0)
1547 cursor.x_rot = Math_PI / 2.0;
1548 if (cursor.x_rot < -Math_PI / 2.0)
1549 cursor.x_rot = -Math_PI / 2.0;
1550 name = "";
1551 _update_name();
1552 } break;
1553
1554 default: {}
1555 }
1556 } break;
1557 case InputEvent::KEY: {
1558 const InputEventKey &k = p_event.key;
1559 if (!k.pressed)
1560 break;
1561
1562 if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) {
1563 if (_edit.mode != TRANSFORM_NONE) {
1564 _edit.snap = true;
1565 }
1566 }
1567 if (ED_IS_SHORTCUT("spatial_editor/bottom_view", p_event)) {
1568 cursor.y_rot = 0;
1569 cursor.x_rot = -Math_PI / 2.0;
1570 set_message(TTR("Bottom View."), 2);
1571 name = TTR("Bottom");
1572 _update_name();
1573 }
1574 if (ED_IS_SHORTCUT("spatial_editor/top_view", p_event)) {
1575 cursor.y_rot = 0;
1576 cursor.x_rot = Math_PI / 2.0;
1577 set_message(TTR("Top View."), 2);
1578 name = TTR("Top");
1579 _update_name();
1580 }
1581 if (ED_IS_SHORTCUT("spatial_editor/rear_view", p_event)) {
1582 cursor.x_rot = 0;
1583 cursor.y_rot = Math_PI;
1584 set_message(TTR("Rear View."), 2);
1585 name = TTR("Rear");
1586 _update_name();
1587 }
1588 if (ED_IS_SHORTCUT("spatial_editor/front_view", p_event)) {
1589 cursor.x_rot = 0;
1590 cursor.y_rot = 0;
1591 set_message(TTR("Front View."), 2);
1592 name = TTR("Front");
1593 _update_name();
1594 }
1595 if (ED_IS_SHORTCUT("spatial_editor/left_view", p_event)) {
1596 cursor.x_rot = 0;
1597 cursor.y_rot = Math_PI / 2.0;
1598 set_message(TTR("Left View."), 2);
1599 name = TTR("Left");
1600 _update_name();
1601 }
1602 if (ED_IS_SHORTCUT("spatial_editor/right_view", p_event)) {
1603 cursor.x_rot = 0;
1604 cursor.y_rot = -Math_PI / 2.0;
1605 set_message(TTR("Right View."), 2);
1606 name = TTR("Right");
1607 _update_name();
1608 }
1609 if (ED_IS_SHORTCUT("spatial_editor/switch_perspective_orthogonal", p_event)) {
1610 _menu_option(orthogonal ? VIEW_PERSPECTIVE : VIEW_ORTHOGONAL);
1611 _update_name();
1612 }
1613 if (ED_IS_SHORTCUT("spatial_editor/insert_anim_key", p_event)) {
1614 if (!get_selected_count() || _edit.mode != TRANSFORM_NONE)
1615 break;
1616
1617 if (!AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
1618 set_message(TTR("Keying is disabled (no key inserted)."));
1619 break;
1620 }
1621
1622 List<Node *> &selection = editor_selection->get_selected_node_list();
1623
1624 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
1625
1626 Spatial *sp = E->get()->cast_to<Spatial>();
1627 if (!sp)
1628 continue;
1629
1630 emit_signal("transform_key_request", sp, "", sp->get_transform());
1631 }
1632
1633 set_message(TTR("Animation Key Inserted."));
1634 }
1635
1636 if (k.scancode == KEY_SPACE) {
1637 if (!k.pressed) emit_signal("toggle_maximize_view", this);
1638 }
1639
1640 } break;
1641 }
1642 }
1643
set_message(String p_message,float p_time)1644 void SpatialEditorViewport::set_message(String p_message, float p_time) {
1645
1646 message = p_message;
1647 message_time = p_time;
1648 }
1649
_notification(int p_what)1650 void SpatialEditorViewport::_notification(int p_what) {
1651
1652 if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
1653
1654 bool visible = is_visible();
1655
1656 set_process(visible);
1657
1658 if (visible)
1659 _update_camera();
1660
1661 call_deferred("update_transform_gizmo_view");
1662 }
1663
1664 if (p_what == NOTIFICATION_RESIZED) {
1665
1666 call_deferred("update_transform_gizmo_view");
1667 }
1668
1669 if (p_what == NOTIFICATION_PROCESS) {
1670
1671 //force editr camera
1672 /*
1673 current_camera=get_root_node()->get_current_camera();
1674 if (current_camera!=camera) {
1675
1676
1677 }
1678 */
1679
1680 _update_camera();
1681
1682 Map<Node *, Object *> &selection = editor_selection->get_selection();
1683
1684 bool changed = false;
1685 bool exist = false;
1686
1687 for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
1688
1689 Spatial *sp = E->key()->cast_to<Spatial>();
1690 if (!sp)
1691 continue;
1692
1693 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
1694 if (!se)
1695 continue;
1696
1697 VisualInstance *vi = sp->cast_to<VisualInstance>();
1698
1699 if (se->aabb.has_no_surface()) {
1700
1701 se->aabb = vi ? vi->get_aabb() : AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
1702 }
1703
1704 Transform t = sp->get_global_transform();
1705 t.translate(se->aabb.pos);
1706 t.basis.scale(se->aabb.size);
1707
1708 exist = true;
1709 if (se->last_xform == t)
1710 continue;
1711 changed = true;
1712 se->last_xform = t;
1713 VisualServer::get_singleton()->instance_set_transform(se->sbox_instance, t);
1714 }
1715
1716 if (changed || (spatial_editor->is_gizmo_visible() && !exist)) {
1717 spatial_editor->update_transform_gizmo();
1718 }
1719
1720 if (message_time > 0) {
1721
1722 if (message != last_message) {
1723 surface->update();
1724 last_message = message;
1725 }
1726
1727 message_time -= get_fixed_process_delta_time();
1728 if (message_time < 0)
1729 surface->update();
1730 }
1731
1732 // FPS Counter.
1733 bool show_fps = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_FPS)) && !previewing;
1734 if (show_fps != fps->is_visible()) {
1735 if (show_fps)
1736 fps->show();
1737 else
1738 fps->hide();
1739 }
1740
1741 if (show_fps) {
1742 const float os_fps = OS::get_singleton()->get_frames_per_second();
1743 String text = TTR("FPS") + ": " + itos(os_fps) + " (" + String::num(1000.0f / os_fps, 2) + " ms)";
1744
1745 if (fps_label->get_text() != text || surface->get_size() != prev_size) {
1746 fps_label->set_text(text);
1747 Vector2 container_position = Vector2(surface->get_size().x - fps->get_size().x - 20, 20);
1748 if (preview)
1749 container_position.y += 20;
1750
1751 container_position *= EDSCALE;
1752 fps->set_pos(container_position);
1753 }
1754 }
1755 }
1756
1757 if (p_what == NOTIFICATION_ENTER_TREE) {
1758
1759 surface->connect("draw", this, "_draw");
1760 surface->connect("input_event", this, "_sinput");
1761 surface->connect("mouse_enter", this, "_smouseenter");
1762 fps->add_style_override("panel", get_stylebox("panel", "Panel"));
1763 preview_camera->set_icon(get_icon("Camera", "EditorIcons"));
1764 _init_gizmo_instance(index);
1765 }
1766 if (p_what == NOTIFICATION_EXIT_TREE) {
1767
1768 _finish_gizmo_instances();
1769 }
1770
1771 if (p_what == NOTIFICATION_MOUSE_ENTER) {
1772 }
1773
1774 if (p_what == NOTIFICATION_DRAW) {
1775 }
1776 }
1777
_draw()1778 void SpatialEditorViewport::_draw() {
1779
1780 if (surface->has_focus()) {
1781 Size2 size = surface->get_size();
1782 Rect2 r = Rect2(Point2(), size);
1783 get_stylebox("EditorFocus", "EditorStyles")->draw(surface->get_canvas_item(), r);
1784 }
1785
1786 RID ci = surface->get_canvas_item();
1787
1788 if (cursor.region_select) {
1789
1790 VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor.region_begin, cursor.region_end - cursor.region_begin), Color(0.7, 0.7, 1.0, 0.3));
1791 }
1792
1793 if (message_time > 0) {
1794 Ref<Font> font = get_font("font", "Label");
1795 Point2 msgpos = Point2(5, get_size().y - 20);
1796 font->draw(ci, msgpos + Point2(1, 1), message, Color(0, 0, 0, 0.8));
1797 font->draw(ci, msgpos + Point2(-1, -1), message, Color(0, 0, 0, 0.8));
1798 font->draw(ci, msgpos, message, Color(1, 1, 1, 1));
1799 }
1800
1801 if (_edit.mode == TRANSFORM_ROTATE) {
1802
1803 Point2 center = _point_to_screen(_edit.center);
1804 VisualServer::get_singleton()->canvas_item_add_line(ci, _edit.mouse_pos, center, Color(0.4, 0.7, 1.0, 0.8));
1805 }
1806
1807 if (previewing) {
1808
1809 Size2 ss = Size2(Globals::get_singleton()->get("display/width"), Globals::get_singleton()->get("display/height"));
1810 float aspect = ss.get_aspect();
1811 Size2 s = get_size();
1812
1813 Rect2 draw_rect;
1814
1815 switch (previewing->get_keep_aspect_mode()) {
1816 case Camera::KEEP_WIDTH: {
1817
1818 draw_rect.size = Size2(s.width, s.width / aspect);
1819 draw_rect.pos.x = 0;
1820 draw_rect.pos.y = (s.height - draw_rect.size.y) * 0.5;
1821
1822 } break;
1823 case Camera::KEEP_HEIGHT: {
1824
1825 draw_rect.size = Size2(s.height * aspect, s.height);
1826 draw_rect.pos.y = 0;
1827 draw_rect.pos.x = (s.width - draw_rect.size.x) * 0.5;
1828
1829 } break;
1830 }
1831
1832 draw_rect = Rect2(Vector2(), s).clip(draw_rect);
1833
1834 surface->draw_line(draw_rect.pos, draw_rect.pos + Vector2(draw_rect.size.x, 0), Color(0.6, 0.6, 0.1, 0.5), 2.0);
1835 surface->draw_line(draw_rect.pos + Vector2(draw_rect.size.x, 0), draw_rect.pos + draw_rect.size, Color(0.6, 0.6, 0.1, 0.5), 2.0);
1836 surface->draw_line(draw_rect.pos + draw_rect.size, draw_rect.pos + Vector2(0, draw_rect.size.y), Color(0.6, 0.6, 0.1, 0.5), 2.0);
1837 surface->draw_line(draw_rect.pos, draw_rect.pos + Vector2(0, draw_rect.size.y), Color(0.6, 0.6, 0.1, 0.5), 2.0);
1838 }
1839 }
1840
_menu_option(int p_option)1841 void SpatialEditorViewport::_menu_option(int p_option) {
1842
1843 switch (p_option) {
1844
1845 case VIEW_TOP: {
1846
1847 cursor.x_rot = Math_PI / 2.0;
1848 cursor.y_rot = 0;
1849 name = TTR("Top");
1850 _update_name();
1851 } break;
1852 case VIEW_BOTTOM: {
1853
1854 cursor.x_rot = -Math_PI / 2.0;
1855 cursor.y_rot = 0;
1856 name = TTR("Bottom");
1857 _update_name();
1858
1859 } break;
1860 case VIEW_LEFT: {
1861
1862 cursor.y_rot = Math_PI / 2.0;
1863 cursor.x_rot = 0;
1864 name = TTR("Left");
1865 _update_name();
1866
1867 } break;
1868 case VIEW_RIGHT: {
1869
1870 cursor.y_rot = -Math_PI / 2.0;
1871 cursor.x_rot = 0;
1872 name = TTR("Right");
1873 _update_name();
1874
1875 } break;
1876 case VIEW_FRONT: {
1877
1878 cursor.y_rot = 0;
1879 cursor.x_rot = 0;
1880 name = TTR("Front");
1881 _update_name();
1882
1883 } break;
1884 case VIEW_REAR: {
1885
1886 cursor.y_rot = Math_PI;
1887 cursor.x_rot = 0;
1888 name = TTR("Rear");
1889 _update_name();
1890
1891 } break;
1892 case VIEW_CENTER_TO_ORIGIN: {
1893
1894 cursor.pos = Vector3(0, 0, 0);
1895
1896 } break;
1897 case VIEW_CENTER_TO_SELECTION: {
1898
1899 if (!get_selected_count())
1900 break;
1901
1902 Vector3 center;
1903 int count = 0;
1904
1905 List<Node *> &selection = editor_selection->get_selected_node_list();
1906
1907 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
1908
1909 Spatial *sp = E->get()->cast_to<Spatial>();
1910 if (!sp)
1911 continue;
1912
1913 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
1914 if (!se)
1915 continue;
1916
1917 center += sp->get_global_transform().origin;
1918 count++;
1919 }
1920
1921 if (count != 0) {
1922 center /= float(count);
1923 }
1924
1925 cursor.pos = center;
1926 } break;
1927 case VIEW_ALIGN_SELECTION_WITH_VIEW: {
1928
1929 if (!get_selected_count())
1930 break;
1931
1932 Transform camera_transform = camera->get_global_transform();
1933
1934 List<Node *> &selection = editor_selection->get_selected_node_list();
1935
1936 undo_redo->create_action(TTR("Align with view"));
1937 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
1938
1939 Spatial *sp = E->get()->cast_to<Spatial>();
1940 if (!sp)
1941 continue;
1942
1943 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
1944 if (!se)
1945 continue;
1946
1947 Transform xform = camera_transform;
1948 xform.scale_basis(sp->get_scale());
1949
1950 undo_redo->add_do_method(sp, "set_global_transform", xform);
1951 undo_redo->add_undo_method(sp, "set_global_transform", sp->get_global_transform());
1952 }
1953 undo_redo->commit_action();
1954 } break;
1955 case VIEW_ENVIRONMENT: {
1956
1957 int idx = view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT);
1958 bool current = view_menu->get_popup()->is_item_checked(idx);
1959 current = !current;
1960 if (current) {
1961
1962 camera->set_environment(RES());
1963 } else {
1964
1965 camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment());
1966 }
1967
1968 view_menu->get_popup()->set_item_checked(idx, current);
1969
1970 } break;
1971 case VIEW_PERSPECTIVE: {
1972
1973 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), true);
1974 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), false);
1975 orthogonal = false;
1976 call_deferred("update_transform_gizmo_view");
1977 _update_name();
1978
1979 } break;
1980 case VIEW_ORTHOGONAL: {
1981
1982 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), false);
1983 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), true);
1984 orthogonal = true;
1985 call_deferred("update_transform_gizmo_view");
1986 _update_name();
1987
1988 } break;
1989 case VIEW_AUDIO_LISTENER: {
1990
1991 int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
1992 bool current = view_menu->get_popup()->is_item_checked(idx);
1993 current = !current;
1994 viewport->set_as_audio_listener(current);
1995 view_menu->get_popup()->set_item_checked(idx, current);
1996
1997 } break;
1998 case VIEW_GIZMOS: {
1999
2000 int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
2001 bool current = view_menu->get_popup()->is_item_checked(idx);
2002 current = !current;
2003 if (current)
2004 camera->set_visible_layers(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + index)) | (1 << GIZMO_EDIT_LAYER) | (1 << GIZMO_GRID_LAYER));
2005 else
2006 camera->set_visible_layers(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + index)) | (1 << GIZMO_GRID_LAYER));
2007 view_menu->get_popup()->set_item_checked(idx, current);
2008
2009 } break;
2010 case VIEW_FPS: {
2011 int idx = view_menu->get_popup()->get_item_index(VIEW_FPS);
2012 bool current = view_menu->get_popup()->is_item_checked(idx);
2013 view_menu->get_popup()->set_item_checked(idx, !current);
2014
2015 } break;
2016 }
2017 }
2018
_preview_exited_scene()2019 void SpatialEditorViewport::_preview_exited_scene() {
2020
2021 preview_camera->set_pressed(false);
2022 _toggle_camera_preview(false);
2023 view_menu->show();
2024 }
2025
_init_gizmo_instance(int p_idx)2026 void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
2027
2028 uint32_t layer = 1 << (GIZMO_BASE_LAYER + p_idx); //|(1<<GIZMO_GRID_LAYER);
2029
2030 for (int i = 0; i < 3; i++) {
2031 move_gizmo_instance[i] = VS::get_singleton()->instance_create();
2032 VS::get_singleton()->instance_set_base(move_gizmo_instance[i], spatial_editor->get_move_gizmo(i)->get_rid());
2033 VS::get_singleton()->instance_set_scenario(move_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
2034 VS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i], VS::INSTANCE_FLAG_VISIBLE, false);
2035 //VS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
2036 VS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
2037 VS::get_singleton()->instance_set_layer_mask(move_gizmo_instance[i], layer);
2038
2039 rotate_gizmo_instance[i] = VS::get_singleton()->instance_create();
2040 VS::get_singleton()->instance_set_base(rotate_gizmo_instance[i], spatial_editor->get_rotate_gizmo(i)->get_rid());
2041 VS::get_singleton()->instance_set_scenario(rotate_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
2042 VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i], VS::INSTANCE_FLAG_VISIBLE, false);
2043 //VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
2044 VS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
2045 VS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i], layer);
2046 }
2047 }
2048
_finish_gizmo_instances()2049 void SpatialEditorViewport::_finish_gizmo_instances() {
2050
2051 for (int i = 0; i < 3; i++) {
2052 VS::get_singleton()->free(move_gizmo_instance[i]);
2053 VS::get_singleton()->free(rotate_gizmo_instance[i]);
2054 }
2055 }
_toggle_camera_preview(bool p_activate)2056 void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {
2057
2058 ERR_FAIL_COND(p_activate && !preview);
2059 ERR_FAIL_COND(!p_activate && !previewing);
2060
2061 if (!p_activate) {
2062
2063 previewing->disconnect("exit_tree", this, "_preview_exited_scene");
2064 previewing = NULL;
2065 VS::get_singleton()->viewport_attach_camera(viewport->get_viewport(), camera->get_camera()); //restore
2066 if (!preview)
2067 preview_camera->hide();
2068 view_menu->show();
2069 surface->update();
2070
2071 } else {
2072
2073 previewing = preview;
2074 previewing->connect("exit_tree", this, "_preview_exited_scene");
2075 VS::get_singleton()->viewport_attach_camera(viewport->get_viewport(), preview->get_camera()); //replace
2076 view_menu->hide();
2077 surface->update();
2078 }
2079 }
2080
_selection_result_pressed(int p_result)2081 void SpatialEditorViewport::_selection_result_pressed(int p_result) {
2082
2083 if (selection_results.size() <= p_result)
2084 return;
2085
2086 clicked = selection_results[p_result].item->get_instance_ID();
2087
2088 if (clicked) {
2089 _select_clicked(clicked_wants_append, true);
2090 clicked = 0;
2091 }
2092 }
2093
_selection_menu_hide()2094 void SpatialEditorViewport::_selection_menu_hide() {
2095
2096 selection_results.clear();
2097 selection_menu->clear();
2098 selection_menu->set_size(Vector2(0, 0));
2099 }
2100
set_can_preview(Camera * p_preview)2101 void SpatialEditorViewport::set_can_preview(Camera *p_preview) {
2102
2103 preview = p_preview;
2104
2105 if (!preview_camera->is_pressed()) {
2106
2107 if (p_preview) {
2108 preview_camera->show();
2109 } else {
2110 preview_camera->hide();
2111 }
2112 }
2113 }
2114
update_transform_gizmo_view()2115 void SpatialEditorViewport::update_transform_gizmo_view() {
2116
2117 if (!is_visible())
2118 return;
2119
2120 Transform xform = spatial_editor->get_gizmo_transform();
2121
2122 Transform camera_xform = camera->get_transform();
2123 Vector3 camz = -camera_xform.get_basis().get_axis(2).normalized();
2124 Vector3 camy = -camera_xform.get_basis().get_axis(1).normalized();
2125 Plane p(camera_xform.origin, camz);
2126 float gizmo_d = Math::abs(p.distance_to(xform.origin));
2127 float d0 = camera->unproject_position(camera_xform.origin + camz * gizmo_d).y;
2128 float d1 = camera->unproject_position(camera_xform.origin + camz * gizmo_d + camy).y;
2129 float dd = Math::abs(d0 - d1);
2130 if (dd == 0)
2131 dd = 0.0001;
2132
2133 float gsize = EditorSettings::get_singleton()->get("3d_editor/manipulator_gizmo_size");
2134 gizmo_scale = (gsize / Math::abs(dd));
2135 Vector3 scale = Vector3(1, 1, 1) * gizmo_scale;
2136
2137 xform.basis.scale(scale);
2138
2139 //xform.basis.scale(GIZMO_SCALE_DEFAULT*Vector3(1,1,1));
2140
2141 for (int i = 0; i < 3; i++) {
2142 VisualServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform);
2143 VisualServer::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i], VS::INSTANCE_FLAG_VISIBLE, spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE));
2144 VisualServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform);
2145 VisualServer::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i], VS::INSTANCE_FLAG_VISIBLE, spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE));
2146 }
2147 }
2148
set_state(const Dictionary & p_state)2149 void SpatialEditorViewport::set_state(const Dictionary &p_state) {
2150
2151 cursor.pos = p_state["pos"];
2152 cursor.x_rot = p_state["x_rot"];
2153 cursor.y_rot = p_state["y_rot"];
2154 cursor.distance = p_state["distance"];
2155 bool env = p_state["use_environment"];
2156 bool orth = p_state["use_orthogonal"];
2157 if (orth)
2158 _menu_option(VIEW_ORTHOGONAL);
2159 else
2160 _menu_option(VIEW_PERSPECTIVE);
2161 if (env != camera->get_environment().is_valid())
2162 _menu_option(VIEW_ENVIRONMENT);
2163 if (p_state.has("listener")) {
2164 bool listener = p_state["listener"];
2165
2166 int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
2167 viewport->set_as_audio_listener(listener);
2168 view_menu->get_popup()->set_item_checked(idx, listener);
2169 }
2170
2171 if (p_state.has("previewing")) {
2172 Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]);
2173 if (pv && pv->cast_to<Camera>()) {
2174 previewing = pv->cast_to<Camera>();
2175 previewing->connect("exit_tree", this, "_preview_exited_scene");
2176 VS::get_singleton()->viewport_attach_camera(viewport->get_viewport(), previewing->get_camera()); //replace
2177 view_menu->hide();
2178 surface->update();
2179 preview_camera->set_pressed(true);
2180 preview_camera->show();
2181 }
2182 }
2183 }
2184
get_state() const2185 Dictionary SpatialEditorViewport::get_state() const {
2186
2187 Dictionary d;
2188 d["pos"] = cursor.pos;
2189 d["x_rot"] = cursor.x_rot;
2190 d["y_rot"] = cursor.y_rot;
2191 d["distance"] = cursor.distance;
2192 d["use_environment"] = camera->get_environment().is_valid();
2193 d["use_orthogonal"] = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL;
2194 d["listener"] = viewport->is_audio_listener();
2195 if (previewing) {
2196 d["previewing"] = EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing);
2197 }
2198
2199 return d;
2200 }
2201
_bind_methods()2202 void SpatialEditorViewport::_bind_methods() {
2203
2204 ObjectTypeDB::bind_method(_MD("_draw"), &SpatialEditorViewport::_draw);
2205 ObjectTypeDB::bind_method(_MD("_smouseenter"), &SpatialEditorViewport::_smouseenter);
2206 ObjectTypeDB::bind_method(_MD("_sinput"), &SpatialEditorViewport::_sinput);
2207 ObjectTypeDB::bind_method(_MD("_menu_option"), &SpatialEditorViewport::_menu_option);
2208 ObjectTypeDB::bind_method(_MD("_toggle_camera_preview"), &SpatialEditorViewport::_toggle_camera_preview);
2209 ObjectTypeDB::bind_method(_MD("_preview_exited_scene"), &SpatialEditorViewport::_preview_exited_scene);
2210 ObjectTypeDB::bind_method(_MD("update_transform_gizmo_view"), &SpatialEditorViewport::update_transform_gizmo_view);
2211 ObjectTypeDB::bind_method(_MD("_selection_result_pressed"), &SpatialEditorViewport::_selection_result_pressed);
2212 ObjectTypeDB::bind_method(_MD("_selection_menu_hide"), &SpatialEditorViewport::_selection_menu_hide);
2213
2214 ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")));
2215 }
2216
reset()2217 void SpatialEditorViewport::reset() {
2218
2219 orthogonal = false;
2220 message_time = 0;
2221 message = "";
2222 last_message = "";
2223 name = "";
2224
2225 cursor.x_rot = 0.5;
2226 cursor.y_rot = 0.5;
2227 cursor.distance = 4;
2228 cursor.region_select = false;
2229 _update_name();
2230 }
2231
SpatialEditorViewport(SpatialEditor * p_spatial_editor,EditorNode * p_editor,int p_index)2232 SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) {
2233
2234 _edit.mode = TRANSFORM_NONE;
2235 _edit.plane = TRANSFORM_VIEW;
2236 _edit.edited_gizmo = 0;
2237 _edit.snap = 1;
2238 _edit.gizmo_handle = 0;
2239
2240 index = p_index;
2241 editor = p_editor;
2242 editor_selection = editor->get_editor_selection();
2243 undo_redo = editor->get_undo_redo();
2244 clicked = 0;
2245 clicked_includes_current = false;
2246 orthogonal = false;
2247 message_time = 0;
2248
2249 spatial_editor = p_spatial_editor;
2250 Control *c = memnew(Control);
2251 add_child(c);
2252 c->set_area_as_parent_rect();
2253 viewport = memnew(Viewport);
2254 viewport->set_disable_input(true);
2255 c->add_child(viewport);
2256 surface = memnew(Control);
2257 add_child(surface);
2258 surface->set_area_as_parent_rect();
2259 camera = memnew(Camera);
2260 camera->set_disable_gizmo(true);
2261 camera->set_visible_layers(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + p_index)) | (1 << GIZMO_EDIT_LAYER) | (1 << GIZMO_GRID_LAYER));
2262 //camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment());
2263 viewport->add_child(camera);
2264 camera->make_current();
2265 surface->set_focus_mode(FOCUS_ALL);
2266
2267 view_menu = memnew(MenuButton);
2268 surface->add_child(view_menu);
2269 view_menu->set_pos(Point2(4, 4));
2270 view_menu->set_self_opacity(0.5);
2271 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/top_view"), VIEW_TOP);
2272 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/bottom_view"), VIEW_BOTTOM);
2273 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/left_view"), VIEW_LEFT);
2274 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/right_view"), VIEW_RIGHT);
2275 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/front_view"), VIEW_FRONT);
2276 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/rear_view"), VIEW_REAR);
2277 view_menu->get_popup()->add_separator();
2278 view_menu->get_popup()->add_check_item(TTR("Perspective") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_PERSPECTIVE);
2279 view_menu->get_popup()->add_check_item(TTR("Orthogonal") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_ORTHOGONAL);
2280 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), true);
2281 view_menu->get_popup()->add_separator();
2282 view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_environment", TTR("Environment")), VIEW_ENVIRONMENT);
2283 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT), true);
2284 view_menu->get_popup()->add_separator();
2285 view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_audio_listener", TTR("Audio Listener")), VIEW_AUDIO_LISTENER);
2286 view_menu->get_popup()->add_separator();
2287 view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_gizmos", TTR("Gizmos")), VIEW_GIZMOS);
2288 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS), true);
2289 view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_fps", TTR("View FPS")), VIEW_FPS);
2290
2291 view_menu->get_popup()->add_separator();
2292 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_origin"), VIEW_CENTER_TO_ORIGIN);
2293 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_selection"), VIEW_CENTER_TO_SELECTION);
2294 view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_selection_with_view"), VIEW_ALIGN_SELECTION_WITH_VIEW);
2295 view_menu->get_popup()->connect("item_pressed", this, "_menu_option");
2296
2297 preview_camera = memnew(Button);
2298 preview_camera->set_toggle_mode(true);
2299 preview_camera->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, 90);
2300 preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10);
2301 preview_camera->set_text("preview");
2302 surface->add_child(preview_camera);
2303 preview_camera->hide();
2304 preview_camera->connect("toggled", this, "_toggle_camera_preview");
2305 previewing = NULL;
2306 preview = NULL;
2307 gizmo_scale = 1.0;
2308
2309 // FPS Counter.
2310 fps = memnew(PanelContainer);
2311 fps->set_self_opacity(0.4f);
2312 surface->add_child(fps);
2313 fps_label = memnew(Label);
2314 fps->add_child(fps_label);
2315 fps->hide();
2316
2317 selection_menu = memnew(PopupMenu);
2318 add_child(selection_menu);
2319 selection_menu->set_custom_minimum_size(Vector2(100, 0));
2320 selection_menu->connect("item_pressed", this, "_selection_result_pressed");
2321 selection_menu->connect("popup_hide", this, "_selection_menu_hide");
2322
2323 if (p_index == 0) {
2324 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER), true);
2325 viewport->set_as_audio_listener(true);
2326 }
2327
2328 name = TTR("Top");
2329 _update_name();
2330
2331 EditorSettings::get_singleton()->connect("settings_changed", this, "update_transform_gizmo_view");
2332 }
2333
2334 SpatialEditor *SpatialEditor::singleton = NULL;
2335
~SpatialEditorSelectedItem()2336 SpatialEditorSelectedItem::~SpatialEditorSelectedItem() {
2337
2338 if (sbox_instance.is_valid())
2339 VisualServer::get_singleton()->free(sbox_instance);
2340 }
2341
select_gizmo_highlight_axis(int p_axis)2342 void SpatialEditor::select_gizmo_highlight_axis(int p_axis) {
2343
2344 for (int i = 0; i < 3; i++) {
2345
2346 move_gizmo[i]->surface_set_material(0, i == p_axis ? gizmo_hl : gizmo_color[i]);
2347 rotate_gizmo[i]->surface_set_material(0, (i + 3) == p_axis ? gizmo_hl : gizmo_color[i]);
2348 }
2349 }
2350
update_transform_gizmo()2351 void SpatialEditor::update_transform_gizmo() {
2352
2353 List<Node *> &selection = editor_selection->get_selected_node_list();
2354 AABB center;
2355 bool first = true;
2356
2357 Matrix3 gizmo_basis;
2358 bool local_gizmo_coords = transform_menu->get_popup()->is_item_checked(transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS));
2359
2360 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
2361
2362 Spatial *sp = E->get()->cast_to<Spatial>();
2363 if (!sp)
2364 continue;
2365
2366 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
2367 if (!se)
2368 continue;
2369
2370 Transform xf = se->sp->get_global_transform();
2371 if (first) {
2372 center.pos = xf.origin;
2373 first = false;
2374 if (local_gizmo_coords) {
2375 gizmo_basis = xf.basis;
2376 gizmo_basis.orthonormalize();
2377 }
2378 } else {
2379 center.expand_to(xf.origin);
2380 gizmo_basis = Matrix3();
2381 }
2382 // count++;
2383 }
2384
2385 Vector3 pcenter = center.pos + center.size * 0.5;
2386 gizmo.visible = !first;
2387 gizmo.transform.origin = pcenter;
2388 gizmo.transform.basis = gizmo_basis;
2389
2390 for (int i = 0; i < 4; i++) {
2391 viewports[i]->update_transform_gizmo_view();
2392 }
2393 }
2394
_get_editor_data(Object * p_what)2395 Object *SpatialEditor::_get_editor_data(Object *p_what) {
2396
2397 Spatial *sp = p_what->cast_to<Spatial>();
2398 if (!sp)
2399 return NULL;
2400
2401 SpatialEditorSelectedItem *si = memnew(SpatialEditorSelectedItem);
2402
2403 si->sp = sp;
2404 si->sbox_instance = VisualServer::get_singleton()->instance_create2(selection_box->get_rid(), sp->get_world()->get_scenario());
2405 VS::get_singleton()->instance_geometry_set_cast_shadows_setting(si->sbox_instance, VS::SHADOW_CASTING_SETTING_OFF);
2406
2407 if (get_tree()->is_editor_hint())
2408 editor->call("edit_node", sp);
2409
2410 return si;
2411 }
2412
_generate_selection_box()2413 void SpatialEditor::_generate_selection_box() {
2414
2415 AABB aabb(Vector3(), Vector3(1, 1, 1));
2416 aabb.grow_by(aabb.get_longest_axis_size() / 20.0);
2417
2418 Ref<SurfaceTool> st = memnew(SurfaceTool);
2419
2420 st->begin(Mesh::PRIMITIVE_LINES);
2421 for (int i = 0; i < 12; i++) {
2422
2423 Vector3 a, b;
2424 aabb.get_edge(i, a, b);
2425
2426 /*Vector<Vector3> points;
2427 Vector<Color> colors;
2428 points.push_back(a);
2429 points.push_back(b);*/
2430
2431 st->add_color(Color(1.0, 1.0, 0.8, 0.8));
2432 st->add_vertex(a);
2433 st->add_color(Color(1.0, 1.0, 0.8, 0.4));
2434 st->add_vertex(a.linear_interpolate(b, 0.2));
2435
2436 st->add_color(Color(1.0, 1.0, 0.8, 0.4));
2437 st->add_vertex(a.linear_interpolate(b, 0.8));
2438 st->add_color(Color(1.0, 1.0, 0.8, 0.8));
2439 st->add_vertex(b);
2440 }
2441
2442 Ref<FixedMaterial> mat = memnew(FixedMaterial);
2443 mat->set_flag(Material::FLAG_UNSHADED, true);
2444 mat->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1));
2445 mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
2446 mat->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
2447 st->set_material(mat);
2448 selection_box = st->commit();
2449 }
2450
get_state() const2451 Dictionary SpatialEditor::get_state() const {
2452
2453 Dictionary d;
2454
2455 d["snap_enabled"] = snap_enabled;
2456 d["translate_snap"] = get_translate_snap();
2457 d["rotate_snap"] = get_rotate_snap();
2458 d["scale_snap"] = get_scale_snap();
2459
2460 int local_coords_index = transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS);
2461 d["local_coords"] = transform_menu->get_popup()->is_item_checked(local_coords_index);
2462
2463 int vc = 0;
2464 if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT)))
2465 vc = 1;
2466 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS)))
2467 vc = 2;
2468 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS)))
2469 vc = 3;
2470 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS)))
2471 vc = 4;
2472 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT)))
2473 vc = 5;
2474 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT)))
2475 vc = 6;
2476
2477 d["viewport_mode"] = vc;
2478 Array vpdata;
2479 for (int i = 0; i < 4; i++) {
2480 vpdata.push_back(viewports[i]->get_state());
2481 }
2482
2483 d["viewports"] = vpdata;
2484
2485 d["default_light"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT));
2486 d["ambient_light_color"] = settings_ambient_color->get_color();
2487
2488 d["default_srgb"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB));
2489 d["show_grid"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_GRID));
2490 d["show_origin"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN));
2491 d["fov"] = get_fov();
2492 d["znear"] = get_znear();
2493 d["zfar"] = get_zfar();
2494 d["deflight_rot_x"] = settings_default_light_rot_x;
2495 d["deflight_rot_y"] = settings_default_light_rot_y;
2496
2497 return d;
2498 }
set_state(const Dictionary & p_state)2499 void SpatialEditor::set_state(const Dictionary &p_state) {
2500
2501 Dictionary d = p_state;
2502
2503 if (d.has("snap_enabled")) {
2504 snap_enabled = d["snap_enabled"];
2505 int snap_enabled_idx = transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_USE_SNAP);
2506 transform_menu->get_popup()->set_item_checked(snap_enabled_idx, snap_enabled);
2507 }
2508
2509 if (d.has("translate_snap"))
2510 snap_translate->set_text(d["translate_snap"]);
2511
2512 if (d.has("rotate_snap"))
2513 snap_rotate->set_text(d["rotate_snap"]);
2514
2515 if (d.has("scale_snap"))
2516 snap_scale->set_text(d["scale_snap"]);
2517
2518 if (d.has("local_coords")) {
2519 int local_coords_idx = transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS);
2520 transform_menu->get_popup()->set_item_checked(local_coords_idx, d["local_coords"]);
2521 update_transform_gizmo();
2522 }
2523
2524 if (d.has("viewport_mode")) {
2525 int vc = d["viewport_mode"];
2526
2527 if (vc == 1)
2528 _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
2529 else if (vc == 2)
2530 _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS);
2531 else if (vc == 3)
2532 _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS);
2533 else if (vc == 4)
2534 _menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS);
2535 else if (vc == 5)
2536 _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT);
2537 else if (vc == 6)
2538 _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT);
2539 }
2540
2541 if (d.has("viewports")) {
2542 Array vp = d["viewports"];
2543 ERR_FAIL_COND(vp.size() > 4);
2544
2545 for (int i = 0; i < 4; i++) {
2546 viewports[i]->set_state(vp[i]);
2547 }
2548 }
2549
2550 if (d.has("zfar"))
2551 settings_zfar->set_val(float(d["zfar"]));
2552 if (d.has("znear"))
2553 settings_znear->set_val(float(d["znear"]));
2554 if (d.has("fov"))
2555 settings_fov->set_val(float(d["fov"]));
2556
2557 if (d.has("default_light")) {
2558 bool use = d["default_light"];
2559
2560 bool existing = light_instance.is_valid();
2561 if (use != existing) {
2562 if (existing) {
2563 VisualServer::get_singleton()->free(light_instance);
2564 light_instance = RID();
2565 } else {
2566 light_instance = VisualServer::get_singleton()->instance_create2(light, get_tree()->get_root()->get_world()->get_scenario());
2567 VisualServer::get_singleton()->instance_set_transform(light_instance, light_transform);
2568 }
2569 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT), light_instance.is_valid());
2570 }
2571 }
2572 if (d.has("ambient_light_color")) {
2573 settings_ambient_color->set_color(d["ambient_light_color"]);
2574 viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR, d["ambient_light_color"]);
2575 }
2576
2577 if (d.has("default_srgb")) {
2578 bool use = d["default_srgb"];
2579
2580 viewport_environment->set_enable_fx(Environment::FX_SRGB, use);
2581 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB), use);
2582 }
2583 if (d.has("show_grid")) {
2584 bool use = d["show_grid"];
2585
2586 if (use != view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_GRID))) {
2587 _menu_item_pressed(MENU_VIEW_GRID);
2588 }
2589 }
2590
2591 if (d.has("show_origin")) {
2592 bool use = d["show_origin"];
2593
2594 if (use != view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN))) {
2595 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN), use);
2596 VisualServer::get_singleton()->instance_geometry_set_flag(origin_instance, VS::INSTANCE_FLAG_VISIBLE, use);
2597 }
2598 }
2599
2600 if (d.has("deflight_rot_x"))
2601 settings_default_light_rot_x = d["deflight_rot_x"];
2602 if (d.has("deflight_rot_y"))
2603 settings_default_light_rot_y = d["deflight_rot_y"];
2604
2605 _update_default_light_angle();
2606 }
2607
edit(Spatial * p_spatial)2608 void SpatialEditor::edit(Spatial *p_spatial) {
2609
2610 if (p_spatial != selected) {
2611 if (selected) {
2612
2613 Ref<SpatialEditorGizmo> seg = selected->get_gizmo();
2614 if (seg.is_valid()) {
2615 seg->set_selected(false);
2616 selected->update_gizmo();
2617 }
2618 }
2619
2620 selected = p_spatial;
2621 over_gizmo_handle = -1;
2622
2623 if (selected) {
2624
2625 Ref<SpatialEditorGizmo> seg = selected->get_gizmo();
2626 if (seg.is_valid()) {
2627 seg->set_selected(true);
2628 selected->update_gizmo();
2629 }
2630 }
2631 }
2632
2633 if (p_spatial) {
2634 //_validate_selection();
2635 //if (selected.has(p_spatial->get_instance_ID()) && selected.size()==1)
2636 // return;
2637 //_select(p_spatial->get_instance_ID(),false,true);
2638
2639 // should become the selection
2640 }
2641 }
2642
_xform_dialog_action()2643 void SpatialEditor::_xform_dialog_action() {
2644
2645 Transform t;
2646 //translation
2647 Vector3 scale;
2648 Vector3 rotate;
2649 Vector3 translate;
2650
2651 for (int i = 0; i < 3; i++) {
2652 translate[i] = xform_translate[i]->get_text().to_double();
2653 rotate[i] = Math::deg2rad(xform_rotate[i]->get_text().to_double());
2654 scale[i] = xform_scale[i]->get_text().to_double();
2655 }
2656
2657 t.origin = translate;
2658 for (int i = 0; i < 3; i++) {
2659 if (!rotate[i])
2660 continue;
2661 Vector3 axis;
2662 axis[i] = 1.0;
2663 t.basis.rotate(axis, rotate[i]);
2664 }
2665
2666 for (int i = 0; i < 3; i++) {
2667 if (scale[i] == 1)
2668 continue;
2669 t.basis.set_axis(i, t.basis.get_axis(i) * scale[i]);
2670 }
2671
2672 undo_redo->create_action(TTR("XForm Dialog"));
2673
2674 List<Node *> &selection = editor_selection->get_selected_node_list();
2675
2676 for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
2677
2678 Spatial *sp = E->get()->cast_to<Spatial>();
2679 if (!sp)
2680 continue;
2681
2682 SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
2683 if (!se)
2684 continue;
2685
2686 bool post = xform_type->get_selected() > 0;
2687
2688 Transform tr = sp->get_global_transform();
2689 if (post)
2690 tr = tr * t;
2691 else {
2692
2693 tr.basis = t.basis * tr.basis;
2694 tr.origin += t.origin;
2695 }
2696
2697 undo_redo->add_do_method(sp, "set_global_transform", tr);
2698 undo_redo->add_undo_method(sp, "set_global_transform", sp->get_global_transform());
2699 }
2700 undo_redo->commit_action();
2701 }
2702
_menu_item_pressed(int p_option)2703 void SpatialEditor::_menu_item_pressed(int p_option) {
2704
2705 switch (p_option) {
2706
2707 case MENU_TOOL_SELECT:
2708 case MENU_TOOL_MOVE:
2709 case MENU_TOOL_ROTATE:
2710 case MENU_TOOL_SCALE:
2711 case MENU_TOOL_LIST_SELECT: {
2712
2713 for (int i = 0; i < TOOL_MAX; i++)
2714 tool_button[i]->set_pressed(i == p_option);
2715 tool_mode = (ToolMode)p_option;
2716
2717 // static const char *_mode[]={"Selection Mode.","Translation Mode.","Rotation Mode.","Scale Mode.","List Selection Mode."};
2718 // set_message(_mode[p_option],3);
2719 update_transform_gizmo();
2720
2721 } break;
2722 case MENU_TRANSFORM_USE_SNAP: {
2723
2724 bool is_checked = transform_menu->get_popup()->is_item_checked(transform_menu->get_popup()->get_item_index(p_option));
2725 snap_enabled = !is_checked;
2726 transform_menu->get_popup()->set_item_checked(transform_menu->get_popup()->get_item_index(p_option), snap_enabled);
2727 } break;
2728 case MENU_TRANSFORM_CONFIGURE_SNAP: {
2729
2730 snap_dialog->popup_centered(Size2(200, 180));
2731 } break;
2732 case MENU_TRANSFORM_LOCAL_COORDS: {
2733
2734 bool is_checked = transform_menu->get_popup()->is_item_checked(transform_menu->get_popup()->get_item_index(p_option));
2735 transform_menu->get_popup()->set_item_checked(transform_menu->get_popup()->get_item_index(p_option), !is_checked);
2736 update_transform_gizmo();
2737
2738 } break;
2739 case MENU_TRANSFORM_DIALOG: {
2740
2741 for (int i = 0; i < 3; i++) {
2742
2743 xform_translate[i]->set_text("0");
2744 xform_rotate[i]->set_text("0");
2745 xform_scale[i]->set_text("1");
2746 }
2747
2748 xform_dialog->popup_centered(Size2(200, 200));
2749
2750 } break;
2751 case MENU_VIEW_USE_DEFAULT_LIGHT: {
2752
2753 bool is_checked = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(p_option));
2754
2755 if (is_checked) {
2756 VisualServer::get_singleton()->free(light_instance);
2757 light_instance = RID();
2758 } else {
2759 light_instance = VisualServer::get_singleton()->instance_create2(light, get_tree()->get_root()->get_world()->get_scenario());
2760 VisualServer::get_singleton()->instance_set_transform(light_instance, light_transform);
2761
2762 _update_default_light_angle();
2763 }
2764
2765 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(p_option), light_instance.is_valid());
2766
2767 } break;
2768 case MENU_VIEW_USE_DEFAULT_SRGB: {
2769
2770 bool is_checked = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(p_option));
2771
2772 if (is_checked) {
2773 viewport_environment->set_enable_fx(Environment::FX_SRGB, false);
2774 } else {
2775 viewport_environment->set_enable_fx(Environment::FX_SRGB, true);
2776 }
2777
2778 is_checked = !is_checked;
2779
2780 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(p_option), is_checked);
2781
2782 } break;
2783 case MENU_VIEW_USE_1_VIEWPORT: {
2784
2785 for (int i = 1; i < 4; i++) {
2786
2787 viewports[i]->hide();
2788 }
2789
2790 viewports[0]->set_area_as_parent_rect();
2791
2792 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), true);
2793 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false);
2794 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false);
2795 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false);
2796 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false);
2797 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false);
2798
2799 } break;
2800 case MENU_VIEW_USE_2_VIEWPORTS: {
2801
2802 for (int i = 1; i < 4; i++) {
2803
2804 if (i == 1 || i == 3)
2805 viewports[i]->hide();
2806 else
2807 viewports[i]->show();
2808 }
2809 viewports[0]->set_area_as_parent_rect();
2810 viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_RATIO, 0.5);
2811 viewports[2]->set_area_as_parent_rect();
2812 viewports[2]->set_anchor_and_margin(MARGIN_TOP, ANCHOR_RATIO, 0.5);
2813
2814 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false);
2815 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), true);
2816 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false);
2817 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false);
2818 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false);
2819 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false);
2820
2821 } break;
2822 case MENU_VIEW_USE_2_VIEWPORTS_ALT: {
2823
2824 for (int i = 1; i < 4; i++) {
2825
2826 if (i == 1 || i == 3)
2827 viewports[i]->hide();
2828 else
2829 viewports[i]->show();
2830 }
2831 viewports[0]->set_area_as_parent_rect();
2832 viewports[0]->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_RATIO, 0.5);
2833 viewports[2]->set_area_as_parent_rect();
2834 viewports[2]->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.5);
2835
2836 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false);
2837 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false);
2838 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false);
2839 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false);
2840 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), true);
2841 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false);
2842
2843 } break;
2844 case MENU_VIEW_USE_3_VIEWPORTS: {
2845
2846 for (int i = 1; i < 4; i++) {
2847
2848 if (i == 1)
2849 viewports[i]->hide();
2850 else
2851 viewports[i]->show();
2852 }
2853 viewports[0]->set_area_as_parent_rect();
2854 viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_RATIO, 0.5);
2855 viewports[2]->set_area_as_parent_rect();
2856 viewports[2]->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_RATIO, 0.5);
2857 viewports[2]->set_anchor_and_margin(MARGIN_TOP, ANCHOR_RATIO, 0.5);
2858 viewports[3]->set_area_as_parent_rect();
2859 viewports[3]->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.5);
2860 viewports[3]->set_anchor_and_margin(MARGIN_TOP, ANCHOR_RATIO, 0.5);
2861
2862 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false);
2863 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false);
2864 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), true);
2865 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false);
2866 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false);
2867 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false);
2868
2869 } break;
2870 case MENU_VIEW_USE_3_VIEWPORTS_ALT: {
2871
2872 for (int i = 1; i < 4; i++) {
2873
2874 if (i == 1)
2875 viewports[i]->hide();
2876 else
2877 viewports[i]->show();
2878 }
2879 viewports[0]->set_area_as_parent_rect();
2880 viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_RATIO, 0.5);
2881 viewports[0]->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_RATIO, 0.5);
2882 viewports[2]->set_area_as_parent_rect();
2883 viewports[2]->set_anchor_and_margin(MARGIN_TOP, ANCHOR_RATIO, 0.5);
2884 viewports[2]->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_RATIO, 0.5);
2885 viewports[3]->set_area_as_parent_rect();
2886 viewports[3]->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.5);
2887
2888 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false);
2889 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false);
2890 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false);
2891 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false);
2892 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false);
2893 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), true);
2894
2895 } break;
2896 case MENU_VIEW_USE_4_VIEWPORTS: {
2897
2898 for (int i = 1; i < 4; i++) {
2899
2900 viewports[i]->show();
2901 }
2902 viewports[0]->set_area_as_parent_rect();
2903 viewports[0]->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_RATIO, 0.5);
2904 viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_RATIO, 0.5);
2905 viewports[1]->set_area_as_parent_rect();
2906 viewports[1]->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.5);
2907 viewports[1]->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_RATIO, 0.5);
2908 viewports[2]->set_area_as_parent_rect();
2909 viewports[2]->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_RATIO, 0.5);
2910 viewports[2]->set_anchor_and_margin(MARGIN_TOP, ANCHOR_RATIO, 0.5);
2911 viewports[3]->set_area_as_parent_rect();
2912 viewports[3]->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_RATIO, 0.5);
2913 viewports[3]->set_anchor_and_margin(MARGIN_TOP, ANCHOR_RATIO, 0.5);
2914
2915 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false);
2916 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false);
2917 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false);
2918 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), true);
2919 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false);
2920 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false);
2921
2922 } break;
2923 case MENU_VIEW_DISPLAY_NORMAL: {
2924
2925 VisualServer::get_singleton()->scenario_set_debug(get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_DISABLED);
2926
2927 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), true);
2928 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false);
2929 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false);
2930 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false);
2931
2932 } break;
2933 case MENU_VIEW_DISPLAY_WIREFRAME: {
2934
2935 VisualServer::get_singleton()->scenario_set_debug(get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_WIREFRAME);
2936 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false);
2937 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), true);
2938 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false);
2939 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false);
2940
2941 } break;
2942 case MENU_VIEW_DISPLAY_OVERDRAW: {
2943
2944 VisualServer::get_singleton()->scenario_set_debug(get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_OVERDRAW);
2945 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false);
2946 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false);
2947 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), true);
2948 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false);
2949
2950 } break;
2951 case MENU_VIEW_DISPLAY_SHADELESS: {
2952
2953 VisualServer::get_singleton()->scenario_set_debug(get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_SHADELESS);
2954 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false);
2955 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false);
2956 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false);
2957 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), true);
2958
2959 } break;
2960 case MENU_VIEW_ORIGIN: {
2961
2962 bool is_checked = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(p_option));
2963
2964 is_checked = !is_checked;
2965 VisualServer::get_singleton()->instance_geometry_set_flag(origin_instance, VS::INSTANCE_FLAG_VISIBLE, is_checked);
2966
2967 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(p_option), is_checked);
2968 } break;
2969 case MENU_VIEW_GRID: {
2970
2971 bool is_checked = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(p_option));
2972
2973 grid_enabled = !is_checked;
2974
2975 for (int i = 0; i < 3; ++i) {
2976 if (grid_enable[i]) {
2977 VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i], VS::INSTANCE_FLAG_VISIBLE, grid_enabled);
2978 grid_visible[i] = grid_enabled;
2979 }
2980 }
2981
2982 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(p_option), grid_enabled);
2983
2984 } break;
2985 case MENU_VIEW_CAMERA_SETTINGS: {
2986
2987 settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50));
2988 } break;
2989 }
2990 }
2991
_init_indicators()2992 void SpatialEditor::_init_indicators() {
2993
2994 //make sure that the camera indicator is not selectable
2995 light = VisualServer::get_singleton()->light_create(VisualServer::LIGHT_DIRECTIONAL);
2996 //VisualServer::get_singleton()->light_set_shadow( light, true );
2997 light_instance = VisualServer::get_singleton()->instance_create2(light, get_tree()->get_root()->get_world()->get_scenario());
2998
2999 light_transform.rotate(Vector3(1, 0, 0), Math_PI / 5.0);
3000 VisualServer::get_singleton()->instance_set_transform(light_instance, light_transform);
3001
3002 //RID mat = VisualServer::get_singleton()->fixed_material_create();
3003 ///VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA,true);
3004 //VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true);
3005
3006 {
3007
3008 indicator_mat = VisualServer::get_singleton()->fixed_material_create();
3009 VisualServer::get_singleton()->material_set_flag(indicator_mat, VisualServer::MATERIAL_FLAG_UNSHADED, true);
3010 VisualServer::get_singleton()->material_set_flag(indicator_mat, VisualServer::MATERIAL_FLAG_ONTOP, false);
3011 VisualServer::get_singleton()->fixed_material_set_flag(indicator_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true);
3012 VisualServer::get_singleton()->fixed_material_set_flag(indicator_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, true);
3013
3014 DVector<Color> grid_colors[3];
3015 DVector<Vector3> grid_points[3];
3016 Vector<Color> origin_colors;
3017 Vector<Vector3> origin_points;
3018
3019 Color grid_color = EditorSettings::get_singleton()->get("3d_editor/grid_color");
3020
3021 for (int i = 0; i < 3; i++) {
3022 Vector3 axis;
3023 axis[i] = 1;
3024 Vector3 axis_n1;
3025 axis_n1[(i + 1) % 3] = 1;
3026 Vector3 axis_n2;
3027 axis_n2[(i + 2) % 3] = 1;
3028
3029 origin_colors.push_back(Color(axis.x, axis.y, axis.z));
3030 origin_colors.push_back(Color(axis.x, axis.y, axis.z));
3031 origin_points.push_back(axis * 4096);
3032 origin_points.push_back(axis * -4096);
3033 #define ORIGIN_GRID_SIZE 25
3034
3035 for (int j = -ORIGIN_GRID_SIZE; j <= ORIGIN_GRID_SIZE; j++) {
3036
3037 grid_colors[i].push_back(grid_color);
3038 grid_colors[i].push_back(grid_color);
3039 grid_colors[i].push_back(grid_color);
3040 grid_colors[i].push_back(grid_color);
3041 grid_points[i].push_back(axis_n1 * ORIGIN_GRID_SIZE + axis_n2 * j);
3042 grid_points[i].push_back(-axis_n1 * ORIGIN_GRID_SIZE + axis_n2 * j);
3043 grid_points[i].push_back(axis_n2 * ORIGIN_GRID_SIZE + axis_n1 * j);
3044 grid_points[i].push_back(-axis_n2 * ORIGIN_GRID_SIZE + axis_n1 * j);
3045 }
3046
3047 grid[i] = VisualServer::get_singleton()->mesh_create();
3048 Array d;
3049 d.resize(VS::ARRAY_MAX);
3050 d[VisualServer::ARRAY_VERTEX] = grid_points[i];
3051 d[VisualServer::ARRAY_COLOR] = grid_colors[i];
3052 VisualServer::get_singleton()->mesh_add_surface(grid[i], VisualServer::PRIMITIVE_LINES, d);
3053 VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat);
3054 grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario());
3055
3056 grid_visible[i] = false;
3057 grid_enable[i] = false;
3058 VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i], VS::INSTANCE_FLAG_VISIBLE, false);
3059 VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
3060 VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << SpatialEditorViewport::GIZMO_GRID_LAYER);
3061 }
3062
3063 origin = VisualServer::get_singleton()->mesh_create();
3064 Array d;
3065 d.resize(VS::ARRAY_MAX);
3066 d[VisualServer::ARRAY_VERTEX] = origin_points;
3067 d[VisualServer::ARRAY_COLOR] = origin_colors;
3068
3069 VisualServer::get_singleton()->mesh_add_surface(origin, VisualServer::PRIMITIVE_LINES, d);
3070 VisualServer::get_singleton()->mesh_surface_set_material(origin, 0, indicator_mat);
3071
3072 // origin = VisualServer::get_singleton()->poly_create();
3073 // VisualServer::get_singleton()->poly_add_primitive(origin,origin_points,Vector<Vector3>(),origin_colors,Vector<Vector3>());
3074 // VisualServer::get_singleton()->poly_set_material(origin,indicator_mat,true);
3075 origin_instance = VisualServer::get_singleton()->instance_create2(origin, get_tree()->get_root()->get_world()->get_scenario());
3076 VS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << SpatialEditorViewport::GIZMO_GRID_LAYER);
3077
3078 VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, VS::SHADOW_CASTING_SETTING_OFF);
3079
3080 VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[1], VS::INSTANCE_FLAG_VISIBLE, true);
3081 grid_enable[1] = true;
3082 grid_visible[1] = true;
3083 grid_enabled = true;
3084 last_grid_snap = 1;
3085 }
3086
3087 {
3088 cursor_mesh = VisualServer::get_singleton()->mesh_create();
3089 DVector<Vector3> cursor_points;
3090 float cs = 0.25;
3091 cursor_points.push_back(Vector3(+cs, 0, 0));
3092 cursor_points.push_back(Vector3(-cs, 0, 0));
3093 cursor_points.push_back(Vector3(0, +cs, 0));
3094 cursor_points.push_back(Vector3(0, -cs, 0));
3095 cursor_points.push_back(Vector3(0, 0, +cs));
3096 cursor_points.push_back(Vector3(0, 0, -cs));
3097 cursor_material = VisualServer::get_singleton()->fixed_material_create();
3098 VisualServer::get_singleton()->fixed_material_set_param(cursor_material, VS::FIXED_MATERIAL_PARAM_DIFFUSE, Color(0, 1, 1));
3099 VisualServer::get_singleton()->material_set_flag(cursor_material, VisualServer::MATERIAL_FLAG_UNSHADED, true);
3100 VisualServer::get_singleton()->fixed_material_set_flag(cursor_material, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true);
3101 VisualServer::get_singleton()->fixed_material_set_flag(cursor_material, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, true);
3102
3103 Array d;
3104 d.resize(VS::ARRAY_MAX);
3105 d[VS::ARRAY_VERTEX] = cursor_points;
3106 VisualServer::get_singleton()->mesh_add_surface(cursor_mesh, VS::PRIMITIVE_LINES, d);
3107 VisualServer::get_singleton()->mesh_surface_set_material(cursor_mesh, 0, cursor_material);
3108
3109 cursor_instance = VisualServer::get_singleton()->instance_create2(cursor_mesh, get_tree()->get_root()->get_world()->get_scenario());
3110 VS::get_singleton()->instance_set_layer_mask(cursor_instance, 1 << SpatialEditorViewport::GIZMO_GRID_LAYER);
3111
3112 VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(cursor_instance, VS::SHADOW_CASTING_SETTING_OFF);
3113 }
3114
3115 {
3116
3117 //move gizmo
3118
3119 float gizmo_alph = EditorSettings::get_singleton()->get("3d_editor/manipulator_gizmo_opacity");
3120
3121 gizmo_hl = Ref<FixedMaterial>(memnew(FixedMaterial));
3122 gizmo_hl->set_flag(Material::FLAG_UNSHADED, true);
3123 gizmo_hl->set_flag(Material::FLAG_ONTOP, true);
3124 gizmo_hl->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
3125 gizmo_hl->set_parameter(FixedMaterial::PARAM_DIFFUSE, Color(1, 1, 1, gizmo_alph + 0.2f));
3126
3127 for (int i = 0; i < 3; i++) {
3128
3129 move_gizmo[i] = Ref<Mesh>(memnew(Mesh));
3130 rotate_gizmo[i] = Ref<Mesh>(memnew(Mesh));
3131
3132 Ref<FixedMaterial> mat = memnew(FixedMaterial);
3133 mat->set_flag(Material::FLAG_UNSHADED, true);
3134 mat->set_flag(Material::FLAG_ONTOP, true);
3135 mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
3136 Color col;
3137 col[i] = 1.0;
3138 col.a = gizmo_alph;
3139 mat->set_parameter(FixedMaterial::PARAM_DIFFUSE, col);
3140 gizmo_color[i] = mat;
3141
3142 Vector3 ivec;
3143 ivec[i] = 1;
3144 Vector3 nivec;
3145 nivec[(i + 1) % 3] = 1;
3146 nivec[(i + 2) % 3] = 1;
3147 Vector3 ivec2;
3148 ivec2[(i + 1) % 3] = 1;
3149 Vector3 ivec3;
3150 ivec3[(i + 2) % 3] = 1;
3151
3152 {
3153
3154 Ref<SurfaceTool> surftool = memnew(SurfaceTool);
3155 surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
3156
3157 //translate
3158
3159 const int arrow_points = 5;
3160 Vector3 arrow[5] = {
3161 nivec * 0.0 + ivec * 0.0,
3162 nivec * 0.01 + ivec * 0.0,
3163 nivec * 0.01 + ivec * 1.0,
3164 nivec * 0.1 + ivec * 1.0,
3165 nivec * 0.0 + ivec * (1 + GIZMO_ARROW_SIZE),
3166 };
3167
3168 int arrow_sides = 6;
3169
3170 for (int k = 0; k < 7; k++) {
3171
3172 Matrix3 ma(ivec, Math_PI * 2 * float(k) / arrow_sides);
3173 Matrix3 mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides);
3174
3175 for (int j = 0; j < arrow_points - 1; j++) {
3176
3177 Vector3 points[4] = {
3178 ma.xform(arrow[j]),
3179 mb.xform(arrow[j]),
3180 mb.xform(arrow[j + 1]),
3181 ma.xform(arrow[j + 1]),
3182 };
3183 surftool->add_vertex(points[0]);
3184 surftool->add_vertex(points[1]);
3185 surftool->add_vertex(points[2]);
3186
3187 surftool->add_vertex(points[0]);
3188 surftool->add_vertex(points[2]);
3189 surftool->add_vertex(points[3]);
3190 }
3191 }
3192
3193 surftool->set_material(mat);
3194 surftool->commit(move_gizmo[i]);
3195 }
3196
3197 {
3198
3199 Ref<SurfaceTool> surftool = memnew(SurfaceTool);
3200 surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
3201
3202 Vector3 circle[5] = {
3203 ivec * 0.02 + ivec2 * 0.02 + ivec2 * 1.0,
3204 ivec * -0.02 + ivec2 * 0.02 + ivec2 * 1.0,
3205 ivec * -0.02 + ivec2 * -0.02 + ivec2 * 1.0,
3206 ivec * 0.02 + ivec2 * -0.02 + ivec2 * 1.0,
3207 ivec * 0.02 + ivec2 * 0.02 + ivec2 * 1.0,
3208 };
3209
3210 for (int k = 0; k < 33; k++) {
3211
3212 Matrix3 ma(ivec, Math_PI * 2 * float(k) / 32);
3213 Matrix3 mb(ivec, Math_PI * 2 * float(k + 1) / 32);
3214
3215 for (int j = 0; j < 4; j++) {
3216
3217 Vector3 points[4] = {
3218 ma.xform(circle[j]),
3219 mb.xform(circle[j]),
3220 mb.xform(circle[j + 1]),
3221 ma.xform(circle[j + 1]),
3222 };
3223 surftool->add_vertex(points[0]);
3224 surftool->add_vertex(points[1]);
3225 surftool->add_vertex(points[2]);
3226
3227 surftool->add_vertex(points[0]);
3228 surftool->add_vertex(points[2]);
3229 surftool->add_vertex(points[3]);
3230 }
3231 }
3232
3233 surftool->set_material(mat);
3234 surftool->commit(rotate_gizmo[i]);
3235 }
3236 }
3237 }
3238
3239 /*for(int i=0;i<4;i++) {
3240
3241 viewports[i]->init_gizmo_instance(i);
3242 }*/
3243
3244 _generate_selection_box();
3245
3246 //get_scene()->get_root_node()->cast_to<EditorNode>()->get_scene_root()->add_child(camera);
3247
3248 //current_camera=camera;
3249 }
3250
_finish_indicators()3251 void SpatialEditor::_finish_indicators() {
3252
3253 VisualServer::get_singleton()->free(origin_instance);
3254 VisualServer::get_singleton()->free(origin);
3255 for (int i = 0; i < 3; i++) {
3256 VisualServer::get_singleton()->free(grid_instance[i]);
3257 VisualServer::get_singleton()->free(grid[i]);
3258 }
3259 VisualServer::get_singleton()->free(light_instance);
3260 VisualServer::get_singleton()->free(light);
3261 //VisualServer::get_singleton()->free(poly);
3262 //VisualServer::get_singleton()->free(indicators_instance);
3263 //VisualServer::get_singleton()->free(indicators);
3264
3265 VisualServer::get_singleton()->free(cursor_instance);
3266 VisualServer::get_singleton()->free(cursor_mesh);
3267 VisualServer::get_singleton()->free(indicator_mat);
3268 VisualServer::get_singleton()->free(cursor_material);
3269 }
3270
_instance_scene()3271 void SpatialEditor::_instance_scene() {
3272 #if 0
3273 EditorNode *en = get_scene()->get_root_node()->cast_to<EditorNode>();
3274 ERR_FAIL_COND(!en);
3275 String path = en->get_filesystem_dock()->get_selected_path();
3276 if (path=="") {
3277 set_message(TTR("No scene selected to instance!"));
3278 return;
3279 }
3280
3281 undo_redo->create_action(TTR("Instance at Cursor"));
3282
3283 Node* scene = en->request_instance_scene(path);
3284
3285 if (!scene) {
3286 set_message(TTR("Could not instance scene!"));
3287 undo_redo->commit_action(); //bleh
3288 return;
3289 }
3290
3291 Spatial *s = scene->cast_to<Spatial>();
3292 if (s) {
3293
3294 undo_redo->add_do_method(s,"set_global_transform",Transform(Matrix3(),cursor.cursor_pos));
3295 }
3296
3297 undo_redo->commit_action();
3298 #endif
3299 }
3300
_unhandled_key_input(InputEvent p_event)3301 void SpatialEditor::_unhandled_key_input(InputEvent p_event) {
3302
3303 if (!is_visible() || get_viewport()->gui_has_modal_stack())
3304 return;
3305
3306 {
3307
3308 EditorNode *en = editor;
3309 EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
3310
3311 if (!over_plugin_list->empty() && over_plugin_list->forward_input_event(p_event)) {
3312
3313 return; //ate the over input event
3314 }
3315 }
3316
3317 switch (p_event.type) {
3318
3319 case InputEvent::KEY: {
3320
3321 const InputEventKey &k = p_event.key;
3322
3323 if (!k.pressed)
3324 break;
3325
3326 switch (k.scancode) {
3327
3328 case KEY_Q: _menu_item_pressed(MENU_TOOL_SELECT); break;
3329 case KEY_W: _menu_item_pressed(MENU_TOOL_MOVE); break;
3330 case KEY_E: _menu_item_pressed(MENU_TOOL_ROTATE); break;
3331 case KEY_R: _menu_item_pressed(MENU_TOOL_SCALE); break;
3332
3333 case KEY_Z: {
3334 if (k.mod.shift || k.mod.control || k.mod.command)
3335 break;
3336
3337 if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME))) {
3338 _menu_item_pressed(MENU_VIEW_DISPLAY_NORMAL);
3339 } else {
3340 _menu_item_pressed(MENU_VIEW_DISPLAY_WIREFRAME);
3341 }
3342 } break;
3343
3344 #if 0
3345 #endif
3346 }
3347
3348 } break;
3349 }
3350 }
_notification(int p_what)3351 void SpatialEditor::_notification(int p_what) {
3352
3353 if (p_what == NOTIFICATION_READY) {
3354
3355 tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons"));
3356 tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon(get_icon("ToolMove", "EditorIcons"));
3357 tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons"));
3358 tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons"));
3359 tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_icon("ListSelect", "EditorIcons"));
3360 instance_button->set_icon(get_icon("SpatialAdd", "EditorIcons"));
3361 instance_button->hide();
3362
3363 view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_icon("Panels1", "EditorIcons"));
3364 view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_icon("Panels2", "EditorIcons"));
3365 view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_icon("Panels2Alt", "EditorIcons"));
3366 view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_icon("Panels3", "EditorIcons"));
3367 view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_icon("Panels3Alt", "EditorIcons"));
3368 view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_icon("Panels4", "EditorIcons"));
3369
3370 _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
3371
3372 get_tree()->connect("node_removed", this, "_node_removed");
3373 VS::get_singleton()->scenario_set_fallback_environment(get_viewport()->find_world()->get_scenario(), viewport_environment->get_rid());
3374 }
3375
3376 if (p_what == NOTIFICATION_ENTER_TREE) {
3377
3378 gizmos = memnew(SpatialEditorGizmos);
3379 _init_indicators();
3380 _update_default_light_angle();
3381 }
3382
3383 if (p_what == NOTIFICATION_EXIT_TREE) {
3384
3385 _finish_indicators();
3386 memdelete(gizmos);
3387 }
3388 }
3389
add_control_to_menu_panel(Control * p_control)3390 void SpatialEditor::add_control_to_menu_panel(Control *p_control) {
3391
3392 hbc_menu->add_child(p_control);
3393 }
3394
set_can_preview(Camera * p_preview)3395 void SpatialEditor::set_can_preview(Camera *p_preview) {
3396
3397 for (int i = 0; i < 4; i++) {
3398 viewports[i]->set_can_preview(p_preview);
3399 }
3400 }
3401
get_shader_split()3402 VSplitContainer *SpatialEditor::get_shader_split() {
3403
3404 return shader_split;
3405 }
3406
get_palette_split()3407 HSplitContainer *SpatialEditor::get_palette_split() {
3408
3409 return palette_split;
3410 }
3411
_request_gizmo(Object * p_obj)3412 void SpatialEditor::_request_gizmo(Object *p_obj) {
3413
3414 Spatial *sp = p_obj->cast_to<Spatial>();
3415 if (!sp)
3416 return;
3417 if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || sp->get_owner() == editor->get_edited_scene() || editor->get_edited_scene()->is_editable_instance(sp->get_owner()))) {
3418
3419 Ref<SpatialEditorGizmo> seg;
3420
3421 for (int i = 0; i < EditorNode::get_singleton()->get_editor_data().get_editor_plugin_count(); i++) {
3422
3423 seg = EditorNode::get_singleton()->get_editor_data().get_editor_plugin(i)->create_spatial_gizmo(sp);
3424 if (seg.is_valid())
3425 break;
3426 }
3427
3428 if (!seg.is_valid()) {
3429 seg = gizmos->get_gizmo(sp);
3430 }
3431
3432 if (seg.is_valid()) {
3433 sp->set_gizmo(seg);
3434 }
3435
3436 if (seg.is_valid() && sp == selected) {
3437 seg->set_selected(true);
3438 selected->update_gizmo();
3439 }
3440 }
3441 }
3442
_toggle_maximize_view(Object * p_viewport)3443 void SpatialEditor::_toggle_maximize_view(Object *p_viewport) {
3444 if (!p_viewport) return;
3445 SpatialEditorViewport *current_viewport = p_viewport->cast_to<SpatialEditorViewport>();
3446 if (!current_viewport) return;
3447
3448 int index = -1;
3449 bool maximized = false;
3450 for (int i = 0; i < 4; i++) {
3451 if (viewports[i] == current_viewport) {
3452 index = i;
3453 if (current_viewport->get_global_rect() == viewport_base->get_global_rect())
3454 maximized = true;
3455 break;
3456 }
3457 }
3458 if (index == -1) return;
3459
3460 if (!maximized) {
3461
3462 for (int i = 0; i < 4; i++) {
3463 if (i == index)
3464 viewports[i]->set_area_as_parent_rect();
3465 else
3466 viewports[i]->hide();
3467 }
3468 } else {
3469
3470 for (int i = 0; i < 4; i++)
3471 viewports[i]->show();
3472
3473 if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT)))
3474 _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
3475 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS)))
3476 _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS);
3477 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT)))
3478 _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT);
3479 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS)))
3480 _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS);
3481 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT)))
3482 _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT);
3483 else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS)))
3484 _menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS);
3485 }
3486 }
3487
_node_removed(Node * p_node)3488 void SpatialEditor::_node_removed(Node *p_node) {
3489
3490 if (p_node == selected)
3491 selected = NULL;
3492 }
3493
_bind_methods()3494 void SpatialEditor::_bind_methods() {
3495
3496 // ObjectTypeDB::bind_method("_input_event",&SpatialEditor::_input_event);
3497 ObjectTypeDB::bind_method("_unhandled_key_input", &SpatialEditor::_unhandled_key_input);
3498 ObjectTypeDB::bind_method("_node_removed", &SpatialEditor::_node_removed);
3499 ObjectTypeDB::bind_method("_menu_item_pressed", &SpatialEditor::_menu_item_pressed);
3500 ObjectTypeDB::bind_method("_xform_dialog_action", &SpatialEditor::_xform_dialog_action);
3501 ObjectTypeDB::bind_method("_instance_scene", &SpatialEditor::_instance_scene);
3502 ObjectTypeDB::bind_method("_get_editor_data", &SpatialEditor::_get_editor_data);
3503 ObjectTypeDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo);
3504 ObjectTypeDB::bind_method("_default_light_angle_input", &SpatialEditor::_default_light_angle_input);
3505 ObjectTypeDB::bind_method("_update_ambient_light_color", &SpatialEditor::_update_ambient_light_color);
3506 ObjectTypeDB::bind_method("_toggle_maximize_view", &SpatialEditor::_toggle_maximize_view);
3507
3508 ADD_SIGNAL(MethodInfo("transform_key_request"));
3509 }
3510
clear()3511 void SpatialEditor::clear() {
3512
3513 settings_fov->set_val(EDITOR_DEF("3d_editor/default_fov", 55.0));
3514 settings_znear->set_val(EDITOR_DEF("3d_editor/default_z_near", 0.1));
3515 settings_zfar->set_val(EDITOR_DEF("3d_editor/default_z_far", 1500.0));
3516
3517 for (int i = 0; i < 4; i++) {
3518 viewports[i]->reset();
3519 }
3520
3521 _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
3522 _menu_item_pressed(MENU_VIEW_DISPLAY_NORMAL);
3523
3524 VisualServer::get_singleton()->instance_geometry_set_flag(origin_instance, VS::INSTANCE_FLAG_VISIBLE, true);
3525 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN), true);
3526 for (int i = 0; i < 3; ++i) {
3527 if (grid_enable[i]) {
3528 VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i], VS::INSTANCE_FLAG_VISIBLE, true);
3529 grid_visible[i] = true;
3530 }
3531 }
3532
3533 for (int i = 0; i < 4; i++) {
3534
3535 viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(SpatialEditorViewport::VIEW_AUDIO_LISTENER), i == 0);
3536 viewports[i]->viewport->set_as_audio_listener(i == 0);
3537 }
3538
3539 view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true);
3540
3541 settings_default_light_rot_x = Math_PI * 0.3;
3542 settings_default_light_rot_y = Math_PI * 0.2;
3543
3544 viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR, Color(0.15, 0.15, 0.15));
3545 settings_ambient_color->set_color(Color(0.15, 0.15, 0.15));
3546 if (!light_instance.is_valid())
3547 _menu_item_pressed(MENU_VIEW_USE_DEFAULT_LIGHT);
3548
3549 _update_default_light_angle();
3550 }
3551
_update_ambient_light_color(const Color & p_color)3552 void SpatialEditor::_update_ambient_light_color(const Color &p_color) {
3553
3554 viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR, settings_ambient_color->get_color());
3555 }
3556
_update_default_light_angle()3557 void SpatialEditor::_update_default_light_angle() {
3558
3559 Transform t;
3560 t.basis.rotate(Vector3(1, 0, 0), settings_default_light_rot_x);
3561 t.basis.rotate(Vector3(0, 1, 0), settings_default_light_rot_y);
3562 settings_dlight->set_transform(t);
3563 if (light_instance.is_valid()) {
3564 VS::get_singleton()->instance_set_transform(light_instance, t);
3565 }
3566 }
3567
_default_light_angle_input(const InputEvent & p_event)3568 void SpatialEditor::_default_light_angle_input(const InputEvent &p_event) {
3569
3570 if (p_event.type == InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask & (0x1 | 0x2 | 0x4)) {
3571
3572 settings_default_light_rot_y = Math::fposmod(settings_default_light_rot_y - p_event.mouse_motion.relative_x * 0.01, Math_PI * 2.0);
3573 settings_default_light_rot_x = Math::fposmod(settings_default_light_rot_x - p_event.mouse_motion.relative_y * 0.01, Math_PI * 2.0);
3574 _update_default_light_angle();
3575 }
3576 }
3577
SpatialEditor(EditorNode * p_editor)3578 SpatialEditor::SpatialEditor(EditorNode *p_editor) {
3579
3580 gizmo.visible = true;
3581 gizmo.scale = 1.0;
3582
3583 viewport_environment = Ref<Environment>(memnew(Environment));
3584 undo_redo = p_editor->get_undo_redo();
3585 VBoxContainer *vbc = this;
3586
3587 custom_camera = NULL;
3588 singleton = this;
3589 editor = p_editor;
3590 editor_selection = editor->get_editor_selection();
3591 editor_selection->add_editor_plugin(this);
3592
3593 snap_enabled = false;
3594 tool_mode = TOOL_MODE_SELECT;
3595
3596 //set_focus_mode(FOCUS_ALL);
3597
3598 hbc_menu = memnew(HBoxContainer);
3599 vbc->add_child(hbc_menu);
3600
3601 Vector<Variant> button_binds;
3602 button_binds.resize(1);
3603
3604 tool_button[TOOL_MODE_SELECT] = memnew(ToolButton);
3605 hbc_menu->add_child(tool_button[TOOL_MODE_SELECT]);
3606 tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true);
3607 tool_button[TOOL_MODE_SELECT]->set_flat(true);
3608 tool_button[TOOL_MODE_SELECT]->set_pressed(true);
3609 button_binds[0] = MENU_TOOL_SELECT;
3610 tool_button[TOOL_MODE_SELECT]->connect("pressed", this, "_menu_item_pressed", button_binds);
3611 tool_button[TOOL_MODE_SELECT]->set_tooltip("Select Mode (Q)\n" + keycode_get_string(KEY_MASK_CMD) + "Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection");
3612
3613 tool_button[TOOL_MODE_MOVE] = memnew(ToolButton);
3614
3615 hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]);
3616 tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true);
3617 tool_button[TOOL_MODE_MOVE]->set_flat(true);
3618 button_binds[0] = MENU_TOOL_MOVE;
3619 tool_button[TOOL_MODE_MOVE]->connect("pressed", this, "_menu_item_pressed", button_binds);
3620 tool_button[TOOL_MODE_MOVE]->set_tooltip(TTR("Move Mode (W)"));
3621
3622 tool_button[TOOL_MODE_ROTATE] = memnew(ToolButton);
3623 hbc_menu->add_child(tool_button[TOOL_MODE_ROTATE]);
3624 tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true);
3625 tool_button[TOOL_MODE_ROTATE]->set_flat(true);
3626 button_binds[0] = MENU_TOOL_ROTATE;
3627 tool_button[TOOL_MODE_ROTATE]->connect("pressed", this, "_menu_item_pressed", button_binds);
3628 tool_button[TOOL_MODE_ROTATE]->set_tooltip(TTR("Rotate Mode (E)"));
3629
3630 tool_button[TOOL_MODE_SCALE] = memnew(ToolButton);
3631 hbc_menu->add_child(tool_button[TOOL_MODE_SCALE]);
3632 tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true);
3633 tool_button[TOOL_MODE_SCALE]->set_flat(true);
3634 button_binds[0] = MENU_TOOL_SCALE;
3635 tool_button[TOOL_MODE_SCALE]->connect("pressed", this, "_menu_item_pressed", button_binds);
3636 tool_button[TOOL_MODE_SCALE]->set_tooltip(TTR("Scale Mode (R)"));
3637
3638 instance_button = memnew(Button);
3639 hbc_menu->add_child(instance_button);
3640 instance_button->set_flat(true);
3641 instance_button->connect("pressed", this, "_instance_scene");
3642 instance_button->hide();
3643
3644 VSeparator *vs = memnew(VSeparator);
3645 hbc_menu->add_child(vs);
3646
3647 tool_button[TOOL_MODE_LIST_SELECT] = memnew(ToolButton);
3648 hbc_menu->add_child(tool_button[TOOL_MODE_LIST_SELECT]);
3649 tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true);
3650 tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true);
3651 button_binds[0] = MENU_TOOL_LIST_SELECT;
3652 tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", this, "_menu_item_pressed", button_binds);
3653 tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
3654
3655 vs = memnew(VSeparator);
3656 hbc_menu->add_child(vs);
3657
3658 ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KEY_MASK_ALT + KEY_KP_7);
3659 ED_SHORTCUT("spatial_editor/top_view", TTR("Top View"), KEY_KP_7);
3660 ED_SHORTCUT("spatial_editor/rear_view", TTR("Rear View"), KEY_MASK_ALT + KEY_KP_1);
3661 ED_SHORTCUT("spatial_editor/front_view", TTR("Front View"), KEY_KP_1);
3662 ED_SHORTCUT("spatial_editor/left_view", TTR("Left View"), KEY_MASK_ALT + KEY_KP_3);
3663 ED_SHORTCUT("spatial_editor/right_view", TTR("Right View"), KEY_KP_3);
3664 ED_SHORTCUT("spatial_editor/switch_perspective_orthogonal", TTR("Switch Perspective/Orthogonal view"), KEY_KP_5);
3665 ED_SHORTCUT("spatial_editor/snap", TTR("Snap"), KEY_S);
3666 ED_SHORTCUT("spatial_editor/insert_anim_key", TTR("Insert Animation Key"), KEY_K);
3667 ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), KEY_O);
3668 ED_SHORTCUT("spatial_editor/focus_selection", TTR("Focus Selection"), KEY_F);
3669 ED_SHORTCUT("spatial_editor/align_selection_with_view", TTR("Align Selection With View"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_F);
3670
3671 PopupMenu *p;
3672
3673 transform_menu = memnew(MenuButton);
3674 transform_menu->set_text(TTR("Transform"));
3675 hbc_menu->add_child(transform_menu);
3676
3677 p = transform_menu->get_popup();
3678 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_snap", TTR("Use Snap")), MENU_TRANSFORM_USE_SNAP);
3679 p->add_shortcut(ED_SHORTCUT("spatial_editor/configure_snap", TTR("Configure Snap..")), MENU_TRANSFORM_CONFIGURE_SNAP);
3680 p->add_separator();
3681 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Local Coords")), MENU_TRANSFORM_LOCAL_COORDS);
3682 //p->set_item_checked(p->get_item_count()-1,true);
3683 p->add_separator();
3684 p->add_shortcut(ED_SHORTCUT("spatial_editor/transform_dialog", TTR("Transform Dialog..")), MENU_TRANSFORM_DIALOG);
3685
3686 p->connect("item_pressed", this, "_menu_item_pressed");
3687
3688 view_menu = memnew(MenuButton);
3689 view_menu->set_text(TTR("View"));
3690 view_menu->set_pos(Point2(212, 0));
3691 hbc_menu->add_child(view_menu);
3692
3693 p = view_menu->get_popup();
3694
3695 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_default_light", TTR("Use Default Light")), MENU_VIEW_USE_DEFAULT_LIGHT);
3696 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_default_srgb", TTR("Use Default sRGB")), MENU_VIEW_USE_DEFAULT_SRGB);
3697 p->add_separator();
3698
3699 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KEY_MASK_CMD + KEY_1), MENU_VIEW_USE_1_VIEWPORT);
3700 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS);
3701 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT);
3702 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"), KEY_MASK_CMD + KEY_3), MENU_VIEW_USE_3_VIEWPORTS);
3703 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT);
3704 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KEY_MASK_CMD + KEY_4), MENU_VIEW_USE_4_VIEWPORTS);
3705 p->add_separator();
3706
3707 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_normal", TTR("Display Normal")), MENU_VIEW_DISPLAY_NORMAL);
3708 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_wireframe", TTR("Display Wireframe")), MENU_VIEW_DISPLAY_WIREFRAME);
3709 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_overdraw", TTR("Display Overdraw")), MENU_VIEW_DISPLAY_OVERDRAW);
3710 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_shadeless", TTR("Display Shadeless")), MENU_VIEW_DISPLAY_SHADELESS);
3711 p->add_separator();
3712 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN);
3713 p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid")), MENU_VIEW_GRID);
3714 p->add_separator();
3715 p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings")), MENU_VIEW_CAMERA_SETTINGS);
3716
3717 p->set_item_checked(p->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT), true);
3718 p->set_item_checked(p->get_item_index(MENU_VIEW_DISPLAY_NORMAL), true);
3719 p->set_item_checked(p->get_item_index(MENU_VIEW_ORIGIN), true);
3720 p->set_item_checked(p->get_item_index(MENU_VIEW_GRID), true);
3721
3722 p->connect("item_pressed", this, "_menu_item_pressed");
3723
3724 /* REST OF MENU */
3725
3726 palette_split = memnew(HSplitContainer);
3727 palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
3728 vbc->add_child(palette_split);
3729
3730 shader_split = memnew(VSplitContainer);
3731 shader_split->set_h_size_flags(SIZE_EXPAND_FILL);
3732 palette_split->add_child(shader_split);
3733 viewport_base = memnew(Control);
3734 shader_split->add_child(viewport_base);
3735 viewport_base->set_v_size_flags(SIZE_EXPAND_FILL);
3736 for (int i = 0; i < 4; i++) {
3737
3738 viewports[i] = memnew(SpatialEditorViewport(this, editor, i));
3739 viewports[i]->connect("toggle_maximize_view", this, "_toggle_maximize_view");
3740 viewport_base->add_child(viewports[i]);
3741 }
3742 //vbc->add_child(viewport_base);
3743
3744 /* SNAP DIALOG */
3745
3746 snap_dialog = memnew(ConfirmationDialog);
3747 snap_dialog->set_title(TTR("Snap Settings"));
3748 add_child(snap_dialog);
3749
3750 VBoxContainer *snap_dialog_vbc = memnew(VBoxContainer);
3751 snap_dialog->add_child(snap_dialog_vbc);
3752 snap_dialog->set_child_rect(snap_dialog_vbc);
3753
3754 snap_translate = memnew(LineEdit);
3755 snap_translate->set_text("1");
3756 snap_dialog_vbc->add_margin_child(TTR("Translate Snap:"), snap_translate);
3757
3758 snap_rotate = memnew(LineEdit);
3759 snap_rotate->set_text("5");
3760 snap_dialog_vbc->add_margin_child(TTR("Rotate Snap (deg.):"), snap_rotate);
3761
3762 snap_scale = memnew(LineEdit);
3763 snap_scale->set_text("5");
3764 snap_dialog_vbc->add_margin_child(TTR("Scale Snap (%):"), snap_scale);
3765
3766 /* SETTINGS DIALOG */
3767
3768 settings_dialog = memnew(ConfirmationDialog);
3769 settings_dialog->set_title(TTR("Viewport Settings"));
3770 add_child(settings_dialog);
3771 settings_vbc = memnew(VBoxContainer);
3772 settings_vbc->set_custom_minimum_size(Size2(200, 0));
3773 settings_dialog->add_child(settings_vbc);
3774 settings_dialog->set_child_rect(settings_vbc);
3775
3776 settings_light_base = memnew(Control);
3777 settings_light_base->set_custom_minimum_size(Size2(128, 128));
3778 settings_light_base->connect("input_event", this, "_default_light_angle_input");
3779 settings_vbc->add_margin_child(TTR("Default Light Normal:"), settings_light_base);
3780 settings_light_vp = memnew(Viewport);
3781 settings_light_vp->set_disable_input(true);
3782 settings_light_vp->set_use_own_world(true);
3783 settings_light_base->add_child(settings_light_vp);
3784
3785 settings_dlight = memnew(DirectionalLight);
3786 settings_light_vp->add_child(settings_dlight);
3787 settings_sphere = memnew(ImmediateGeometry);
3788 settings_sphere->begin(Mesh::PRIMITIVE_TRIANGLES, Ref<Texture>());
3789 settings_sphere->set_color(Color(1, 1, 1));
3790 settings_sphere->add_sphere(32, 16, 1);
3791 settings_sphere->end();
3792 settings_light_vp->add_child(settings_sphere);
3793 settings_camera = memnew(Camera);
3794 settings_light_vp->add_child(settings_camera);
3795 settings_camera->set_translation(Vector3(0, 0, 2));
3796 settings_camera->set_orthogonal(2.1, 0.1, 5);
3797
3798 settings_default_light_rot_x = Math_PI * 0.3;
3799 settings_default_light_rot_y = Math_PI * 0.2;
3800
3801 settings_ambient_color = memnew(ColorPickerButton);
3802 settings_vbc->add_margin_child(TTR("Ambient Light Color:"), settings_ambient_color);
3803 settings_ambient_color->connect("color_changed", this, "_update_ambient_light_color");
3804
3805 viewport_environment->set_enable_fx(Environment::FX_AMBIENT_LIGHT, true);
3806 viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR, Color(0.15, 0.15, 0.15));
3807 settings_ambient_color->set_color(Color(0.15, 0.15, 0.15));
3808
3809 settings_fov = memnew(SpinBox);
3810 settings_fov->set_max(179);
3811 settings_fov->set_min(1);
3812 settings_fov->set_step(0.01);
3813 settings_fov->set_val(EDITOR_DEF("3d_editor/default_fov", 55.0));
3814 settings_vbc->add_margin_child(TTR("Perspective FOV (deg.):"), settings_fov);
3815
3816 settings_znear = memnew(SpinBox);
3817 settings_znear->set_max(10000);
3818 settings_znear->set_min(0.1);
3819 settings_znear->set_step(0.01);
3820 settings_znear->set_val(EDITOR_DEF("3d_editor/default_z_near", 0.1));
3821 settings_vbc->add_margin_child(TTR("View Z-Near:"), settings_znear);
3822
3823 settings_zfar = memnew(SpinBox);
3824 settings_zfar->set_max(10000);
3825 settings_zfar->set_min(0.1);
3826 settings_zfar->set_step(0.01);
3827 settings_zfar->set_val(EDITOR_DEF("3d_editor/default_z_far", 1500));
3828 settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar);
3829
3830 //settings_dialog->get_cancel()->hide();
3831 /* XFORM DIALOG */
3832
3833 xform_dialog = memnew(ConfirmationDialog);
3834 xform_dialog->set_title(TTR("Transform Change"));
3835 add_child(xform_dialog);
3836 Label *l = memnew(Label);
3837 l->set_text(TTR("Translate:"));
3838 l->set_pos(Point2(5, 5));
3839 xform_dialog->add_child(l);
3840
3841 for (int i = 0; i < 3; i++) {
3842
3843 xform_translate[i] = memnew(LineEdit);
3844 xform_translate[i]->set_pos(Point2(15 + i * 60, 22));
3845 xform_translate[i]->set_size(Size2(50, 12));
3846 xform_dialog->add_child(xform_translate[i]);
3847 }
3848
3849 l = memnew(Label);
3850 l->set_text(TTR("Rotate (deg.):"));
3851 l->set_pos(Point2(5, 45));
3852 xform_dialog->add_child(l);
3853
3854 for (int i = 0; i < 3; i++) {
3855 xform_rotate[i] = memnew(LineEdit);
3856 xform_rotate[i]->set_pos(Point2(15 + i * 60, 62));
3857 xform_rotate[i]->set_size(Size2(50, 22));
3858 xform_dialog->add_child(xform_rotate[i]);
3859 }
3860
3861 l = memnew(Label);
3862 l->set_text(TTR("Scale (ratio):"));
3863 l->set_pos(Point2(5, 85));
3864 xform_dialog->add_child(l);
3865
3866 for (int i = 0; i < 3; i++) {
3867 xform_scale[i] = memnew(LineEdit);
3868 xform_scale[i]->set_pos(Point2(15 + i * 60, 102));
3869 xform_scale[i]->set_size(Size2(50, 22));
3870 xform_dialog->add_child(xform_scale[i]);
3871 }
3872
3873 l = memnew(Label);
3874 l->set_text(TTR("Transform Type"));
3875 l->set_pos(Point2(5, 125));
3876 xform_dialog->add_child(l);
3877
3878 xform_type = memnew(OptionButton);
3879 xform_type->set_anchor(MARGIN_RIGHT, ANCHOR_END);
3880 xform_type->set_begin(Point2(15, 142));
3881 xform_type->set_end(Point2(15, 75));
3882 xform_type->add_item(TTR("Pre"));
3883 xform_type->add_item(TTR("Post"));
3884 xform_dialog->add_child(xform_type);
3885
3886 xform_dialog->connect("confirmed", this, "_xform_dialog_action");
3887
3888 scenario_debug = VisualServer::SCENARIO_DEBUG_DISABLED;
3889
3890 selected = NULL;
3891
3892 set_process_unhandled_key_input(true);
3893 add_to_group("_spatial_editor_group");
3894
3895 EDITOR_DEF("3d_editor/manipulator_gizmo_size", 80);
3896 EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "3d_editor/manipulator_gizmo_size", PROPERTY_HINT_RANGE, "16,1024,1"));
3897 EDITOR_DEF("3d_editor/manipulator_gizmo_opacity", 0.2);
3898
3899 over_gizmo_handle = -1;
3900 }
3901
~SpatialEditor()3902 SpatialEditor::~SpatialEditor() {
3903 }
3904
make_visible(bool p_visible)3905 void SpatialEditorPlugin::make_visible(bool p_visible) {
3906
3907 if (p_visible) {
3908
3909 spatial_editor->show();
3910 spatial_editor->set_process(true);
3911 //VisualServer::get_singleton()->viewport_set_hide_scenario(editor->get_scene_root()->get_viewport(),false);
3912 spatial_editor->grab_focus();
3913
3914 } else {
3915
3916 spatial_editor->hide();
3917 spatial_editor->set_process(false);
3918 //VisualServer::get_singleton()->viewport_set_hide_scenario(editor->get_scene_root()->get_viewport(),true);
3919 }
3920 }
edit(Object * p_object)3921 void SpatialEditorPlugin::edit(Object *p_object) {
3922
3923 spatial_editor->edit(p_object->cast_to<Spatial>());
3924 }
3925
handles(Object * p_object) const3926 bool SpatialEditorPlugin::handles(Object *p_object) const {
3927
3928 return p_object->is_type("Spatial");
3929 }
3930
get_state() const3931 Dictionary SpatialEditorPlugin::get_state() const {
3932 return spatial_editor->get_state();
3933 }
3934
set_state(const Dictionary & p_state)3935 void SpatialEditorPlugin::set_state(const Dictionary &p_state) {
3936
3937 spatial_editor->set_state(p_state);
3938 }
3939
snap_cursor_to_plane(const Plane & p_plane)3940 void SpatialEditor::snap_cursor_to_plane(const Plane &p_plane) {
3941
3942 // cursor.pos=p_plane.project(cursor.pos);
3943 }
3944
_bind_methods()3945 void SpatialEditorPlugin::_bind_methods() {
3946
3947 ObjectTypeDB::bind_method("snap_cursor_to_plane", &SpatialEditorPlugin::snap_cursor_to_plane);
3948 }
3949
snap_cursor_to_plane(const Plane & p_plane)3950 void SpatialEditorPlugin::snap_cursor_to_plane(const Plane &p_plane) {
3951
3952 spatial_editor->snap_cursor_to_plane(p_plane);
3953 }
3954
SpatialEditorPlugin(EditorNode * p_node)3955 SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) {
3956
3957 editor = p_node;
3958 spatial_editor = memnew(SpatialEditor(p_node));
3959 spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
3960 editor->get_viewport()->add_child(spatial_editor);
3961
3962 //spatial_editor->set_area_as_parent_rect();
3963 spatial_editor->hide();
3964 spatial_editor->connect("transform_key_request", editor, "_transform_keyed");
3965
3966 //spatial_editor->set_process(true);
3967 }
3968
~SpatialEditorPlugin()3969 SpatialEditorPlugin::~SpatialEditorPlugin() {
3970 }
3971