Add helper for 3D gizmos and unify box

This commit is contained in:
kobewi 2023-08-04 22:21:09 +02:00
parent 3ed4497113
commit 015953a3d9
14 changed files with 342 additions and 317 deletions

View File

@ -34,6 +34,7 @@
#include "core/math/geometry_3d.h" #include "core/math/geometry_3d.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/gizmos/gizmo_3d_helper.h"
#include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/collision_shape_3d.h" #include "scene/3d/collision_shape_3d.h"
#include "scene/resources/box_shape_3d.h" #include "scene/resources/box_shape_3d.h"
@ -47,6 +48,7 @@
#include "scene/resources/world_boundary_shape_3d.h" #include "scene/resources/world_boundary_shape_3d.h"
CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() { CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() {
helper.instantiate();
const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
create_material("shape_material", gizmo_color); create_material("shape_material", gizmo_color);
const float gizmo_value = gizmo_color.get_v(); const float gizmo_value = gizmo_color.get_v();
@ -55,6 +57,9 @@ CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() {
create_handle_material("handles"); create_handle_material("handles");
} }
CollisionShape3DGizmoPlugin::~CollisionShape3DGizmoPlugin() {
}
bool CollisionShape3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { bool CollisionShape3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
return Object::cast_to<CollisionShape3D>(p_spatial) != nullptr; return Object::cast_to<CollisionShape3D>(p_spatial) != nullptr;
} }
@ -80,7 +85,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g
} }
if (Object::cast_to<BoxShape3D>(*s)) { if (Object::cast_to<BoxShape3D>(*s)) {
return "Size"; return helper->box_get_handle_name(p_id);
} }
if (Object::cast_to<CapsuleShape3D>(*s)) { if (Object::cast_to<CapsuleShape3D>(*s)) {
@ -135,8 +140,7 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p
} }
void CollisionShape3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) { void CollisionShape3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) {
initial_transform = p_gizmo->get_node_3d()->get_global_transform(); helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform());
initial_value = get_handle_value(p_gizmo, p_id, p_secondary);
} }
void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
@ -147,13 +151,8 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i
return; return;
} }
Transform3D gt = initial_transform; Vector3 sg[2];
Transform3D gi = gt.affine_inverse(); helper->get_segment(p_camera, p_point, sg);
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
if (Object::cast_to<SphereShape3D>(*s)) { if (Object::cast_to<SphereShape3D>(*s)) {
Ref<SphereShape3D> ss = s; Ref<SphereShape3D> ss = s;
@ -188,38 +187,12 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i
} }
if (Object::cast_to<BoxShape3D>(*s)) { if (Object::cast_to<BoxShape3D>(*s)) {
Vector3 axis;
axis[p_id / 2] = 1.0;
Ref<BoxShape3D> bs = s; Ref<BoxShape3D> bs = s;
Vector3 ra, rb; Vector3 size = bs->get_size();
int sign = p_id % 2 * -2 + 1; Vector3 position;
Vector3 initial_size = initial_value; helper->box_set_handle(sg, p_id, size, position);
bs->set_size(size);
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * sign, sg[0], sg[1], ra, rb); cs->set_global_position(position);
if (ra[p_id / 2] == 0) {
// Point before half of the shape. Needs to be calculated in opposite direction.
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * -sign, sg[0], sg[1], ra, rb);
}
float d = ra[p_id / 2] * sign;
Vector3 he = bs->get_size();
he[p_id / 2] = d * 2;
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
he[p_id / 2] = Math::snapped(he[p_id / 2], Node3DEditor::get_singleton()->get_translate_snap());
}
if (Input::get_singleton()->is_key_pressed(Key::ALT)) {
he[p_id / 2] = MAX(he[p_id / 2], 0.001);
bs->set_size(he);
cs->set_global_position(initial_transform.get_origin());
} else {
he[p_id / 2] = MAX(he[p_id / 2], -initial_size[p_id / 2] + 0.002);
bs->set_size((initial_size + (he - initial_size) * 0.5).abs());
Vector3 pos = initial_transform.affine_inverse().xform(initial_transform.get_origin());
pos += (bs->get_size() - initial_size) * 0.5 * sign;
cs->set_global_position(initial_transform.xform(pos));
}
} }
if (Object::cast_to<CapsuleShape3D>(*s)) { if (Object::cast_to<CapsuleShape3D>(*s)) {
@ -291,20 +264,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo
} }
if (Object::cast_to<BoxShape3D>(*s)) { if (Object::cast_to<BoxShape3D>(*s)) {
Ref<BoxShape3D> ss = s; helper->box_commit_handle(TTR("Change Box Shape Size"), p_cancel, cs, s.ptr());
if (p_cancel) {
cs->set_global_position(initial_transform.get_origin());
ss->set_size(p_restore);
return;
}
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Change Box Shape Size"));
ur->add_do_method(ss.ptr(), "set_size", ss->get_size());
ur->add_do_method(cs, "set_global_position", cs->get_global_position());
ur->add_undo_method(ss.ptr(), "set_size", p_restore);
ur->add_undo_method(cs, "set_global_position", initial_transform.get_origin());
ur->commit_action();
} }
if (Object::cast_to<CapsuleShape3D>(*s)) { if (Object::cast_to<CapsuleShape3D>(*s)) {
@ -446,14 +406,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
lines.push_back(b); lines.push_back(b);
} }
Vector<Vector3> handles; const Vector<Vector3> handles = helper->box_get_handles(bs->get_size());
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = bs->get_size()[i] / 2;
handles.push_back(ax);
handles.push_back(-ax);
}
p_gizmo->add_lines(lines, material); p_gizmo->add_lines(lines, material);
p_gizmo->add_collision_segments(lines); p_gizmo->add_collision_segments(lines);

