1 /*************************************************************************/
2 /* grid_map_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 "grid_map_editor_plugin.h"
31 #include "editor/editor_settings.h"
32 #include "editor/plugins/spatial_editor_plugin.h"
33 #include "scene/3d/camera.h"
34
35 #include "geometry.h"
36 #include "os/keyboard.h"
37
_node_removed(Node * p_node)38 void GridMapEditor::_node_removed(Node *p_node) {
39
40 if (p_node == node) {
41 node = NULL;
42 hide();
43 theme_pallete->hide();
44 }
45 }
46
_configure()47 void GridMapEditor::_configure() {
48
49 if (!node)
50 return;
51
52 update_grid();
53 }
54
_menu_option(int p_option)55 void GridMapEditor::_menu_option(int p_option) {
56
57 switch (p_option) {
58
59 case MENU_OPTION_CONFIGURE: {
60
61 } break;
62 case MENU_OPTION_LOCK_VIEW: {
63
64 int index = options->get_popup()->get_item_index(MENU_OPTION_LOCK_VIEW);
65 lock_view = !options->get_popup()->is_item_checked(index);
66
67 options->get_popup()->set_item_checked(index, lock_view);
68 } break;
69 case MENU_OPTION_CLIP_DISABLED:
70 case MENU_OPTION_CLIP_ABOVE:
71 case MENU_OPTION_CLIP_BELOW: {
72
73 clip_mode = ClipMode(p_option - MENU_OPTION_CLIP_DISABLED);
74 for (int i = 0; i < 3; i++) {
75
76 int index = options->get_popup()->get_item_index(MENU_OPTION_CLIP_DISABLED + i);
77 options->get_popup()->set_item_checked(index, i == clip_mode);
78 }
79
80 _update_clip();
81 } break;
82 case MENU_OPTION_X_AXIS:
83 case MENU_OPTION_Y_AXIS:
84 case MENU_OPTION_Z_AXIS: {
85
86 int new_axis = p_option - MENU_OPTION_X_AXIS;
87 for (int i = 0; i < 3; i++) {
88 int idx = options->get_popup()->get_item_index(MENU_OPTION_X_AXIS + i);
89 options->get_popup()->set_item_checked(idx, i == new_axis);
90 }
91 edit_axis = Vector3::Axis(new_axis);
92 update_grid();
93 _update_clip();
94
95 } break;
96 case MENU_OPTION_CURSOR_ROTATE_Y: {
97 Matrix3 r;
98 if (input_action == INPUT_DUPLICATE) {
99
100 r.set_orthogonal_index(selection.duplicate_rot);
101 r.rotate(Vector3(0, 1, 0), Math_PI / 2.0);
102 selection.duplicate_rot = r.get_orthogonal_index();
103 _update_duplicate_indicator();
104 break;
105 }
106 r.set_orthogonal_index(cursor_rot);
107 r.rotate(Vector3(0, 1, 0), Math_PI / 2.0);
108 cursor_rot = r.get_orthogonal_index();
109 _update_cursor_transform();
110 } break;
111 case MENU_OPTION_CURSOR_ROTATE_X: {
112 Matrix3 r;
113 if (input_action == INPUT_DUPLICATE) {
114
115 r.set_orthogonal_index(selection.duplicate_rot);
116 r.rotate(Vector3(1, 0, 0), Math_PI / 2.0);
117 selection.duplicate_rot = r.get_orthogonal_index();
118 _update_duplicate_indicator();
119 break;
120 }
121
122 r.set_orthogonal_index(cursor_rot);
123 r.rotate(Vector3(1, 0, 0), Math_PI / 2.0);
124 cursor_rot = r.get_orthogonal_index();
125 _update_cursor_transform();
126 } break;
127 case MENU_OPTION_CURSOR_ROTATE_Z: {
128 Matrix3 r;
129 if (input_action == INPUT_DUPLICATE) {
130
131 r.set_orthogonal_index(selection.duplicate_rot);
132 r.rotate(Vector3(0, 0, 1), Math_PI / 2.0);
133 selection.duplicate_rot = r.get_orthogonal_index();
134 _update_duplicate_indicator();
135 break;
136 }
137
138 r.set_orthogonal_index(cursor_rot);
139 r.rotate(Vector3(0, 0, 1), Math_PI / 2.0);
140 cursor_rot = r.get_orthogonal_index();
141 _update_cursor_transform();
142 } break;
143 case MENU_OPTION_CURSOR_BACK_ROTATE_Y: {
144 Matrix3 r;
145 r.set_orthogonal_index(cursor_rot);
146 r.rotate(Vector3(0, 1, 0), -Math_PI / 2.0);
147 cursor_rot = r.get_orthogonal_index();
148 _update_cursor_transform();
149 } break;
150 case MENU_OPTION_CURSOR_BACK_ROTATE_X: {
151 Matrix3 r;
152 r.set_orthogonal_index(cursor_rot);
153 r.rotate(Vector3(1, 0, 0), -Math_PI / 2.0);
154 cursor_rot = r.get_orthogonal_index();
155 _update_cursor_transform();
156 } break;
157 case MENU_OPTION_CURSOR_BACK_ROTATE_Z: {
158 Matrix3 r;
159 r.set_orthogonal_index(cursor_rot);
160 r.rotate(Vector3(0, 0, 1), -Math_PI / 2.0);
161 cursor_rot = r.get_orthogonal_index();
162 _update_cursor_transform();
163 } break;
164 case MENU_OPTION_CURSOR_CLEAR_ROTATION: {
165
166 if (input_action == INPUT_DUPLICATE) {
167
168 selection.duplicate_rot = 0;
169 _update_duplicate_indicator();
170 break;
171 }
172
173 cursor_rot = 0;
174 _update_cursor_transform();
175 } break;
176
177 case MENU_OPTION_DUPLICATE_SELECTS: {
178 int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS);
179 options->get_popup()->set_item_checked(idx, !options->get_popup()->is_item_checked(idx));
180 } break;
181 case MENU_OPTION_SELECTION_MAKE_AREA:
182 case MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR: {
183
184 if (!selection.active)
185 break;
186 int area = node->get_unused_area_id();
187 Error err = node->create_area(area, AABB(selection.begin, selection.end - selection.begin + Vector3(1, 1, 1)));
188 if (err != OK) {
189 }
190 if (p_option == MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR) {
191
192 node->area_set_exterior_portal(area, true);
193 }
194 _update_areas_display();
195 update_areas();
196
197 } break;
198 case MENU_OPTION_REMOVE_AREA: {
199 if (selected_area < 1)
200 return;
201 node->erase_area(selected_area);
202 _update_areas_display();
203 update_areas();
204 } break;
205 case MENU_OPTION_SELECTION_DUPLICATE:
206 if (!(selection.active && input_action == INPUT_NONE))
207 return;
208 if (last_mouseover == Vector3(-1, -1, -1)) //nono mouseovering anythin
209 break;
210
211 input_action = INPUT_DUPLICATE;
212 selection.click = last_mouseover;
213 selection.current = last_mouseover;
214 selection.duplicate_rot = 0;
215 _update_duplicate_indicator();
216 break;
217 case MENU_OPTION_SELECTION_CLEAR: {
218 if (!selection.active)
219 return;
220
221 _delete_selection();
222
223 } break;
224 case MENU_OPTION_GRIDMAP_SETTINGS: {
225 settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50));
226 } break;
227 }
228 }
229
_update_cursor_transform()230 void GridMapEditor::_update_cursor_transform() {
231
232 cursor_transform = Transform();
233 cursor_transform.origin = cursor_origin;
234 cursor_transform.basis.set_orthogonal_index(cursor_rot);
235 cursor_transform = node->get_transform() * cursor_transform;
236
237 if (cursor_instance.is_valid()) {
238 VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform);
239 VisualServer::get_singleton()->instance_geometry_set_flag(cursor_instance, VS::INSTANCE_FLAG_VISIBLE, cursor_visible);
240 }
241 }
242
_update_selection_transform()243 void GridMapEditor::_update_selection_transform() {
244
245 if (!selection.active) {
246
247 Transform xf;
248 xf.basis.set_zero();
249 VisualServer::get_singleton()->instance_set_transform(selection_instance, xf);
250 return;
251 }
252
253 Transform xf;
254 xf.scale(Vector3(1, 1, 1) * (Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size());
255 xf.origin = selection.begin * node->get_cell_size();
256
257 VisualServer::get_singleton()->instance_set_transform(selection_instance, node->get_global_transform() * xf);
258 }
259
_validate_selection()260 void GridMapEditor::_validate_selection() {
261
262 if (!selection.active)
263 return;
264 selection.begin = selection.click;
265 selection.end = selection.current;
266
267 if (selection.begin.x > selection.end.x)
268 SWAP(selection.begin.x, selection.end.x);
269 if (selection.begin.y > selection.end.y)
270 SWAP(selection.begin.y, selection.end.y);
271 if (selection.begin.z > selection.end.z)
272 SWAP(selection.begin.z, selection.end.z);
273
274 _update_selection_transform();
275 }
276
do_input_action(Camera * p_camera,const Point2 & p_point,bool p_click)277 bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click) {
278
279 if (!spatial_editor)
280 return false;
281
282 if (selected_pallete < 0 && input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE)
283 return false;
284 Ref<MeshLibrary> theme = node->get_theme();
285 if (theme.is_null())
286 return false;
287 if (input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE && !theme->has_item(selected_pallete))
288 return false;
289
290 Camera *camera = p_camera;
291 Vector3 from = camera->project_ray_origin(p_point);
292 Vector3 normal = camera->project_ray_normal(p_point);
293 Transform local_xform = node->get_global_transform().affine_inverse();
294 Vector<Plane> planes = camera->get_frustum();
295 from = local_xform.xform(from);
296 normal = local_xform.basis.xform(normal).normalized();
297
298 Plane p;
299 p.normal[edit_axis] = 1.0;
300 p.d = edit_floor[edit_axis] * node->get_cell_size();
301
302 Vector3 inters;
303 if (!p.intersects_segment(from, from + normal * settings_pick_distance->get_val(), &inters))
304 return false;
305
306 //make sure the intersection is inside the frustum planes, to avoid
307 //painting on invisible regions
308 for (int i = 0; i < planes.size(); i++) {
309
310 Plane fp = local_xform.xform(planes[i]);
311 if (fp.is_point_over(inters))
312 return false;
313 }
314
315 int cell[3];
316 float cell_size[3] = { node->get_cell_size(), node->get_cell_size(), node->get_cell_size() };
317
318 last_mouseover = Vector3(-1, -1, -1);
319
320 for (int i = 0; i < 3; i++) {
321
322 if (i == edit_axis)
323 cell[i] = edit_floor[i];
324 else {
325
326 cell[i] = inters[i] / node->get_cell_size();
327 if (inters[i] < 0)
328 cell[i] -= 1; //compensate negative
329 grid_ofs[i] = cell[i] * cell_size[i];
330 }
331
332 /*if (cell[i]<0 || cell[i]>=grid_size[i]) {
333
334 cursor_visible=false;
335 _update_cursor_transform();
336 return false;
337 }*/
338 }
339
340 last_mouseover = Vector3(cell[0], cell[1], cell[2]);
341 VS::get_singleton()->instance_set_transform(grid_instance[edit_axis], Transform(Matrix3(), grid_ofs));
342
343 if (cursor_instance.is_valid()) {
344
345 cursor_origin = (Vector3(cell[0], cell[1], cell[2]) + Vector3(0.5 * node->get_center_x(), 0.5 * node->get_center_y(), 0.5 * node->get_center_z())) * node->get_cell_size();
346 cursor_visible = true;
347
348 _update_cursor_transform();
349 }
350
351 if (input_action == INPUT_DUPLICATE) {
352
353 selection.current = Vector3(cell[0], cell[1], cell[2]);
354 _update_duplicate_indicator();
355
356 } else if (input_action == INPUT_SELECT) {
357
358 selection.current = Vector3(cell[0], cell[1], cell[2]);
359 if (p_click)
360 selection.click = selection.current;
361 selection.active = true;
362 _validate_selection();
363
364 return true;
365 } else if (input_action == INPUT_COPY) {
366
367 int item = node->get_cell_item(cell[0], cell[1], cell[2]);
368 if (item >= 0) {
369 selected_pallete = item;
370 theme_pallete->set_current(item);
371 update_pallete();
372 _update_cursor_instance();
373 }
374 return true;
375 }
376 if (input_action == INPUT_PAINT) {
377 SetItem si;
378 si.pos = Vector3(cell[0], cell[1], cell[2]);
379 si.new_value = selected_pallete;
380 si.new_orientation = cursor_rot;
381 si.old_value = node->get_cell_item(cell[0], cell[1], cell[2]);
382 si.old_orientation = node->get_cell_item_orientation(cell[0], cell[1], cell[2]);
383 set_items.push_back(si);
384 node->set_cell_item(cell[0], cell[1], cell[2], selected_pallete, cursor_rot);
385 return true;
386 } else if (input_action == INPUT_ERASE) {
387 SetItem si;
388 si.pos = Vector3(cell[0], cell[1], cell[2]);
389 si.new_value = -1;
390 si.new_orientation = 0;
391 si.old_value = node->get_cell_item(cell[0], cell[1], cell[2]);
392 si.old_orientation = node->get_cell_item_orientation(cell[0], cell[1], cell[2]);
393 set_items.push_back(si);
394 node->set_cell_item(cell[0], cell[1], cell[2], -1);
395 return true;
396 }
397
398 return false;
399 }
400
_delete_selection()401 void GridMapEditor::_delete_selection() {
402
403 if (!selection.active)
404 return;
405
406 undo_redo->create_action("GridMap Delete Selection");
407 for (int i = selection.begin.x; i <= selection.end.x; i++) {
408
409 for (int j = selection.begin.y; j <= selection.end.y; j++) {
410
411 for (int k = selection.begin.z; k <= selection.end.z; k++) {
412
413 undo_redo->add_do_method(node, "set_cell_item", i, j, k, GridMap::INVALID_CELL_ITEM);
414 undo_redo->add_undo_method(node, "set_cell_item", i, j, k, node->get_cell_item(i, j, k), node->get_cell_item_orientation(i, j, k));
415 }
416 }
417 }
418 undo_redo->commit_action();
419
420 selection.active = false;
421 _validate_selection();
422 }
423
_update_duplicate_indicator()424 void GridMapEditor::_update_duplicate_indicator() {
425
426 if (!selection.active || input_action != INPUT_DUPLICATE) {
427
428 Transform xf;
429 xf.basis.set_zero();
430 VisualServer::get_singleton()->instance_set_transform(duplicate_instance, xf);
431 return;
432 }
433
434 Transform xf;
435 xf.scale(Vector3(1, 1, 1) * (Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size());
436 xf.origin = (selection.begin + (selection.current - selection.click)) * node->get_cell_size();
437 Matrix3 rot;
438 rot.set_orthogonal_index(selection.duplicate_rot);
439 xf.basis = rot * xf.basis;
440
441 VisualServer::get_singleton()->instance_set_transform(duplicate_instance, node->get_global_transform() * xf);
442 }
443
444 struct __Item {
445 Vector3 pos;
446 int rot;
447 int item;
448 };
_duplicate_paste()449 void GridMapEditor::_duplicate_paste() {
450
451 if (!selection.active)
452 return;
453
454 int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS);
455 bool reselect = options->get_popup()->is_item_checked(idx);
456
457 List<__Item> items;
458
459 Matrix3 rot;
460 rot.set_orthogonal_index(selection.duplicate_rot);
461
462 for (int i = selection.begin.x; i <= selection.end.x; i++) {
463
464 for (int j = selection.begin.y; j <= selection.end.y; j++) {
465
466 for (int k = selection.begin.z; k <= selection.end.z; k++) {
467
468 int itm = node->get_cell_item(i, j, k);
469 if (itm == GridMap::INVALID_CELL_ITEM)
470 continue;
471 int orientation = node->get_cell_item_orientation(i, j, k);
472 __Item item;
473 Vector3 rel = Vector3(i, j, k) - selection.begin;
474 rel = rot.xform(rel);
475
476 Matrix3 orm;
477 orm.set_orthogonal_index(orientation);
478 orm = rot * orm;
479
480 item.pos = selection.begin + rel;
481 item.item = itm;
482 item.rot = orm.get_orthogonal_index();
483 items.push_back(item);
484 }
485 }
486 }
487
488 Vector3 ofs = selection.current - selection.click;
489 if (items.size()) {
490 undo_redo->create_action("GridMap Duplicate Selection");
491 for (List<__Item>::Element *E = items.front(); E; E = E->next()) {
492 __Item &it = E->get();
493 Vector3 pos = it.pos + ofs;
494
495 undo_redo->add_do_method(node, "set_cell_item", pos.x, pos.y, pos.z, it.item, it.rot);
496 undo_redo->add_undo_method(node, "set_cell_item", pos.x, pos.y, pos.z, node->get_cell_item(pos.x, pos.y, pos.z), node->get_cell_item_orientation(pos.x, pos.y, pos.z));
497 }
498 undo_redo->commit_action();
499 }
500
501 if (reselect) {
502
503 selection.begin += ofs;
504 selection.end += ofs;
505 selection.click = selection.begin;
506 selection.current = selection.end;
507 _validate_selection();
508 }
509 }
510
forward_spatial_input_event(Camera * p_camera,const InputEvent & p_event)511 bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const InputEvent &p_event) {
512 if (!node) {
513 return false;
514 }
515
516 if (edit_mode->get_selected() == 0) { // regular click
517 switch (p_event.type) {
518 case InputEvent::MOUSE_BUTTON: {
519
520 if (p_event.mouse_button.button_index == BUTTON_WHEEL_UP && (p_event.mouse_button.mod.command || p_event.mouse_button.mod.shift)) {
521 if (p_event.mouse_button.pressed)
522 floor->set_val(floor->get_val() + p_event.mouse_button.factor);
523
524 return true; //eaten
525 } else if (p_event.mouse_button.button_index == BUTTON_WHEEL_DOWN && (p_event.mouse_button.mod.command || p_event.mouse_button.mod.shift)) {
526 if (p_event.mouse_button.pressed)
527 floor->set_val(floor->get_val() - p_event.mouse_button.factor);
528 return true;
529 }
530
531 if (p_event.mouse_button.pressed) {
532
533 if (p_event.mouse_button.button_index == BUTTON_LEFT) {
534
535 if (input_action == INPUT_DUPLICATE) {
536
537 //paste
538 _duplicate_paste();
539 input_action = INPUT_NONE;
540 _update_duplicate_indicator();
541 } else if (p_event.mouse_button.mod.shift) {
542 input_action = INPUT_SELECT;
543 } else if (p_event.mouse_button.mod.command)
544 input_action = INPUT_COPY;
545 else {
546 input_action = INPUT_PAINT;
547 set_items.clear();
548 }
549 } else if (p_event.mouse_button.button_index == BUTTON_RIGHT)
550 if (input_action == INPUT_DUPLICATE) {
551
552 input_action = INPUT_NONE;
553 _update_duplicate_indicator();
554 } else {
555 input_action = INPUT_ERASE;
556 set_items.clear();
557 }
558 else
559 return false;
560
561 return do_input_action(p_camera, Point2(p_event.mouse_button.x, p_event.mouse_button.y), true);
562 } else {
563
564 if (
565 (p_event.mouse_button.button_index == BUTTON_RIGHT && input_action == INPUT_ERASE) ||
566 (p_event.mouse_button.button_index == BUTTON_LEFT && input_action == INPUT_PAINT)) {
567
568 if (set_items.size()) {
569 undo_redo->create_action("GridMap Paint");
570 for (List<SetItem>::Element *E = set_items.front(); E; E = E->next()) {
571
572 const SetItem &si = E->get();
573 undo_redo->add_do_method(node, "set_cell_item", si.pos.x, si.pos.y, si.pos.z, si.new_value, si.new_orientation);
574 }
575 for (List<SetItem>::Element *E = set_items.back(); E; E = E->prev()) {
576
577 const SetItem &si = E->get();
578 undo_redo->add_undo_method(node, "set_cell_item", si.pos.x, si.pos.y, si.pos.z, si.old_value, si.old_orientation);
579 }
580
581 undo_redo->commit_action();
582 }
583 set_items.clear();
584 input_action = INPUT_NONE;
585 return true;
586 }
587
588 if (p_event.mouse_button.button_index == BUTTON_LEFT && input_action != INPUT_NONE) {
589
590 set_items.clear();
591 input_action = INPUT_NONE;
592 return true;
593 }
594 if (p_event.mouse_button.button_index == BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_DUPLICATE)) {
595 input_action = INPUT_NONE;
596 return true;
597 }
598 }
599 } break;
600 case InputEvent::MOUSE_MOTION: {
601
602 return do_input_action(p_camera, Point2(p_event.mouse_motion.x, p_event.mouse_motion.y), false);
603 } break;
604 }
605
606 } else if (edit_mode->get_selected() == 1) {
607 //area mode, select an area
608
609 switch (p_event.type) {
610 case InputEvent::MOUSE_BUTTON: {
611
612 if (p_event.mouse_button.button_index == BUTTON_LEFT && p_event.mouse_button.pressed) {
613
614 Point2 point = Point2(p_event.mouse_motion.x, p_event.mouse_motion.y);
615
616 Camera *camera = p_camera;
617 Vector3 from = camera->project_ray_origin(point);
618 Vector3 normal = camera->project_ray_normal(point);
619 Transform local_xform = node->get_global_transform().affine_inverse();
620 from = local_xform.xform(from);
621 normal = local_xform.basis.xform(normal).normalized();
622
623 List<int> areas;
624 node->get_area_list(&areas);
625
626 float min_d = 1e10;
627 int min_area = -1;
628
629 for (List<int>::Element *E = areas.front(); E; E = E->next()) {
630
631 int area = E->get();
632 AABB aabb = node->area_get_bounds(area);
633 aabb.pos *= node->get_cell_size();
634 aabb.size *= node->get_cell_size();
635
636 Vector3 rclip, rnormal;
637 if (!aabb.intersects_segment(from, from + normal * 10000, &rclip, &rnormal))
638 continue;
639
640 float d = normal.dot(rclip);
641 if (d < min_d) {
642 min_d = d;
643 min_area = area;
644 }
645 }
646
647 selected_area = min_area;
648 update_areas();
649 }
650 } break;
651 }
652 }
653
654 return false;
655 }
656
657 struct _CGMEItemSort {
658
659 String name;
660 int id;
operator <_CGMEItemSort661 _FORCE_INLINE_ bool operator<(const _CGMEItemSort &r_it) const { return name < r_it.name; }
662 };
663
_set_display_mode(int p_mode)664 void GridMapEditor::_set_display_mode(int p_mode) {
665 if (display_mode == p_mode) {
666 return;
667 }
668
669 if (p_mode == DISPLAY_LIST) {
670 mode_list->set_pressed(true);
671 mode_thumbnail->set_pressed(false);
672 } else if (p_mode == DISPLAY_THUMBNAIL) {
673 mode_list->set_pressed(false);
674 mode_thumbnail->set_pressed(true);
675 }
676
677 display_mode = p_mode;
678
679 update_pallete();
680 }
681
update_pallete()682 void GridMapEditor::update_pallete() {
683 int selected = theme_pallete->get_current();
684
685 theme_pallete->clear();
686 if (display_mode == DISPLAY_THUMBNAIL) {
687 theme_pallete->set_max_columns(0);
688 theme_pallete->set_icon_mode(ItemList::ICON_MODE_TOP);
689 } else if (display_mode == DISPLAY_LIST) {
690 theme_pallete->set_max_columns(1);
691 theme_pallete->set_icon_mode(ItemList::ICON_MODE_LEFT);
692 }
693
694 float min_size = EDITOR_DEF("grid_map/preview_size", 64);
695 theme_pallete->set_fixed_icon_size(Size2(min_size, min_size));
696 theme_pallete->set_fixed_column_width(min_size * 3 / 2);
697 theme_pallete->set_max_text_lines(2);
698
699 Ref<MeshLibrary> theme = node->get_theme();
700
701 if (theme.is_null()) {
702 last_theme = NULL;
703 return;
704 }
705
706 Vector<int> ids;
707 ids = theme->get_item_list();
708
709 List<_CGMEItemSort> il;
710 for (int i = 0; i < ids.size(); i++) {
711
712 _CGMEItemSort is;
713 is.id = ids[i];
714 is.name = theme->get_item_name(ids[i]);
715 il.push_back(is);
716 }
717 il.sort();
718
719 int item = 0;
720
721 for (List<_CGMEItemSort>::Element *E = il.front(); E; E = E->next()) {
722 int id = E->get().id;
723
724 theme_pallete->add_item("");
725
726 String name = theme->get_item_name(id);
727 Ref<Texture> preview = theme->get_item_preview(id);
728
729 if (!preview.is_null()) {
730 theme_pallete->set_item_icon(item, preview);
731 theme_pallete->set_item_tooltip(item, name);
732 }
733 if (name != "") {
734 theme_pallete->set_item_text(item, name);
735 }
736 theme_pallete->set_item_metadata(item, id);
737
738 item++;
739 }
740
741 if (selected != -1) {
742 theme_pallete->select(selected);
743 }
744
745 last_theme = theme.operator->();
746 }
747
_area_renamed()748 void GridMapEditor::_area_renamed() {
749
750 TreeItem *it = area_list->get_selected();
751 int area = it->get_metadata(0);
752 if (area < 1)
753 return;
754 node->area_set_name(area, it->get_text(0));
755 }
756
_area_selected()757 void GridMapEditor::_area_selected() {
758
759 TreeItem *it = area_list->get_selected();
760 int area = it->get_metadata(0);
761 if (area < 1)
762 return;
763 selected_area = area;
764 }
765
update_areas()766 void GridMapEditor::update_areas() {
767
768 area_list->clear();
769
770 List<int> areas;
771 node->get_area_list(&areas);
772
773 TreeItem *root = area_list->create_item(NULL);
774 area_list->set_hide_root(true);
775 TreeItem *selected = NULL;
776
777 for (List<int>::Element *E = areas.front(); E; E = E->next()) {
778
779 int area = E->get();
780 TreeItem *ti = area_list->create_item(root);
781 String name = node->area_get_name(area);
782
783 ti->set_metadata(0, area);
784 ti->set_text(0, name);
785 ti->set_editable(0, true);
786 if (area == selected_area)
787 selected = ti;
788 }
789
790 if (selected)
791 selected->select(0);
792 }
793
edit(GridMap * p_gridmap)794 void GridMapEditor::edit(GridMap *p_gridmap) {
795
796 node = p_gridmap;
797 VS *vs = VS::get_singleton();
798
799 last_mouseover = Vector3(-1, -1, -1);
800 input_action = INPUT_NONE;
801 selection.active = false;
802 _update_selection_transform();
803 _update_duplicate_indicator();
804
805 spatial_editor = editor->get_editor_plugin_screen()->cast_to<SpatialEditorPlugin>();
806
807 if (!node) {
808 set_process(false);
809 for (int i = 0; i < 3; i++) {
810 VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i], VS::INSTANCE_FLAG_VISIBLE, false);
811 }
812
813 VisualServer::get_singleton()->instance_geometry_set_flag(cursor_instance, VS::INSTANCE_FLAG_VISIBLE, false);
814
815 _clear_areas();
816
817 return;
818 }
819
820 update_pallete();
821 update_areas();
822
823 set_process(true);
824
825 Vector3 edited_floor = p_gridmap->get_meta("_editor_floor_");
826 clip_mode = p_gridmap->has_meta("_editor_clip_") ? ClipMode(p_gridmap->get_meta("_editor_clip_").operator int()) : CLIP_DISABLED;
827
828 for (int i = 0; i < 3; i++) {
829 if (vs->mesh_get_surface_count(grid[i]) > 0)
830 vs->mesh_remove_surface(grid[i], 0);
831 edit_floor[i] = edited_floor[i];
832 }
833
834 {
835
836 //update grids
837 indicator_mat = VisualServer::get_singleton()->fixed_material_create();
838 VisualServer::get_singleton()->material_set_flag(indicator_mat, VisualServer::MATERIAL_FLAG_UNSHADED, true);
839 VisualServer::get_singleton()->material_set_flag(indicator_mat, VisualServer::MATERIAL_FLAG_ONTOP, false);
840
841 VisualServer::get_singleton()->fixed_material_set_param(indicator_mat, VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.8, 0.5, 0.1));
842 VisualServer::get_singleton()->fixed_material_set_flag(indicator_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true);
843 VisualServer::get_singleton()->fixed_material_set_flag(indicator_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, true);
844
845 Vector<Vector3> grid_points[3];
846 Vector<Color> grid_colors[3];
847
848 float cell_size[3] = { p_gridmap->get_cell_size(), p_gridmap->get_cell_size(), p_gridmap->get_cell_size() };
849
850 for (int i = 0; i < 3; i++) {
851
852 Vector3 axis;
853 axis[i] = 1;
854 Vector3 axis_n1;
855 axis_n1[(i + 1) % 3] = cell_size[(i + 1) % 3];
856 Vector3 axis_n2;
857 axis_n2[(i + 2) % 3] = cell_size[(i + 2) % 3];
858
859 for (int j = -GRID_CURSOR_SIZE; j <= GRID_CURSOR_SIZE; j++) {
860
861 for (int k = -GRID_CURSOR_SIZE; k <= GRID_CURSOR_SIZE; k++) {
862
863 Vector3 p = axis_n1 * j + axis_n2 * k;
864 float trans = Math::pow(MAX(0, 1.0 - (Vector2(j, k).length() / GRID_CURSOR_SIZE)), 2);
865
866 Vector3 pj = axis_n1 * (j + 1) + axis_n2 * k;
867 float transj = Math::pow(MAX(0, 1.0 - (Vector2(j + 1, k).length() / GRID_CURSOR_SIZE)), 2);
868
869 Vector3 pk = axis_n1 * j + axis_n2 * (k + 1);
870 float transk = Math::pow(MAX(0, 1.0 - (Vector2(j, k + 1).length() / GRID_CURSOR_SIZE)), 2);
871
872 grid_points[i].push_back(p);
873 grid_points[i].push_back(pk);
874 grid_colors[i].push_back(Color(1, 1, 1, trans));
875 grid_colors[i].push_back(Color(1, 1, 1, transk));
876
877 grid_points[i].push_back(p);
878 grid_points[i].push_back(pj);
879 grid_colors[i].push_back(Color(1, 1, 1, trans));
880 grid_colors[i].push_back(Color(1, 1, 1, transj));
881 }
882 }
883
884 Array d;
885 d.resize(VS::ARRAY_MAX);
886 d[VS::ARRAY_VERTEX] = grid_points[i];
887 d[VS::ARRAY_COLOR] = grid_colors[i];
888 VisualServer::get_singleton()->mesh_add_surface(grid[i], VisualServer::PRIMITIVE_LINES, d);
889 VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat);
890 }
891 }
892
893 update_grid();
894 _update_clip();
895 _update_areas_display();
896 }
897
_update_clip()898 void GridMapEditor::_update_clip() {
899
900 node->set_meta("_editor_clip_", clip_mode);
901 if (clip_mode == CLIP_DISABLED)
902 node->set_clip(false);
903 else
904 node->set_clip(true, clip_mode == CLIP_ABOVE, edit_floor[edit_axis], edit_axis);
905 }
906
update_grid()907 void GridMapEditor::update_grid() {
908
909 grid_xform.origin.x -= 1; //force update in hackish way.. what do i care
910
911 //VS *vs = VS::get_singleton();
912
913 grid_ofs[edit_axis] = edit_floor[edit_axis] * node->get_cell_size();
914
915 edit_grid_xform.origin = grid_ofs;
916 edit_grid_xform.basis = Matrix3();
917
918 for (int i = 0; i < 3; i++) {
919 VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i], VS::INSTANCE_FLAG_VISIBLE, i == edit_axis);
920 }
921
922 updating = true;
923 floor->set_val(edit_floor[edit_axis]);
924 updating = false;
925 }
926
_notification(int p_what)927 void GridMapEditor::_notification(int p_what) {
928
929 if (p_what == NOTIFICATION_ENTER_TREE) {
930
931 theme_pallete->connect("item_selected", this, "_item_selected_cbk");
932 edit_mode->connect("item_selected", this, "_edit_mode_changed");
933 area_list->connect("item_edited", this, "_area_renamed");
934 area_list->connect("item_selected", this, "_area_selected");
935 for (int i = 0; i < 3; i++) {
936
937 grid[i] = VS::get_singleton()->mesh_create();
938 grid_instance[i] = VS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario());
939 }
940
941 selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario());
942 duplicate_instance = VisualServer::get_singleton()->instance_create2(duplicate_mesh, get_tree()->get_root()->get_world()->get_scenario());
943
944 _update_selection_transform();
945 _update_duplicate_indicator();
946
947 } else if (p_what == NOTIFICATION_EXIT_TREE) {
948
949 for (int i = 0; i < 3; i++) {
950
951 VS::get_singleton()->free(grid_instance[i]);
952 VS::get_singleton()->free(grid[i]);
953 grid_instance[i] = RID();
954 grid[i] = RID();
955 }
956
957 VisualServer::get_singleton()->free(selection_instance);
958 VisualServer::get_singleton()->free(duplicate_instance);
959 selection_instance = RID();
960 duplicate_instance = RID();
961
962 } else if (p_what == NOTIFICATION_PROCESS) {
963
964 Transform xf = node->get_global_transform();
965
966 if (xf != grid_xform) {
967 for (int i = 0; i < 3; i++) {
968
969 VS::get_singleton()->instance_set_transform(grid_instance[i], xf * edit_grid_xform);
970 }
971 grid_xform = xf;
972 }
973 Ref<MeshLibrary> cgmt = node->get_theme();
974 if (cgmt.operator->() != last_theme)
975 update_pallete();
976
977 if (lock_view) {
978
979 EditorNode *editor = get_tree()->get_root()->get_child(0)->cast_to<EditorNode>();
980
981 Plane p;
982 p.normal[edit_axis] = 1.0;
983 p.d = edit_floor[edit_axis] * node->get_cell_size();
984 p = node->get_transform().xform(p); // plane to snap
985
986 SpatialEditorPlugin *sep = editor->get_editor_plugin_screen()->cast_to<SpatialEditorPlugin>();
987 if (sep)
988 sep->snap_cursor_to_plane(p);
989 //editor->get_editor_plugin_screen()->call("snap_cursor_to_plane",p);
990 }
991 }
992 }
993
_update_cursor_instance()994 void GridMapEditor::_update_cursor_instance() {
995 if (!node) {
996 return;
997 }
998
999 if (cursor_instance.is_valid())
1000 VisualServer::get_singleton()->free(cursor_instance);
1001 cursor_instance = RID();
1002
1003 if (selected_pallete >= 0) {
1004
1005 if (node && !node->get_theme().is_null()) {
1006 Ref<Mesh> mesh = node->get_theme()->get_item_mesh(selected_pallete);
1007 if (!mesh.is_null() && mesh->get_rid().is_valid()) {
1008
1009 cursor_instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario());
1010 VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform);
1011 }
1012 }
1013 }
1014 }
1015
_item_selected_cbk(int idx)1016 void GridMapEditor::_item_selected_cbk(int idx) {
1017 selected_pallete = theme_pallete->get_item_metadata(idx);
1018
1019 _update_cursor_instance();
1020 }
1021
_clear_areas()1022 void GridMapEditor::_clear_areas() {
1023
1024 for (int i = 0; i < areas.size(); i++) {
1025
1026 VisualServer::get_singleton()->free(areas[i].instance);
1027 VisualServer::get_singleton()->free(areas[i].mesh);
1028 }
1029
1030 areas.clear();
1031 }
1032
_update_areas_display()1033 void GridMapEditor::_update_areas_display() {
1034 if (!node) {
1035 return;
1036 }
1037
1038 _clear_areas();
1039 List<int> areas;
1040 node->get_area_list(&areas);
1041
1042 Transform global_xf = node->get_global_transform();
1043
1044 for (List<int>::Element *E = areas.front(); E; E = E->next()) {
1045
1046 int area = E->get();
1047 Color color;
1048 if (node->area_is_exterior_portal(area))
1049 color = Color(1, 1, 1, 0.2);
1050 else
1051 color.set_hsv(Math::fmod(area * 0.37, 1), Math::fmod(area * 0.75, 1), 1.0, 0.2);
1052 RID material = VisualServer::get_singleton()->fixed_material_create();
1053 VisualServer::get_singleton()->fixed_material_set_param(material, VS::FIXED_MATERIAL_PARAM_DIFFUSE, color);
1054 VisualServer::get_singleton()->fixed_material_set_param(material, VS::FIXED_MATERIAL_PARAM_EMISSION, 0.5);
1055 VisualServer::get_singleton()->fixed_material_set_flag(material, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true);
1056
1057 RID mesh = VisualServer::get_singleton()->mesh_create();
1058
1059 DVector<Plane> planes;
1060 for (int i = 0; i < 3; i++) {
1061
1062 Vector3 axis;
1063 axis[i] = 1.0;
1064 planes.push_back(Plane(axis, 1));
1065 planes.push_back(Plane(-axis, 0));
1066 }
1067
1068 VisualServer::get_singleton()->mesh_add_surface_from_planes(mesh, planes);
1069 VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material, true);
1070
1071 AreaDisplay ad;
1072 ad.mesh = mesh;
1073 ad.instance = VisualServer::get_singleton()->instance_create2(mesh, node->get_world()->get_scenario());
1074 Transform xform;
1075 AABB aabb = node->area_get_bounds(area);
1076 xform.origin = aabb.pos * node->get_cell_size();
1077 xform.basis.scale(aabb.size * node->get_cell_size());
1078 VisualServer::get_singleton()->instance_set_transform(ad.instance, global_xf * xform);
1079 this->areas.push_back(ad);
1080 }
1081 }
1082
_edit_mode_changed(int p_what)1083 void GridMapEditor::_edit_mode_changed(int p_what) {
1084
1085 if (p_what == 0) {
1086
1087 theme_pallete->show();
1088 area_list->hide();
1089 } else {
1090
1091 theme_pallete->hide();
1092 area_list->show();
1093 }
1094 }
1095
_floor_changed(float p_value)1096 void GridMapEditor::_floor_changed(float p_value) {
1097
1098 if (updating)
1099 return;
1100
1101 edit_floor[edit_axis] = p_value;
1102 node->set_meta("_editor_floor_", Vector3(edit_floor[0], edit_floor[1], edit_floor[2]));
1103 update_grid();
1104 _update_clip();
1105 }
1106
_bind_methods()1107 void GridMapEditor::_bind_methods() {
1108
1109 ObjectTypeDB::bind_method("_menu_option", &GridMapEditor::_menu_option);
1110 ObjectTypeDB::bind_method("_configure", &GridMapEditor::_configure);
1111 ObjectTypeDB::bind_method("_item_selected_cbk", &GridMapEditor::_item_selected_cbk);
1112 ObjectTypeDB::bind_method("_edit_mode_changed", &GridMapEditor::_edit_mode_changed);
1113 ObjectTypeDB::bind_method("_area_renamed", &GridMapEditor::_area_renamed);
1114 ObjectTypeDB::bind_method("_area_selected", &GridMapEditor::_area_selected);
1115 ObjectTypeDB::bind_method("_floor_changed", &GridMapEditor::_floor_changed);
1116
1117 ObjectTypeDB::bind_method(_MD("_set_display_mode", "mode"), &GridMapEditor::_set_display_mode);
1118 }
1119
GridMapEditor(EditorNode * p_editor)1120 GridMapEditor::GridMapEditor(EditorNode *p_editor) {
1121
1122 input_action = INPUT_NONE;
1123 editor = p_editor;
1124 undo_redo = p_editor->get_undo_redo();
1125
1126 int mw = EDITOR_DEF("grid_map/palette_min_width", 230);
1127 Control *ec = memnew(Control);
1128 ec->set_custom_minimum_size(Size2(mw, 0));
1129 add_child(ec);
1130
1131 spatial_editor_hb = memnew(HBoxContainer);
1132 SpatialEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb);
1133 options = memnew(MenuButton);
1134 spatial_editor_hb->add_child(options);
1135 spatial_editor_hb->hide();
1136
1137 options->set_text("Grid");
1138 options->get_popup()->add_check_item("Snap View", MENU_OPTION_LOCK_VIEW);
1139 options->get_popup()->add_separator();
1140 options->get_popup()->add_item("Prev Level (" + keycode_get_string(KEY_MASK_CMD) + "Down Wheel)", MENU_OPTION_PREV_LEVEL);
1141 options->get_popup()->add_item("Next Level (" + keycode_get_string(KEY_MASK_CMD) + "Up Wheel)", MENU_OPTION_NEXT_LEVEL);
1142 options->get_popup()->add_separator();
1143 options->get_popup()->add_check_item("Clip Disabled", MENU_OPTION_CLIP_DISABLED);
1144 options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_CLIP_DISABLED), true);
1145 options->get_popup()->add_check_item("Clip Above", MENU_OPTION_CLIP_ABOVE);
1146 options->get_popup()->add_check_item("Clip Below", MENU_OPTION_CLIP_BELOW);
1147 options->get_popup()->add_separator();
1148 options->get_popup()->add_check_item("Edit X Axis", MENU_OPTION_X_AXIS, KEY_Z);
1149 options->get_popup()->add_check_item("Edit Y Axis", MENU_OPTION_Y_AXIS, KEY_X);
1150 options->get_popup()->add_check_item("Edit Z Axis", MENU_OPTION_Z_AXIS, KEY_C);
1151 options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_Y_AXIS), true);
1152 options->get_popup()->add_separator();
1153 options->get_popup()->add_item("Cursor Rotate X", MENU_OPTION_CURSOR_ROTATE_X, KEY_A);
1154 options->get_popup()->add_item("Cursor Rotate Y", MENU_OPTION_CURSOR_ROTATE_Y, KEY_S);
1155 options->get_popup()->add_item("Cursor Rotate Z", MENU_OPTION_CURSOR_ROTATE_Z, KEY_D);
1156 options->get_popup()->add_item("Cursor Back Rotate X", MENU_OPTION_CURSOR_BACK_ROTATE_X, KEY_MASK_SHIFT + KEY_A);
1157 options->get_popup()->add_item("Cursor Back Rotate Y", MENU_OPTION_CURSOR_BACK_ROTATE_Y, KEY_MASK_SHIFT + KEY_S);
1158 options->get_popup()->add_item("Cursor Back Rotate Z", MENU_OPTION_CURSOR_BACK_ROTATE_Z, KEY_MASK_SHIFT + KEY_D);
1159 options->get_popup()->add_item("Cursor Clear Rotation", MENU_OPTION_CURSOR_CLEAR_ROTATION, KEY_W);
1160 options->get_popup()->add_separator();
1161 options->get_popup()->add_check_item("Duplicate Selects", MENU_OPTION_DUPLICATE_SELECTS);
1162 options->get_popup()->add_separator();
1163 options->get_popup()->add_item("Create Area", MENU_OPTION_SELECTION_MAKE_AREA, KEY_CONTROL + KEY_C);
1164 options->get_popup()->add_item("Create Exterior Connector", MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR);
1165 options->get_popup()->add_item("Erase Area", MENU_OPTION_REMOVE_AREA);
1166 options->get_popup()->add_separator();
1167 options->get_popup()->add_item("Selection -> Duplicate", MENU_OPTION_SELECTION_DUPLICATE, KEY_MASK_SHIFT + KEY_INSERT);
1168 options->get_popup()->add_item("Selection -> Clear", MENU_OPTION_SELECTION_CLEAR, KEY_MASK_SHIFT + KEY_DELETE);
1169 //options->get_popup()->add_separator();
1170 //options->get_popup()->add_item("Configure",MENU_OPTION_CONFIGURE);
1171
1172 options->get_popup()->add_separator();
1173 options->get_popup()->add_item("Settings", MENU_OPTION_GRIDMAP_SETTINGS);
1174
1175 settings_dialog = memnew(ConfirmationDialog);
1176 settings_dialog->set_title("GridMap Settings");
1177 add_child(settings_dialog);
1178 settings_vbc = memnew(VBoxContainer);
1179 settings_vbc->set_custom_minimum_size(Size2(200, 0));
1180 settings_dialog->add_child(settings_vbc);
1181 settings_dialog->set_child_rect(settings_vbc);
1182
1183 settings_pick_distance = memnew(SpinBox);
1184 settings_pick_distance->set_max(10000.0f);
1185 settings_pick_distance->set_min(500.0f);
1186 settings_pick_distance->set_step(1.0f);
1187 settings_pick_distance->set_val(EDITOR_DEF("grid_map/pick_distance", 5000.0));
1188 settings_vbc->add_margin_child("Pick Distance:", settings_pick_distance);
1189
1190 clip_mode = CLIP_DISABLED;
1191 options->get_popup()->connect("item_pressed", this, "_menu_option");
1192
1193 HBoxContainer *hb = memnew(HBoxContainer);
1194 add_child(hb);
1195 hb->set_h_size_flags(SIZE_EXPAND_FILL);
1196
1197 edit_mode = memnew(OptionButton);
1198 edit_mode->set_area_as_parent_rect();
1199 edit_mode->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_BEGIN, 24);
1200 edit_mode->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 14);
1201 edit_mode->add_item("Tiles");
1202 edit_mode->add_item("Areas");
1203 hb->add_child(edit_mode);
1204 edit_mode->set_h_size_flags(SIZE_EXPAND_FILL);
1205
1206 mode_thumbnail = memnew(ToolButton);
1207 mode_thumbnail->set_toggle_mode(true);
1208 mode_thumbnail->set_pressed(true);
1209 mode_thumbnail->set_icon(p_editor->get_gui_base()->get_icon("FileThumbnail", "EditorIcons"));
1210 hb->add_child(mode_thumbnail);
1211 mode_thumbnail->connect("pressed", this, "_set_display_mode", varray(DISPLAY_THUMBNAIL));
1212
1213 mode_list = memnew(ToolButton);
1214 mode_list->set_toggle_mode(true);
1215 mode_list->set_pressed(false);
1216 mode_list->set_icon(p_editor->get_gui_base()->get_icon("FileList", "EditorIcons"));
1217 hb->add_child(mode_list);
1218 mode_list->connect("pressed", this, "_set_display_mode", varray(DISPLAY_LIST));
1219
1220 display_mode = DISPLAY_THUMBNAIL;
1221 selected_area = -1;
1222
1223 theme_pallete = memnew(ItemList);
1224 add_child(theme_pallete);
1225 theme_pallete->set_v_size_flags(SIZE_EXPAND_FILL);
1226
1227 area_list = memnew(Tree);
1228 add_child(area_list);
1229 area_list->set_v_size_flags(SIZE_EXPAND_FILL);
1230 area_list->hide();
1231
1232 spatial_editor_hb->add_child(memnew(VSeparator));
1233 Label *fl = memnew(Label);
1234 fl->set_text(" Floor: ");
1235 spatial_editor_hb->add_child(fl);
1236
1237 floor = memnew(SpinBox);
1238 floor->set_min(-32767);
1239 floor->set_max(32767);
1240 floor->set_step(1);
1241 floor->get_line_edit()->add_constant_override("minimum_spaces", 16);
1242
1243 spatial_editor_hb->add_child(floor);
1244 floor->connect("value_changed", this, "_floor_changed");
1245
1246 edit_axis = Vector3::AXIS_Y;
1247 edit_floor[0] = -1;
1248 edit_floor[1] = -1;
1249 edit_floor[2] = -1;
1250
1251 cursor_visible = false;
1252 selected_pallete = -1;
1253 lock_view = false;
1254 cursor_rot = 0;
1255 last_mouseover = Vector3(-1, -1, -1);
1256
1257 selection_mesh = VisualServer::get_singleton()->mesh_create();
1258 duplicate_mesh = VisualServer::get_singleton()->mesh_create();
1259
1260 {
1261 //selection mesh create
1262
1263 DVector<Vector3> lines;
1264 DVector<Vector3> triangles;
1265
1266 for (int i = 0; i < 6; i++) {
1267
1268 Vector3 face_points[4];
1269
1270 for (int j = 0; j < 4; j++) {
1271
1272 float v[3];
1273 v[0] = 1.0;
1274 v[1] = 1 - 2 * ((j >> 1) & 1);
1275 v[2] = v[1] * (1 - 2 * (j & 1));
1276
1277 for (int k = 0; k < 3; k++) {
1278
1279 if (i < 3)
1280 face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
1281 else
1282 face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
1283 }
1284 }
1285
1286 triangles.push_back(face_points[0] * 0.5 + Vector3(0.5, 0.5, 0.5));
1287 triangles.push_back(face_points[1] * 0.5 + Vector3(0.5, 0.5, 0.5));
1288 triangles.push_back(face_points[2] * 0.5 + Vector3(0.5, 0.5, 0.5));
1289
1290 triangles.push_back(face_points[2] * 0.5 + Vector3(0.5, 0.5, 0.5));
1291 triangles.push_back(face_points[3] * 0.5 + Vector3(0.5, 0.5, 0.5));
1292 triangles.push_back(face_points[0] * 0.5 + Vector3(0.5, 0.5, 0.5));
1293 }
1294
1295 for (int i = 0; i < 12; i++) {
1296
1297 AABB base(Vector3(0, 0, 0), Vector3(1, 1, 1));
1298 Vector3 a, b;
1299 base.get_edge(i, a, b);
1300 lines.push_back(a);
1301 lines.push_back(b);
1302 }
1303
1304 Array d;
1305 d.resize(VS::ARRAY_MAX);
1306
1307 inner_mat = VisualServer::get_singleton()->fixed_material_create();
1308 VisualServer::get_singleton()->fixed_material_set_param(inner_mat, VS::FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.7, 0.7, 1.0, 0.3));
1309 VisualServer::get_singleton()->material_set_flag(inner_mat, VS::MATERIAL_FLAG_ONTOP, true);
1310 VisualServer::get_singleton()->material_set_flag(inner_mat, VS::MATERIAL_FLAG_UNSHADED, true);
1311 VisualServer::get_singleton()->fixed_material_set_flag(inner_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true);
1312
1313 d[VS::ARRAY_VERTEX] = triangles;
1314 VisualServer::get_singleton()->mesh_add_surface(selection_mesh, VS::PRIMITIVE_TRIANGLES, d);
1315 VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat);
1316
1317 outer_mat = VisualServer::get_singleton()->fixed_material_create();
1318 VisualServer::get_singleton()->fixed_material_set_param(outer_mat, VS::FIXED_MATERIAL_PARAM_DIFFUSE, Color(0.7, 0.7, 1.0, 0.8));
1319 VisualServer::get_singleton()->material_set_line_width(outer_mat, 3.0);
1320 VisualServer::get_singleton()->material_set_flag(outer_mat, VS::MATERIAL_FLAG_ONTOP, true);
1321 VisualServer::get_singleton()->material_set_flag(outer_mat, VS::MATERIAL_FLAG_UNSHADED, true);
1322 VisualServer::get_singleton()->fixed_material_set_flag(outer_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true);
1323
1324 d[VS::ARRAY_VERTEX] = lines;
1325 VisualServer::get_singleton()->mesh_add_surface(selection_mesh, VS::PRIMITIVE_LINES, d);
1326 VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat);
1327
1328 inner_mat_dup = VisualServer::get_singleton()->fixed_material_create();
1329 VisualServer::get_singleton()->fixed_material_set_param(inner_mat_dup, VS::FIXED_MATERIAL_PARAM_DIFFUSE, Color(1.0, 0.7, 0.7, 0.3));
1330 VisualServer::get_singleton()->material_set_flag(inner_mat_dup, VS::MATERIAL_FLAG_ONTOP, true);
1331 VisualServer::get_singleton()->material_set_flag(inner_mat_dup, VS::MATERIAL_FLAG_UNSHADED, true);
1332 VisualServer::get_singleton()->fixed_material_set_flag(inner_mat_dup, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true);
1333
1334 d[VS::ARRAY_VERTEX] = triangles;
1335 VisualServer::get_singleton()->mesh_add_surface(duplicate_mesh, VS::PRIMITIVE_TRIANGLES, d);
1336 VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh, 0, inner_mat_dup);
1337
1338 outer_mat_dup = VisualServer::get_singleton()->fixed_material_create();
1339 VisualServer::get_singleton()->fixed_material_set_param(outer_mat_dup, VS::FIXED_MATERIAL_PARAM_DIFFUSE, Color(1.0, 0.7, 0.7, 0.8));
1340 VisualServer::get_singleton()->material_set_line_width(outer_mat_dup, 3.0);
1341 VisualServer::get_singleton()->material_set_flag(outer_mat_dup, VS::MATERIAL_FLAG_ONTOP, true);
1342 VisualServer::get_singleton()->material_set_flag(outer_mat_dup, VS::MATERIAL_FLAG_UNSHADED, true);
1343 VisualServer::get_singleton()->fixed_material_set_flag(outer_mat_dup, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true);
1344
1345 d[VS::ARRAY_VERTEX] = lines;
1346 VisualServer::get_singleton()->mesh_add_surface(duplicate_mesh, VS::PRIMITIVE_LINES, d);
1347 VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh, 1, outer_mat_dup);
1348 }
1349
1350 selection.active = false;
1351 updating = false;
1352 }
1353
~GridMapEditor()1354 GridMapEditor::~GridMapEditor() {
1355
1356 for (int i = 0; i < 3; i++) {
1357
1358 if (grid[i].is_valid())
1359 VisualServer::get_singleton()->free(grid[i]);
1360 if (grid_instance[i].is_valid())
1361 VisualServer::get_singleton()->free(grid_instance[i]);
1362 if (cursor_instance)
1363 VisualServer::get_singleton()->free(cursor_instance);
1364 }
1365
1366 VisualServer::get_singleton()->free(inner_mat);
1367 VisualServer::get_singleton()->free(outer_mat);
1368 VisualServer::get_singleton()->free(inner_mat_dup);
1369 VisualServer::get_singleton()->free(outer_mat_dup);
1370
1371 VisualServer::get_singleton()->free(selection_mesh);
1372 if (selection_instance.is_valid())
1373 VisualServer::get_singleton()->free(selection_instance);
1374
1375 VisualServer::get_singleton()->free(duplicate_mesh);
1376 if (duplicate_instance.is_valid())
1377 VisualServer::get_singleton()->free(duplicate_instance);
1378
1379 _clear_areas();
1380 }
1381
edit(Object * p_object)1382 void GridMapEditorPlugin::edit(Object *p_object) {
1383
1384 gridmap_editor->edit(p_object ? p_object->cast_to<GridMap>() : NULL);
1385 }
1386
handles(Object * p_object) const1387 bool GridMapEditorPlugin::handles(Object *p_object) const {
1388
1389 return p_object->is_type("GridMap");
1390 }
1391
make_visible(bool p_visible)1392 void GridMapEditorPlugin::make_visible(bool p_visible) {
1393
1394 if (p_visible) {
1395 gridmap_editor->show();
1396 gridmap_editor->spatial_editor_hb->show();
1397 gridmap_editor->set_process(true);
1398 } else {
1399
1400 gridmap_editor->spatial_editor_hb->hide();
1401 gridmap_editor->hide();
1402 gridmap_editor->edit(NULL);
1403 gridmap_editor->set_process(false);
1404 }
1405 }
1406
GridMapEditorPlugin(EditorNode * p_node)1407 GridMapEditorPlugin::GridMapEditorPlugin(EditorNode *p_node) {
1408
1409 editor = p_node;
1410 gridmap_editor = memnew(GridMapEditor(editor));
1411
1412 SpatialEditor::get_singleton()->get_palette_split()->add_child(gridmap_editor);
1413 SpatialEditor::get_singleton()->get_palette_split()->move_child(gridmap_editor, 0);
1414
1415 gridmap_editor->hide();
1416 }
1417
~GridMapEditorPlugin()1418 GridMapEditorPlugin::~GridMapEditorPlugin() {
1419 }
1420