Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/scene/3d/polygon_3d_editor_plugin.cpp
9902 views
1
/**************************************************************************/
2
/* polygon_3d_editor_plugin.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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
31
#include "polygon_3d_editor_plugin.h"
32
33
#include "core/input/input.h"
34
#include "core/math/geometry_2d.h"
35
#include "core/os/keyboard.h"
36
#include "editor/editor_node.h"
37
#include "editor/editor_string_names.h"
38
#include "editor/editor_undo_redo_manager.h"
39
#include "editor/scene/3d/node_3d_editor_plugin.h"
40
#include "editor/scene/canvas_item_editor_plugin.h"
41
#include "editor/settings/editor_settings.h"
42
#include "scene/3d/camera_3d.h"
43
44
void Polygon3DEditor::_notification(int p_what) {
45
switch (p_what) {
46
case NOTIFICATION_READY: {
47
button_create->set_button_icon(get_editor_theme_icon(SNAME("Edit")));
48
button_edit->set_button_icon(get_editor_theme_icon(SNAME("MovePoint")));
49
button_edit->set_pressed(true);
50
get_tree()->connect("node_removed", callable_mp(this, &Polygon3DEditor::_node_removed));
51
52
} break;
53
54
case NOTIFICATION_PROCESS: {
55
if (!node) {
56
return;
57
}
58
59
if (_get_depth() != prev_depth) {
60
_polygon_draw();
61
prev_depth = _get_depth();
62
}
63
64
} break;
65
}
66
}
67
68
void Polygon3DEditor::_node_removed(Node *p_node) {
69
if (p_node == node) {
70
node = nullptr;
71
if (imgeom->get_parent() == p_node) {
72
p_node->remove_child(imgeom);
73
}
74
hide();
75
set_process(false);
76
}
77
}
78
79
void Polygon3DEditor::_menu_option(int p_option) {
80
switch (p_option) {
81
case MODE_CREATE: {
82
mode = MODE_CREATE;
83
button_create->set_pressed(true);
84
button_edit->set_pressed(false);
85
} break;
86
case MODE_EDIT: {
87
mode = MODE_EDIT;
88
button_create->set_pressed(false);
89
button_edit->set_pressed(true);
90
} break;
91
}
92
}
93
94
void Polygon3DEditor::_wip_close() {
95
Object *obj = node_resource.is_valid() ? (Object *)node_resource.ptr() : node;
96
ERR_FAIL_NULL_MSG(obj, "Edited object is not valid.");
97
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
98
undo_redo->create_action(TTR("Create Polygon3D"));
99
undo_redo->add_undo_method(obj, "set_polygon", obj->call("get_polygon"));
100
undo_redo->add_do_method(obj, "set_polygon", wip);
101
undo_redo->add_do_method(this, "_polygon_draw");
102
undo_redo->add_undo_method(this, "_polygon_draw");
103
wip.clear();
104
wip_active = false;
105
mode = MODE_EDIT;
106
button_edit->set_pressed(true);
107
button_create->set_pressed(false);
108
edited_point = -1;
109
undo_redo->commit_action();
110
}
111
112
EditorPlugin::AfterGUIInput Polygon3DEditor::forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) {
113
if (!node) {
114
return EditorPlugin::AFTER_GUI_INPUT_PASS;
115
}
116
117
Object *obj = node_resource.is_valid() ? (Object *)node_resource.ptr() : node;
118
Transform3D gt = node->get_global_transform();
119
Transform3D gi = gt.affine_inverse();
120
float depth = _get_depth() * 0.5;
121
Vector3 n = gt.basis.get_column(2).normalized();
122
Plane p(n, gt.origin + n * depth);
123
124
Ref<InputEventMouseButton> mb = p_event;
125
126
if (mb.is_valid()) {
127
Vector2 gpoint = mb->get_position();
128
Vector3 ray_from = p_camera->project_ray_origin(gpoint);
129
Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
130
131
Vector3 spoint;
132
133
if (!p.intersects_ray(ray_from, ray_dir, &spoint)) {
134
return EditorPlugin::AFTER_GUI_INPUT_PASS;
135
}
136
137
spoint = gi.xform(spoint);
138
139
Vector2 cpoint(spoint.x, spoint.y);
140
141
//DO NOT snap here, it's confusing in 3D for adding points.
142
//Let the snap happen when the point is being moved, instead.
143
//cpoint = CanvasItemEditor::get_singleton()->snap_point(cpoint);
144
145
PackedVector2Array poly = _get_polygon();
146
147
//first check if a point is to be added (segment split)
148
real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius");
149
150
switch (mode) {
151
case MODE_CREATE: {
152
if (mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) {
153
if (!wip_active) {
154
wip.clear();
155
wip.push_back(cpoint);
156
wip_active = true;
157
edited_point_pos = cpoint;
158
snap_ignore = false;
159
_polygon_draw();
160
edited_point = 1;
161
return EditorPlugin::AFTER_GUI_INPUT_STOP;
162
} else {
163
if (wip.size() > 1 && p_camera->unproject_position(gt.xform(Vector3(wip[0].x, wip[0].y, depth))).distance_to(gpoint) < grab_threshold) {
164
//wip closed
165
_wip_close();
166
167
return EditorPlugin::AFTER_GUI_INPUT_STOP;
168
} else {
169
wip.push_back(cpoint);
170
edited_point = wip.size();
171
snap_ignore = false;
172
_polygon_draw();
173
return EditorPlugin::AFTER_GUI_INPUT_STOP;
174
}
175
}
176
} else if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed() && wip_active) {
177
_wip_close();
178
}
179
180
} break;
181
182
case MODE_EDIT: {
183
if (mb->get_button_index() == MouseButton::LEFT) {
184
if (mb->is_pressed()) {
185
if (mb->is_command_or_control_pressed()) {
186
if (poly.size() < 3) {
187
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
188
undo_redo->create_action(TTR("Edit Poly"));
189
undo_redo->add_undo_method(obj, "set_polygon", poly);
190
poly.push_back(cpoint);
191
undo_redo->add_do_method(obj, "set_polygon", poly);
192
undo_redo->add_do_method(this, "_polygon_draw");
193
undo_redo->add_undo_method(this, "_polygon_draw");
194
undo_redo->commit_action();
195
return EditorPlugin::AFTER_GUI_INPUT_STOP;
196
}
197
198
//search edges
199
int closest_idx = -1;
200
Vector2 closest_pos;
201
real_t closest_dist = 1e10;
202
for (int i = 0; i < poly.size(); i++) {
203
const Vector2 segment_a = p_camera->unproject_position(gt.xform(Vector3(poly[i].x, poly[i].y, depth)));
204
const Vector2 segment_b = p_camera->unproject_position(gt.xform(Vector3(poly[(i + 1) % poly.size()].x, poly[(i + 1) % poly.size()].y, depth)));
205
206
Vector2 cp = Geometry2D::get_closest_point_to_segment(gpoint, segment_a, segment_b);
207
if (cp.distance_squared_to(segment_a) < CMP_EPSILON2 || cp.distance_squared_to(segment_b) < CMP_EPSILON2) {
208
continue; //not valid to reuse point
209
}
210
211
real_t d = cp.distance_to(gpoint);
212
if (d < closest_dist && d < grab_threshold) {
213
closest_dist = d;
214
closest_pos = cp;
215
closest_idx = i;
216
}
217
}
218
219
if (closest_idx >= 0) {
220
pre_move_edit = poly;
221
poly.insert(closest_idx + 1, cpoint);
222
edited_point = closest_idx + 1;
223
edited_point_pos = cpoint;
224
_set_polygon(poly);
225
_polygon_draw();
226
snap_ignore = true;
227
228
return EditorPlugin::AFTER_GUI_INPUT_STOP;
229
}
230
} else {
231
//look for points to move
232
233
int closest_idx = -1;
234
Vector2 closest_pos;
235
real_t closest_dist = 1e10;
236
for (int i = 0; i < poly.size(); i++) {
237
Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x, poly[i].y, depth)));
238
239
real_t d = cp.distance_to(gpoint);
240
if (d < closest_dist && d < grab_threshold) {
241
closest_dist = d;
242
closest_pos = cp;
243
closest_idx = i;
244
}
245
}
246
247
if (closest_idx >= 0) {
248
pre_move_edit = poly;
249
edited_point = closest_idx;
250
edited_point_pos = poly[closest_idx];
251
_polygon_draw();
252
snap_ignore = false;
253
return EditorPlugin::AFTER_GUI_INPUT_STOP;
254
}
255
}
256
} else {
257
snap_ignore = false;
258
259
if (edited_point != -1) {
260
//apply
261
262
ERR_FAIL_INDEX_V(edited_point, poly.size(), EditorPlugin::AFTER_GUI_INPUT_PASS);
263
poly.write[edited_point] = edited_point_pos;
264
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
265
undo_redo->create_action(TTR("Edit Poly"));
266
undo_redo->add_do_method(obj, "set_polygon", poly);
267
undo_redo->add_undo_method(obj, "set_polygon", pre_move_edit);
268
undo_redo->add_do_method(this, "_polygon_draw");
269
undo_redo->add_undo_method(this, "_polygon_draw");
270
undo_redo->commit_action();
271
272
edited_point = -1;
273
return EditorPlugin::AFTER_GUI_INPUT_STOP;
274
}
275
}
276
}
277
if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed() && edited_point == -1) {
278
int closest_idx = -1;
279
Vector2 closest_pos;
280
real_t closest_dist = 1e10;
281
for (int i = 0; i < poly.size(); i++) {
282
Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x, poly[i].y, depth)));
283
284
real_t d = cp.distance_to(gpoint);
285
if (d < closest_dist && d < grab_threshold) {
286
closest_dist = d;
287
closest_pos = cp;
288
closest_idx = i;
289
}
290
}
291
292
if (closest_idx >= 0) {
293
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
294
undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
295
undo_redo->add_undo_method(obj, "set_polygon", poly);
296
poly.remove_at(closest_idx);
297
undo_redo->add_do_method(obj, "set_polygon", poly);
298
undo_redo->add_do_method(this, "_polygon_draw");
299
undo_redo->add_undo_method(this, "_polygon_draw");
300
undo_redo->commit_action();
301
return EditorPlugin::AFTER_GUI_INPUT_STOP;
302
}
303
}
304
305
} break;
306
}
307
}
308
309
Ref<InputEventMouseMotion> mm = p_event;
310
311
if (mm.is_valid()) {
312
if (edited_point != -1 && (wip_active || mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
313
Vector2 gpoint = mm->get_position();
314
315
Vector3 ray_from = p_camera->project_ray_origin(gpoint);
316
Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
317
318
Vector3 spoint;
319
320
if (!p.intersects_ray(ray_from, ray_dir, &spoint)) {
321
return EditorPlugin::AFTER_GUI_INPUT_PASS;
322
}
323
324
spoint = gi.xform(spoint);
325
326
Vector2 cpoint(spoint.x, spoint.y);
327
328
if (snap_ignore && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) {
329
snap_ignore = false;
330
}
331
332
if (!snap_ignore && Node3DEditor::get_singleton()->is_snap_enabled()) {
333
cpoint = cpoint.snappedf(Node3DEditor::get_singleton()->get_translate_snap());
334
}
335
edited_point_pos = cpoint;
336
337
_polygon_draw();
338
}
339
}
340
341
return EditorPlugin::AFTER_GUI_INPUT_PASS;
342
}
343
344
float Polygon3DEditor::_get_depth() {
345
Object *obj = node_resource.is_valid() ? (Object *)node_resource.ptr() : node;
346
ERR_FAIL_NULL_V_MSG(obj, 0.0f, "Edited object is not valid.");
347
348
if (bool(obj->call("_has_editable_3d_polygon_no_depth"))) {
349
return 0.0f;
350
}
351
352
return float(obj->call("get_depth"));
353
}
354
355
PackedVector2Array Polygon3DEditor::_get_polygon() {
356
Object *obj = node_resource.is_valid() ? (Object *)node_resource.ptr() : node;
357
ERR_FAIL_NULL_V_MSG(obj, PackedVector2Array(), "Edited object is not valid.");
358
return PackedVector2Array(obj->call("get_polygon"));
359
}
360
361
void Polygon3DEditor::_set_polygon(const PackedVector2Array &p_poly) {
362
Object *obj = node_resource.is_valid() ? (Object *)node_resource.ptr() : node;
363
ERR_FAIL_NULL_MSG(obj, "Edited object is not valid.");
364
obj->call("set_polygon", p_poly);
365
}
366
367
void Polygon3DEditor::_polygon_draw() {
368
if (!node) {
369
return;
370
}
371
372
PackedVector2Array poly;
373
374
if (wip_active) {
375
poly = wip;
376
} else {
377
poly = _get_polygon();
378
}
379
380
float depth = _get_depth() * 0.5;
381
382
m->clear_surfaces();
383
imesh->clear_surfaces();
384
imgeom->set_material_override(line_material);
385
imesh->surface_begin(Mesh::PRIMITIVE_LINES);
386
387
Rect2 rect;
388
389
for (int i = 0; i < poly.size(); i++) {
390
Vector2 p, p2;
391
p = i == edited_point ? edited_point_pos : poly[i];
392
if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point)) {
393
p2 = edited_point_pos;
394
} else {
395
p2 = poly[(i + 1) % poly.size()];
396
}
397
398
if (i == 0) {
399
rect.position = p;
400
} else {
401
rect.expand_to(p);
402
}
403
404
Vector3 point = Vector3(p.x, p.y, depth);
405
Vector3 next_point = Vector3(p2.x, p2.y, depth);
406
407
imesh->surface_set_color(Color(1, 0.3, 0.1, 0.8));
408
imesh->surface_add_vertex(point);
409
imesh->surface_set_color(Color(1, 0.3, 0.1, 0.8));
410
imesh->surface_add_vertex(next_point);
411
412
//Color col=Color(1,0.3,0.1,0.8);
413
//vpc->draw_line(point,next_point,col,2);
414
//vpc->draw_texture(handle,point-handle->get_size()*0.5);
415
}
416
417
rect = rect.grow(1);
418
419
AABB r;
420
r.position.x = rect.position.x;
421
r.position.y = rect.position.y;
422
r.position.z = depth;
423
r.size.x = rect.size.x;
424
r.size.y = rect.size.y;
425
r.size.z = 0;
426
427
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
428
imesh->surface_add_vertex(r.position);
429
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
430
imesh->surface_add_vertex(r.position + Vector3(0.3, 0, 0));
431
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
432
imesh->surface_add_vertex(r.position);
433
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
434
imesh->surface_add_vertex(r.position + Vector3(0.0, 0.3, 0));
435
436
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
437
imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0));
438
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
439
imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) - Vector3(0.3, 0, 0));
440
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
441
imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0));
442
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
443
imesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) + Vector3(0, 0.3, 0));
444
445
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
446
imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0));
447
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
448
imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) - Vector3(0, 0.3, 0));
449
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
450
imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0));
451
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
452
imesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) + Vector3(0.3, 0, 0));
453
454
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
455
imesh->surface_add_vertex(r.position + r.size);
456
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
457
imesh->surface_add_vertex(r.position + r.size - Vector3(0.3, 0, 0));
458
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
459
imesh->surface_add_vertex(r.position + r.size);
460
imesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
461
imesh->surface_add_vertex(r.position + r.size - Vector3(0.0, 0.3, 0));
462
463
imesh->surface_end();
464
465
if (poly.is_empty()) {
466
return;
467
}
468
469
Array a;
470
a.resize(Mesh::ARRAY_MAX);
471
Vector<Vector3> va;
472
{
473
va.resize(poly.size());
474
Vector3 *w = va.ptrw();
475
for (int i = 0; i < poly.size(); i++) {
476
Vector2 p;
477
p = i == edited_point ? edited_point_pos : poly[i];
478
479
Vector3 point = Vector3(p.x, p.y, depth);
480
w[i] = point;
481
}
482
}
483
a[Mesh::ARRAY_VERTEX] = va;
484
m->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS, a);
485
m->surface_set_material(0, handle_material);
486
}
487
488
void Polygon3DEditor::edit(Node *p_node) {
489
if (p_node) {
490
node = Object::cast_to<Node3D>(p_node);
491
node_resource = node->call("_get_editable_3d_polygon_resource");
492
493
if (node_resource.is_valid()) {
494
node_resource->connect_changed(callable_mp(this, &Polygon3DEditor::_polygon_draw));
495
}
496
//Enable the pencil tool if the polygon is empty
497
if (_get_polygon().is_empty()) {
498
_menu_option(MODE_CREATE);
499
}
500
wip.clear();
501
wip_active = false;
502
edited_point = -1;
503
if (imgeom->get_parent()) {
504
imgeom->reparent(p_node, false);
505
} else {
506
p_node->add_child(imgeom);
507
}
508
_polygon_draw();
509
set_process(true);
510
prev_depth = -1;
511
512
} else {
513
node = nullptr;
514
if (node_resource.is_valid()) {
515
node_resource->disconnect_changed(callable_mp(this, &Polygon3DEditor::_polygon_draw));
516
}
517
node_resource.unref();
518
519
if (imgeom->get_parent()) {
520
imgeom->get_parent()->remove_child(imgeom);
521
}
522
523
set_process(false);
524
}
525
}
526
527
void Polygon3DEditor::_bind_methods() {
528
ClassDB::bind_method(D_METHOD("_polygon_draw"), &Polygon3DEditor::_polygon_draw);
529
}
530
531
Polygon3DEditor::Polygon3DEditor() {
532
node = nullptr;
533
534
button_create = memnew(Button);
535
button_create->set_theme_type_variation(SceneStringName(FlatButton));
536
button_create->set_tooltip_text(TTRC("Create Polygon"));
537
add_child(button_create);
538
button_create->connect(SceneStringName(pressed), callable_mp(this, &Polygon3DEditor::_menu_option).bind(MODE_CREATE));
539
button_create->set_toggle_mode(true);
540
541
button_edit = memnew(Button);
542
button_edit->set_theme_type_variation(SceneStringName(FlatButton));
543
button_edit->set_tooltip_text(TTRC("Edit Polygon"));
544
add_child(button_edit);
545
button_edit->connect(SceneStringName(pressed), callable_mp(this, &Polygon3DEditor::_menu_option).bind(MODE_EDIT));
546
button_edit->set_toggle_mode(true);
547
548
mode = MODE_EDIT;
549
wip_active = false;
550
imgeom = memnew(MeshInstance3D);
551
imesh.instantiate();
552
imgeom->set_mesh(imesh);
553
imgeom->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
554
555
line_material.instantiate();
556
line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
557
line_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
558
line_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
559
line_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
560
line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
561
line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
562
line_material->set_albedo(Color(1, 1, 1));
563
564
handle_material.instantiate();
565
handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
566
handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true);
567
handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
568
handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
569
handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
570
handle_material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
571
handle_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
572
Ref<Texture2D> handle = EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Editor3DHandle"), EditorStringName(EditorIcons));
573
handle_material->set_point_size(handle->get_width());
574
handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle);
575
576
pointsm = memnew(MeshInstance3D);
577
imgeom->add_child(pointsm);
578
m.instantiate();
579
pointsm->set_mesh(m);
580
pointsm->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
581
582
snap_ignore = false;
583
}
584
585
Polygon3DEditor::~Polygon3DEditor() {
586
memdelete(imgeom);
587
}
588
589
void Polygon3DEditorPlugin::edit(Object *p_object) {
590
polygon_editor->edit(Object::cast_to<Node>(p_object));
591
}
592
593
bool Polygon3DEditorPlugin::handles(Object *p_object) const {
594
return Object::cast_to<Node3D>(p_object) && bool(p_object->call("_is_editable_3d_polygon"));
595
}
596
597
void Polygon3DEditorPlugin::make_visible(bool p_visible) {
598
if (p_visible) {
599
polygon_editor->show();
600
} else {
601
polygon_editor->hide();
602
polygon_editor->edit(nullptr);
603
}
604
}
605
606
Polygon3DEditorPlugin::Polygon3DEditorPlugin() {
607
polygon_editor = memnew(Polygon3DEditor);
608
Node3DEditor::get_singleton()->add_control_to_menu_panel(polygon_editor);
609
610
polygon_editor->hide();
611
}
612
613