View File

@ -33,11 +33,12 @@
#include "editor/plugins/node_3d_editor_gizmos.h" #include "editor/plugins/node_3d_editor_gizmos.h"
class Gizmo3DHelper;
class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin { class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin); GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
Transform3D initial_transform; Ref<Gizmo3DHelper> helper;
Variant initial_value;
public: public:
bool has_gizmo(Node3D *p_spatial) override; bool has_gizmo(Node3D *p_spatial) override;
@ -52,6 +53,7 @@ public:
void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override;
CollisionShape3DGizmoPlugin(); CollisionShape3DGizmoPlugin();
~CollisionShape3DGizmoPlugin();
}; };
#endif // COLLISION_SHAPE_3D_GIZMO_PLUGIN_H #endif // COLLISION_SHAPE_3D_GIZMO_PLUGIN_H

View File

@ -32,10 +32,12 @@
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/gizmos/gizmo_3d_helper.h"
#include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/decal.h" #include "scene/3d/decal.h"
DecalGizmoPlugin::DecalGizmoPlugin() { DecalGizmoPlugin::DecalGizmoPlugin() {
helper.instantiate();
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/decal", Color(0.6, 0.5, 1.0)); Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/decal", Color(0.6, 0.5, 1.0));
create_material("decal_material", gizmo_color); create_material("decal_material", gizmo_color);
@ -43,6 +45,9 @@ DecalGizmoPlugin::DecalGizmoPlugin() {
create_handle_material("handles"); create_handle_material("handles");
} }
DecalGizmoPlugin::~DecalGizmoPlugin() {
}
bool DecalGizmoPlugin::has_gizmo(Node3D *p_spatial) { bool DecalGizmoPlugin::has_gizmo(Node3D *p_spatial) {
return Object::cast_to<Decal>(p_spatial) != nullptr; return Object::cast_to<Decal>(p_spatial) != nullptr;
} }
@ -56,16 +61,7 @@ int DecalGizmoPlugin::get_priority() const {
} }
String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
switch (p_id) { return helper->box_get_handle_name(p_id);
case 0:
return "Size X";
case 1:
return "Size Y";
case 2:
return "Size Z";
}
return "";
} }
Variant DecalGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { Variant DecalGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
@ -73,52 +69,25 @@ Variant DecalGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int
return decal->get_size(); return decal->get_size();
} }
void DecalGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) {
helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform());
}
void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_node_3d()); Decal *decal = Object::cast_to<Decal>(p_gizmo->get_node_3d());
Transform3D gt = decal->get_global_transform();
Transform3D gi = gt.affine_inverse();
Vector3 size = decal->get_size(); Vector3 size = decal->get_size();
Vector3 ray_from = p_camera->project_ray_origin(p_point); Vector3 sg[2];
Vector3 ray_dir = p_camera->project_ray_normal(p_point); helper->get_segment(p_camera, p_point, sg);
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; Vector3 position;
helper->box_set_handle(sg, p_id, size, position);
Vector3 axis;
axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
float d = ra[p_id] * 2;
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
if (d < 0.001) {
d = 0.001;
}
size[p_id] = d;
decal->set_size(size); decal->set_size(size);
decal->set_global_position(position);
} }
void DecalGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { void DecalGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_node_3d()); helper->box_commit_handle(TTR("Change Decal Size"), p_cancel, p_gizmo->get_node_3d());
Vector3 restore = p_restore;
if (p_cancel) {
decal->set_size(restore);
return;
}
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Change Decal Size"));
ur->add_do_method(decal, "set_size", decal->get_size());
ur->add_undo_method(decal, "set_size", restore);
ur->commit_action();
} }
void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
@ -153,14 +122,7 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
lines.push_back(Vector3(0, half_size_y, 0)); lines.push_back(Vector3(0, half_size_y, 0));
lines.push_back(Vector3(0, half_size_y * 1.2, 0)); lines.push_back(Vector3(0, half_size_y * 1.2, 0));
Vector<Vector3> handles; Vector<Vector3> handles = helper->box_get_handles(decal->get_size());
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = aabb.position[i] + aabb.size[i];
handles.push_back(ax);
}
Ref<Material> material = get_material("decal_material", p_gizmo); Ref<Material> material = get_material("decal_material", p_gizmo);
p_gizmo->add_lines(lines, material); p_gizmo->add_lines(lines, material);

View File

@ -33,9 +33,13 @@
#include "editor/plugins/node_3d_editor_gizmos.h" #include "editor/plugins/node_3d_editor_gizmos.h"
class Gizmo3DHelper;
class DecalGizmoPlugin : public EditorNode3DGizmoPlugin { class DecalGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(DecalGizmoPlugin, EditorNode3DGizmoPlugin); GDCLASS(DecalGizmoPlugin, EditorNode3DGizmoPlugin);
Ref<Gizmo3DHelper> helper;
public: public:
bool has_gizmo(Node3D *p_spatial) override; bool has_gizmo(Node3D *p_spatial) override;
String get_gizmo_name() const override; String get_gizmo_name() const override;
@ -44,10 +48,12 @@ public:
String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override;
void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override;
void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override;
DecalGizmoPlugin(); DecalGizmoPlugin();
~DecalGizmoPlugin();
}; };
#endif // DECAL_GIZMO_PLUGIN_H #endif // DECAL_GIZMO_PLUGIN_H

View File

@ -0,0 +1,131 @@
/**************************************************************************/
/* gizmo_3d_helper.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "gizmo_3d_helper.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/camera_3d.h"
void Gizmo3DHelper::initialize_handle_action(const Variant &p_initial_value, const Transform3D &p_initial_transform) {
initial_value = p_initial_value;
initial_transform = p_initial_transform;
}
void Gizmo3DHelper::get_segment(Camera3D *p_camera, const Point2 &p_point, Vector3 *r_segment) {
Transform3D gt = initial_transform;
Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
r_segment[0] = gi.xform(ray_from);
r_segment[1] = gi.xform(ray_from + ray_dir * 4096);
}
Vector<Vector3> Gizmo3DHelper::box_get_handles(const Vector3 &p_box_size) {
Vector<Vector3> handles;
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = p_box_size[i] / 2;
handles.push_back(ax);
handles.push_back(-ax);
}
return handles;
}
String Gizmo3DHelper::box_get_handle_name(int p_id) const {
switch (p_id) {
case 0:
case 1:
return "Size X";
case 2:
case 3:
return "Size Y";
case 4:
case 5:
return "Size Z";
}
return "";
}
void Gizmo3DHelper::box_set_handle(const Vector3 p_segment[2], int p_id, Vector3 &r_box_size, Vector3 &r_box_position) {
Vector3 axis;
axis[p_id / 2] = 1.0;
Vector3 ra, rb;
int sign = p_id % 2 * -2 + 1;
Vector3 initial_size = initial_value;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * sign, p_segment[0], p_segment[1], ra, rb);
if (ra[p_id / 2] == 0) {
// Point before half of the shape. Needs to be calculated in opposite direction.
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * -sign, p_segment[0], p_segment[1], ra, rb);
}
float d = ra[p_id / 2] * sign;
Vector3 he = r_box_size;
he[p_id / 2] = d * 2;
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
he[p_id / 2] = Math::snapped(he[p_id / 2], Node3DEditor::get_singleton()->get_translate_snap());
}
if (Input::get_singleton()->is_key_pressed(Key::ALT)) {
he[p_id / 2] = MAX(he[p_id / 2], 0.001);
r_box_size = he;
r_box_position = initial_transform.get_origin();
} else {
he[p_id / 2] = MAX(he[p_id / 2], -initial_size[p_id / 2] + 0.002);
r_box_size = (initial_size + (he - initial_size) * 0.5).abs();
Vector3 pos = initial_transform.affine_inverse().xform(initial_transform.get_origin());
pos += (r_box_size - initial_size) * 0.5 * sign;
r_box_position = initial_transform.xform(pos);
}
}
void Gizmo3DHelper::box_commit_handle(const String &p_action_name, bool p_cancel, Object *p_position_object, Object *p_size_object, const StringName &p_position_property, const StringName &p_size_property) {
if (!p_size_object) {
p_size_object = p_position_object;
}
if (p_cancel) {
p_size_object->set(p_size_property, initial_value);
p_position_object->set(p_position_property, initial_transform.get_origin());
return;
}
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(p_action_name);
ur->add_do_property(p_size_object, p_size_property, p_size_object->get(p_size_property));
ur->add_do_property(p_position_object, p_position_property, p_position_object->get(p_position_property));
ur->add_undo_property(p_size_object, p_size_property, initial_value);
ur->add_undo_property(p_position_object, p_position_property, initial_transform.get_origin());
ur->commit_action();
}

View File

@ -0,0 +1,55 @@
/**************************************************************************/
/* gizmo_3d_helper.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GIZMO_3D_HELPER_H
#define GIZMO_3D_HELPER_H
#include "core/object/ref_counted.h"
class Camera3D;
class Gizmo3DHelper : public RefCounted {
GDCLASS(Gizmo3DHelper, RefCounted);
int current_handle_id;
Variant initial_value;
Transform3D initial_transform;
public:
void initialize_handle_action(const Variant &p_initial_value, const Transform3D &p_initial_transform);
void get_segment(Camera3D *p_camera, const Point2 &p_point, Vector3 *r_segment);
Vector<Vector3> box_get_handles(const Vector3 &p_box_size);
String box_get_handle_name(int p_id) const;
void box_set_handle(const Vector3 p_segment[2], int p_id, Vector3 &r_box_size, Vector3 &r_box_position);
void box_commit_handle(const String &p_action_name, bool p_cancel, Object *p_position_object, Object *p_size_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_size_property = "size");
};
#endif // GIZMO_3D_HELPER_H

View File

@ -32,10 +32,13 @@
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/gizmos/gizmo_3d_helper.h"
#include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/gpu_particles_collision_3d.h" #include "scene/3d/gpu_particles_collision_3d.h"
GPUParticlesCollision3DGizmoPlugin::GPUParticlesCollision3DGizmoPlugin() { GPUParticlesCollision3DGizmoPlugin::GPUParticlesCollision3DGizmoPlugin() {
helper.instantiate();
Color gizmo_color_attractor = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particle_attractor", Color(1, 0.7, 0.5)); Color gizmo_color_attractor = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particle_attractor", Color(1, 0.7, 0.5));
create_material("shape_material_attractor", gizmo_color_attractor); create_material("shape_material_attractor", gizmo_color_attractor);
gizmo_color_attractor.a = 0.15; gizmo_color_attractor.a = 0.15;
@ -49,6 +52,9 @@ GPUParticlesCollision3DGizmoPlugin::GPUParticlesCollision3DGizmoPlugin() {
create_handle_material("handles"); create_handle_material("handles");
} }
GPUParticlesCollision3DGizmoPlugin::~GPUParticlesCollision3DGizmoPlugin() {
}
bool GPUParticlesCollision3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { bool GPUParticlesCollision3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
return (Object::cast_to<GPUParticlesCollision3D>(p_spatial) != nullptr) || (Object::cast_to<GPUParticlesAttractor3D>(p_spatial) != nullptr); return (Object::cast_to<GPUParticlesCollision3D>(p_spatial) != nullptr) || (Object::cast_to<GPUParticlesAttractor3D>(p_spatial) != nullptr);
} }
@ -69,7 +75,7 @@ String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGiz
} }
if (Object::cast_to<GPUParticlesCollisionBox3D>(cs) || Object::cast_to<GPUParticlesAttractorBox3D>(cs) || Object::cast_to<GPUParticlesAttractorVectorField3D>(cs) || Object::cast_to<GPUParticlesCollisionSDF3D>(cs) || Object::cast_to<GPUParticlesCollisionHeightField3D>(cs)) { if (Object::cast_to<GPUParticlesCollisionBox3D>(cs) || Object::cast_to<GPUParticlesAttractorBox3D>(cs) || Object::cast_to<GPUParticlesAttractorVectorField3D>(cs) || Object::cast_to<GPUParticlesCollisionSDF3D>(cs) || Object::cast_to<GPUParticlesCollisionHeightField3D>(cs)) {
return "Size"; return helper->box_get_handle_name(p_id);
} }
return ""; return "";
@ -89,16 +95,15 @@ Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(const EditorNode3DG
return Variant(); return Variant();
} }
void GPUParticlesCollision3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) {
helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform());
}
void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
Node3D *sn = p_gizmo->get_node_3d(); Node3D *sn = p_gizmo->get_node_3d();
Transform3D gt = sn->get_global_transform(); Vector3 sg[2];
Transform3D gi = gt.affine_inverse(); helper->get_segment(p_camera, p_point, sg);
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
if (Object::cast_to<GPUParticlesCollisionSphere3D>(sn) || Object::cast_to<GPUParticlesAttractorSphere3D>(sn)) { if (Object::cast_to<GPUParticlesCollisionSphere3D>(sn) || Object::cast_to<GPUParticlesAttractorSphere3D>(sn)) {
Vector3 ra, rb; Vector3 ra, rb;
@ -116,22 +121,11 @@ void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_g
} }
if (Object::cast_to<GPUParticlesCollisionBox3D>(sn) || Object::cast_to<GPUParticlesAttractorBox3D>(sn) || Object::cast_to<GPUParticlesAttractorVectorField3D>(sn) || Object::cast_to<GPUParticlesCollisionSDF3D>(sn) || Object::cast_to<GPUParticlesCollisionHeightField3D>(sn)) { if (Object::cast_to<GPUParticlesCollisionBox3D>(sn) || Object::cast_to<GPUParticlesAttractorBox3D>(sn) || Object::cast_to<GPUParticlesAttractorVectorField3D>(sn) || Object::cast_to<GPUParticlesCollisionSDF3D>(sn) || Object::cast_to<GPUParticlesCollisionHeightField3D>(sn)) {
Vector3 axis; Vector3 size = sn->call("get_size");
axis[p_id] = 1.0; Vector3 position;
Vector3 ra, rb; helper->box_set_handle(sg, p_id, size, position);
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); sn->call("set_size", size);
float d = ra[p_id] * 2; sn->set_global_position(position);
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
if (d < 0.001) {
d = 0.001;
}
Vector3 he = sn->call("get_size");
he[p_id] = d;
sn->call("set_size", he);
} }
} }
@ -152,16 +146,7 @@ void GPUParticlesCollision3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *
} }
if (Object::cast_to<GPUParticlesCollisionBox3D>(sn) || Object::cast_to<GPUParticlesAttractorBox3D>(sn) || Object::cast_to<GPUParticlesAttractorVectorField3D>(sn) || Object::cast_to<GPUParticlesCollisionSDF3D>(sn) || Object::cast_to<GPUParticlesCollisionHeightField3D>(sn)) { if (Object::cast_to<GPUParticlesCollisionBox3D>(sn) || Object::cast_to<GPUParticlesAttractorBox3D>(sn) || Object::cast_to<GPUParticlesAttractorVectorField3D>(sn) || Object::cast_to<GPUParticlesCollisionSDF3D>(sn) || Object::cast_to<GPUParticlesCollisionHeightField3D>(sn)) {
if (p_cancel) { helper->box_commit_handle("Change Box Shape Size", p_cancel, sn);
sn->call("set_size", p_restore);
return;
}
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Change Box Shape Size"));
ur->add_do_method(sn, "set_size", sn->call("get_size"));
ur->add_undo_method(sn, "set_size", p_restore);
ur->commit_action();
} }
} }
@ -237,13 +222,7 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
lines.push_back(b); lines.push_back(b);
} }
Vector<Vector3> handles; Vector<Vector3> handles = helper->box_get_handles(aabb.size);
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = cs->call("get_size").operator Vector3()[i] / 2;
handles.push_back(ax);
}
p_gizmo->add_lines(lines, material); p_gizmo->add_lines(lines, material);
p_gizmo->add_collision_segments(lines); p_gizmo->add_collision_segments(lines);

View File

@ -33,9 +33,13 @@
#include "editor/plugins/node_3d_editor_gizmos.h" #include "editor/plugins/node_3d_editor_gizmos.h"
class Gizmo3DHelper;
class GPUParticlesCollision3DGizmoPlugin : public EditorNode3DGizmoPlugin { class GPUParticlesCollision3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(GPUParticlesCollision3DGizmoPlugin, EditorNode3DGizmoPlugin); GDCLASS(GPUParticlesCollision3DGizmoPlugin, EditorNode3DGizmoPlugin);
Ref<Gizmo3DHelper> helper;
public: public:
bool has_gizmo(Node3D *p_spatial) override; bool has_gizmo(Node3D *p_spatial) override;
String get_gizmo_name() const override; String get_gizmo_name() const override;
@ -44,10 +48,12 @@ public:
String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override;
void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override;
void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override;
GPUParticlesCollision3DGizmoPlugin(); GPUParticlesCollision3DGizmoPlugin();
~GPUParticlesCollision3DGizmoPlugin();
}; };
#endif // GPU_PARTICLES_COLLISION_3D_GIZMO_PLUGIN_H #endif // GPU_PARTICLES_COLLISION_3D_GIZMO_PLUGIN_H

View File

@ -32,10 +32,12 @@
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/gizmos/gizmo_3d_helper.h"
#include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/reflection_probe.h" #include "scene/3d/reflection_probe.h"
ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() { ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() {
helper.instantiate();
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/reflection_probe", Color(0.6, 1, 0.5)); Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/reflection_probe", Color(0.6, 1, 0.5));
create_material("reflection_probe_material", gizmo_color); create_material("reflection_probe_material", gizmo_color);
@ -50,6 +52,9 @@ ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() {
create_handle_material("handles"); create_handle_material("handles");
} }
ReflectionProbeGizmoPlugin::~ReflectionProbeGizmoPlugin() {
}
bool ReflectionProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) { bool ReflectionProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) {
return Object::cast_to<ReflectionProbe>(p_spatial) != nullptr; return Object::cast_to<ReflectionProbe>(p_spatial) != nullptr;
} }
@ -63,21 +68,17 @@ int ReflectionProbeGizmoPlugin::get_priority() const {
} }
String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
if (p_id < 6) {
return helper->box_get_handle_name(p_id);
}
switch (p_id) { switch (p_id) {
case 0: case 6:
return "Size X";
case 1:
return "Size Y";
case 2:
return "Size Z";
case 3:
return "Origin X"; return "Origin X";
case 4: case 7:
return "Origin Y"; return "Origin Y";
case 5: case 8:
return "Origin Z"; return "Origin Z";
} }
return ""; return "";
} }
@ -86,47 +87,30 @@ Variant ReflectionProbeGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_
return AABB(probe->get_origin_offset(), probe->get_size()); return AABB(probe->get_origin_offset(), probe->get_size());
} }
void ReflectionProbeGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) {
// The initial value is only used for resizing the box, so we only need AABB size.
AABB aabb = get_handle_value(p_gizmo, p_id, p_secondary);
helper->initialize_handle_action(aabb.size, p_gizmo->get_node_3d()->get_global_transform());
}
void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d()); ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d());
Transform3D gt = probe->get_global_transform();
Transform3D gi = gt.affine_inverse(); Vector3 sg[2];
helper->get_segment(p_camera, p_point, sg);
if (p_id < 3) { if (p_id < 6) {
Vector3 size = probe->get_size(); Vector3 size = probe->get_size();
Vector3 position;
Vector3 ray_from = p_camera->project_ray_origin(p_point); helper->box_set_handle(sg, p_id, size, position);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
Vector3 axis;
axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
float d = ra[p_id] * 2;
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
if (d < 0.001) {
d = 0.001;
}
size[p_id] = d;
probe->set_size(size); probe->set_size(size);
probe->set_global_position(position);
} else { } else {
p_id -= 3; p_id -= 6;
Vector3 origin = probe->get_origin_offset(); Vector3 origin = probe->get_origin_offset();
origin[p_id] = 0; origin[p_id] = 0;
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
Vector3 axis; Vector3 axis;
axis[p_id] = 1.0; axis[p_id] = 1.0;
@ -146,6 +130,11 @@ void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, in
void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d()); ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d());
if (p_id < 6) {
helper->box_commit_handle(TTR("Change Probe Size"), p_cancel, probe);
return;
}
AABB restore = p_restore; AABB restore = p_restore;
if (p_cancel) { if (p_cancel) {
@ -155,10 +144,8 @@ void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo,
} }
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Change Probe Size")); ur->create_action(TTR("Change Probe Origin Offset"));
ur->add_do_method(probe, "set_size", probe->get_size());
ur->add_do_method(probe, "set_origin_offset", probe->get_origin_offset()); ur->add_do_method(probe, "set_origin_offset", probe->get_origin_offset());
ur->add_undo_method(probe, "set_size", restore.size);
ur->add_undo_method(probe, "set_origin_offset", restore.position); ur->add_undo_method(probe, "set_origin_offset", restore.position);
ur->commit_action(); ur->commit_action();
} }
@ -189,13 +176,7 @@ void ReflectionProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
internal_lines.push_back(ep); internal_lines.push_back(ep);
} }
Vector<Vector3> handles; Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = aabb.position[i] + aabb.size[i];
handles.push_back(ax);
}
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Vector3 orig_handle = probe->get_origin_offset(); Vector3 orig_handle = probe->get_origin_offset();

View File

@ -33,9 +33,13 @@
#include "editor/plugins/node_3d_editor_gizmos.h" #include "editor/plugins/node_3d_editor_gizmos.h"
class Gizmo3DHelper;
class ReflectionProbeGizmoPlugin : public EditorNode3DGizmoPlugin { class ReflectionProbeGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(ReflectionProbeGizmoPlugin, EditorNode3DGizmoPlugin); GDCLASS(ReflectionProbeGizmoPlugin, EditorNode3DGizmoPlugin);
Ref<Gizmo3DHelper> helper;
public: public:
bool has_gizmo(Node3D *p_spatial) override; bool has_gizmo(Node3D *p_spatial) override;
String get_gizmo_name() const override; String get_gizmo_name() const override;
@ -44,10 +48,12 @@ public:
String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override;
void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override;
void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override;
ReflectionProbeGizmoPlugin(); ReflectionProbeGizmoPlugin();
~ReflectionProbeGizmoPlugin();
}; };
#endif // REFLECTION_PROBE_GIZMO_PLUGIN_H #endif // REFLECTION_PROBE_GIZMO_PLUGIN_H

View File

@ -32,10 +32,13 @@
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/gizmos/gizmo_3d_helper.h"
#include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/voxel_gi.h" #include "scene/3d/voxel_gi.h"
VoxelGIGizmoPlugin::VoxelGIGizmoPlugin() { VoxelGIGizmoPlugin::VoxelGIGizmoPlugin() {
helper.instantiate();
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/voxel_gi", Color(0.5, 1, 0.6)); Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/voxel_gi", Color(0.5, 1, 0.6));
create_material("voxel_gi_material", gizmo_color); create_material("voxel_gi_material", gizmo_color);
@ -51,6 +54,9 @@ VoxelGIGizmoPlugin::VoxelGIGizmoPlugin() {
create_handle_material("handles"); create_handle_material("handles");
} }
VoxelGIGizmoPlugin::~VoxelGIGizmoPlugin() {
}
bool VoxelGIGizmoPlugin::has_gizmo(Node3D *p_spatial) { bool VoxelGIGizmoPlugin::has_gizmo(Node3D *p_spatial) {
return Object::cast_to<VoxelGI>(p_spatial) != nullptr; return Object::cast_to<VoxelGI>(p_spatial) != nullptr;
} }
@ -64,16 +70,7 @@ int VoxelGIGizmoPlugin::get_priority() const {
} }
String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
switch (p_id) { return helper->box_get_handle_name(p_id);
case 0:
return "Size X";
case 1:
return "Size Y";
case 2:
return "Size Z";
}
return "";
} }
Variant VoxelGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { Variant VoxelGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
@ -81,52 +78,25 @@ Variant VoxelGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, i
return probe->get_size(); return probe->get_size();
} }
void VoxelGIGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) {
helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform());
}
void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_node_3d()); VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_node_3d());
Transform3D gt = probe->get_global_transform(); Vector3 sg[2];
Transform3D gi = gt.affine_inverse(); helper->get_segment(p_camera, p_point, sg);
Vector3 size = probe->get_size(); Vector3 size = probe->get_size();
Vector3 position;
Vector3 ray_from = p_camera->project_ray_origin(p_point); helper->box_set_handle(sg, p_id, size, position);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
Vector3 axis;
axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
float d = ra[p_id] * 2;
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
if (d < 0.001) {
d = 0.001;
}
size[p_id] = d;
probe->set_size(size); probe->set_size(size);
probe->set_global_position(position);
} }
void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_node_3d()); helper->box_commit_handle(TTR("Change Probe Size"), p_cancel, p_gizmo->get_node_3d());
Vector3 restore = p_restore;
if (p_cancel) {
probe->set_size(restore);
return;
}
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Change Probe Size"));
ur->add_do_method(probe, "set_size", probe->get_size());
ur->add_undo_method(probe, "set_size", restore);
ur->commit_action();
} }
void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
@ -191,13 +161,7 @@ void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
p_gizmo->add_lines(lines, material_internal); p_gizmo->add_lines(lines, material_internal);
Vector<Vector3> handles; Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = aabb.position[i] + aabb.size[i];
handles.push_back(ax);
}
if (p_gizmo->is_selected()) { if (p_gizmo->is_selected()) {
Ref<Material> solid_material = get_material("voxel_gi_solid_material", p_gizmo); Ref<Material> solid_material = get_material("voxel_gi_solid_material", p_gizmo);

View File

@ -33,9 +33,13 @@
#include "editor/plugins/node_3d_editor_gizmos.h" #include "editor/plugins/node_3d_editor_gizmos.h"
class Gizmo3DHelper;
class VoxelGIGizmoPlugin : public EditorNode3DGizmoPlugin { class VoxelGIGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(VoxelGIGizmoPlugin, EditorNode3DGizmoPlugin); GDCLASS(VoxelGIGizmoPlugin, EditorNode3DGizmoPlugin);
Ref<Gizmo3DHelper> helper;
public: public:
bool has_gizmo(Node3D *p_spatial) override; bool has_gizmo(Node3D *p_spatial) override;
String get_gizmo_name() const override; String get_gizmo_name() const override;
@ -44,10 +48,12 @@ public:
String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override;
void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override;
void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override;
VoxelGIGizmoPlugin(); VoxelGIGizmoPlugin();
~VoxelGIGizmoPlugin();
}; };
#endif // VOXEL_GI_GIZMO_PLUGIN_H #endif // VOXEL_GI_GIZMO_PLUGIN_H

View File

@ -35,12 +35,15 @@
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/gizmos/gizmo_3d_helper.h"
#include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/camera_3d.h" #include "scene/3d/camera_3d.h"
/////////// ///////////
CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() { CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() {
helper.instantiate();
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/csg", Color(0.0, 0.4, 1, 0.15)); Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/csg", Color(0.0, 0.4, 1, 0.15));
create_material("shape_union_material", gizmo_color); create_material("shape_union_material", gizmo_color);
create_material("shape_union_solid_material", gizmo_color); create_material("shape_union_solid_material", gizmo_color);
@ -56,6 +59,9 @@ CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() {
create_handle_material("handles"); create_handle_material("handles");
} }
CSGShape3DGizmoPlugin::~CSGShape3DGizmoPlugin() {
}
String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_node_3d()); CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_node_3d());
@ -64,7 +70,7 @@ String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo,
} }
if (Object::cast_to<CSGBox3D>(cs)) { if (Object::cast_to<CSGBox3D>(cs)) {
return "Size"; return helper->box_get_handle_name(p_id);
} }
if (Object::cast_to<CSGCylinder3D>(cs)) { if (Object::cast_to<CSGCylinder3D>(cs)) {
@ -104,17 +110,15 @@ Variant CSGShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo
return Variant(); return Variant();
} }
void CSGShape3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) {
helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform());
}
void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_node_3d()); CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_node_3d());
Transform3D gt = cs->get_global_transform(); Vector3 sg[2];
//gt.orthonormalize(); helper->get_segment(p_camera, p_point, sg);
Transform3D gi = gt.affine_inverse();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
if (Object::cast_to<CSGSphere3D>(cs)) { if (Object::cast_to<CSGSphere3D>(cs)) {
CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs); CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs);
@ -135,29 +139,11 @@ void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_i
if (Object::cast_to<CSGBox3D>(cs)) { if (Object::cast_to<CSGBox3D>(cs)) {
CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); CSGBox3D *s = Object::cast_to<CSGBox3D>(cs);
Vector3 size = s->get_size();
Vector3 axis; Vector3 position;
axis[p_id] = 1.0; helper->box_set_handle(sg, p_id, size, position);
Vector3 ra, rb; s->set_size(size);
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); s->set_global_position(position);
float d = ra[p_id];
if (Math::is_nan(d)) {
// The handle is perpendicular to the camera.
return;
}
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
if (d < 0.001) {
d = 0.001;
}
Vector3 h = s->get_size();
h[p_id] = d * 2;
s->set_size(h);
} }
if (Object::cast_to<CSGCylinder3D>(cs)) { if (Object::cast_to<CSGCylinder3D>(cs)) {
@ -225,17 +211,7 @@ void CSGShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int
} }
if (Object::cast_to<CSGBox3D>(cs)) { if (Object::cast_to<CSGBox3D>(cs)) {
CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); helper->box_commit_handle(TTR("Change Box Shape Size"), p_cancel, cs);
if (p_cancel) {
s->set_size(p_restore);
return;
}
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Change Box Shape Size"));
ur->add_do_method(s, "set_size", s->get_size());
ur->add_undo_method(s, "set_size", p_restore);
ur->commit_action();
} }
if (Object::cast_to<CSGCylinder3D>(cs)) { if (Object::cast_to<CSGCylinder3D>(cs)) {
@ -394,15 +370,7 @@ void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
if (Object::cast_to<CSGBox3D>(cs)) { if (Object::cast_to<CSGBox3D>(cs)) {
CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); CSGBox3D *s = Object::cast_to<CSGBox3D>(cs);
Vector<Vector3> handles = helper->box_get_handles(s->get_size());
Vector<Vector3> handles;
for (int i = 0; i < 3; i++) {
Vector3 h;
h[i] = s->get_size()[i] / 2;
handles.push_back(h);
}
p_gizmo->add_handles(handles, handles_material); p_gizmo->add_handles(handles, handles_material);
} }

View File

@ -38,9 +38,13 @@
#include "editor/editor_plugin.h" #include "editor/editor_plugin.h"
#include "editor/plugins/node_3d_editor_gizmos.h" #include "editor/plugins/node_3d_editor_gizmos.h"
class Gizmo3DHelper;
class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin { class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin); GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
Ref<Gizmo3DHelper> helper;
public: public:
virtual bool has_gizmo(Node3D *p_spatial) override; virtual bool has_gizmo(Node3D *p_spatial) override;
virtual String get_gizmo_name() const override; virtual String get_gizmo_name() const override;
@ -50,10 +54,12 @@ public:
virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override;
void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override;
virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override;
virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) override; virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) override;
CSGShape3DGizmoPlugin(); CSGShape3DGizmoPlugin();
~CSGShape3DGizmoPlugin();
}; };
class EditorPluginCSG : public EditorPlugin { class EditorPluginCSG : public EditorPlugin {