You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-17 14:11:06 +00:00
Use subgizmos instead of handles for Path3D curve points
This commit is contained in:
@@ -646,6 +646,18 @@ void Node3DEditorViewport::cancel_transform() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (se && se->gizmo.is_valid()) {
|
||||||
|
Vector<int> ids;
|
||||||
|
Vector<Transform3D> restore;
|
||||||
|
|
||||||
|
for (const KeyValue<int, Transform3D> &GE : se->subgizmos) {
|
||||||
|
ids.push_back(GE.key);
|
||||||
|
restore.push_back(GE.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
se->gizmo->commit_subgizmos(ids, restore, true);
|
||||||
|
}
|
||||||
|
|
||||||
sp->set_global_transform(se->original);
|
sp->set_global_transform(se->original);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8071,6 +8083,7 @@ void Node3DEditor::_bind_methods() {
|
|||||||
ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons);
|
ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons);
|
||||||
|
|
||||||
ClassDB::bind_method("update_all_gizmos", &Node3DEditor::update_all_gizmos);
|
ClassDB::bind_method("update_all_gizmos", &Node3DEditor::update_all_gizmos);
|
||||||
|
ClassDB::bind_method("update_transform_gizmo", &Node3DEditor::update_transform_gizmo);
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("transform_key_request"));
|
ADD_SIGNAL(MethodInfo("transform_key_request"));
|
||||||
ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
|
ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ public:
|
|||||||
RID sbox_instance_xray;
|
RID sbox_instance_xray;
|
||||||
RID sbox_instance_xray_offset;
|
RID sbox_instance_xray_offset;
|
||||||
Ref<EditorNode3DGizmo> gizmo;
|
Ref<EditorNode3DGizmo> gizmo;
|
||||||
HashMap<int, Transform3D> subgizmos; // map ID -> initial transform
|
HashMap<int, Transform3D> subgizmos; // Key: Subgizmo ID, Value: Initial subgizmo transform.
|
||||||
|
|
||||||
Node3DEditorSelectedItem() {
|
Node3DEditorSelectedItem() {
|
||||||
sp = nullptr;
|
sp = nullptr;
|
||||||
|
|||||||
@@ -200,22 +200,6 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res
|
|||||||
|
|
||||||
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
||||||
|
|
||||||
// Primary handles: position.
|
|
||||||
if (!p_secondary) {
|
|
||||||
// Special cas for primary handle, the handle id equals control point id.
|
|
||||||
const int idx = p_id;
|
|
||||||
if (p_cancel) {
|
|
||||||
c->set_point_position(idx, p_restore);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ur->create_action(TTR("Set Curve Point Position"));
|
|
||||||
ur->add_do_method(c.ptr(), "set_point_position", idx, c->get_point_position(idx));
|
|
||||||
ur->add_undo_method(c.ptr(), "set_point_position", idx, p_restore);
|
|
||||||
ur->commit_action();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Secondary handles: in, out, tilt.
|
// Secondary handles: in, out, tilt.
|
||||||
const HandleInfo info = _secondary_handles_info[p_id];
|
const HandleInfo info = _secondary_handles_info[p_id];
|
||||||
const int idx = info.point_idx;
|
const int idx = info.point_idx;
|
||||||
@@ -235,6 +219,7 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res
|
|||||||
ur->add_do_method(c.ptr(), "set_point_in", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_out(idx) : (-c->get_point_out(idx).normalized() * orig_in_length));
|
ur->add_do_method(c.ptr(), "set_point_in", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_out(idx) : (-c->get_point_out(idx).normalized() * orig_in_length));
|
||||||
ur->add_undo_method(c.ptr(), "set_point_in", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_in_length));
|
ur->add_undo_method(c.ptr(), "set_point_in", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_in_length));
|
||||||
}
|
}
|
||||||
|
|
||||||
ur->commit_action();
|
ur->commit_action();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -252,6 +237,7 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res
|
|||||||
ur->add_do_method(c.ptr(), "set_point_out", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_in(idx) : (-c->get_point_in(idx).normalized() * orig_out_length));
|
ur->add_do_method(c.ptr(), "set_point_out", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_in(idx) : (-c->get_point_in(idx).normalized() * orig_out_length));
|
||||||
ur->add_undo_method(c.ptr(), "set_point_out", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_out_length));
|
ur->add_undo_method(c.ptr(), "set_point_out", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_out_length));
|
||||||
}
|
}
|
||||||
|
|
||||||
ur->commit_action();
|
ur->commit_action();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -263,6 +249,7 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res
|
|||||||
ur->create_action(TTR("Set Curve Point Tilt"));
|
ur->create_action(TTR("Set Curve Point Tilt"));
|
||||||
ur->add_do_method(c.ptr(), "set_point_tilt", idx, c->get_point_tilt(idx));
|
ur->add_do_method(c.ptr(), "set_point_tilt", idx, c->get_point_tilt(idx));
|
||||||
ur->add_undo_method(c.ptr(), "set_point_tilt", idx, p_restore);
|
ur->add_undo_method(c.ptr(), "set_point_tilt", idx, p_restore);
|
||||||
|
|
||||||
ur->commit_action();
|
ur->commit_action();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -275,7 +262,7 @@ void Path3DGizmo::redraw() {
|
|||||||
Ref<StandardMaterial3D> path_material = gizmo_plugin->get_material("path_material", this);
|
Ref<StandardMaterial3D> path_material = gizmo_plugin->get_material("path_material", this);
|
||||||
Ref<StandardMaterial3D> path_thin_material = gizmo_plugin->get_material("path_thin_material", this);
|
Ref<StandardMaterial3D> path_thin_material = gizmo_plugin->get_material("path_thin_material", this);
|
||||||
Ref<StandardMaterial3D> path_tilt_material = gizmo_plugin->get_material("path_tilt_material", this);
|
Ref<StandardMaterial3D> path_tilt_material = gizmo_plugin->get_material("path_tilt_material", this);
|
||||||
Ref<StandardMaterial3D> handles_material = gizmo_plugin->get_material("handles");
|
Ref<StandardMaterial3D> path_tilt_muted_material = gizmo_plugin->get_material("path_tilt_muted_material", this);
|
||||||
Ref<StandardMaterial3D> sec_handles_material = gizmo_plugin->get_material("sec_handles");
|
Ref<StandardMaterial3D> sec_handles_material = gizmo_plugin->get_material("sec_handles");
|
||||||
|
|
||||||
Ref<Curve3D> c = path->get_curve();
|
Ref<Curve3D> c = path->get_curve();
|
||||||
@@ -353,48 +340,57 @@ void Path3DGizmo::redraw() {
|
|||||||
if (Path3DEditorPlugin::singleton->get_edited_path() == path) {
|
if (Path3DEditorPlugin::singleton->get_edited_path() == path) {
|
||||||
PackedVector3Array handle_lines;
|
PackedVector3Array handle_lines;
|
||||||
PackedVector3Array tilt_handle_lines;
|
PackedVector3Array tilt_handle_lines;
|
||||||
PackedVector3Array primary_handle_points;
|
|
||||||
PackedVector3Array secondary_handle_points;
|
PackedVector3Array secondary_handle_points;
|
||||||
PackedInt32Array collected_secondary_handle_ids; // Avoid shadowing member on Node3DEditorGizmo.
|
PackedInt32Array collected_secondary_handle_ids; // Avoid shadowing member on Node3DEditorGizmo.
|
||||||
|
|
||||||
_secondary_handles_info.resize(c->get_point_count() * 3);
|
_secondary_handles_info.resize(c->get_point_count() * 3);
|
||||||
|
|
||||||
for (int idx = 0; idx < c->get_point_count(); idx++) {
|
for (int idx = 0; idx < c->get_point_count(); idx++) {
|
||||||
// Collect primary-handles.
|
|
||||||
const Vector3 pos = c->get_point_position(idx);
|
const Vector3 pos = c->get_point_position(idx);
|
||||||
primary_handle_points.append(pos);
|
bool is_current_point_selected = is_subgizmo_selected(idx);
|
||||||
|
bool is_previous_point_selected = is_subgizmo_selected(idx - 1);
|
||||||
|
bool is_following_point_selected = is_subgizmo_selected(idx + 1);
|
||||||
|
|
||||||
HandleInfo info;
|
HandleInfo info;
|
||||||
info.point_idx = idx;
|
info.point_idx = idx;
|
||||||
|
|
||||||
// Collect in-handles except for the first point.
|
// Collect in-handles except for the first point.
|
||||||
if (idx > 0) {
|
if (idx > 0 && (is_current_point_selected || is_previous_point_selected)) {
|
||||||
|
const Vector3 in = c->get_point_in(idx);
|
||||||
|
|
||||||
|
// Display in-handles only when they are "initialized".
|
||||||
|
if (in.length_squared() > 0) {
|
||||||
info.type = HandleType::HANDLE_TYPE_IN;
|
info.type = HandleType::HANDLE_TYPE_IN;
|
||||||
const int handle_idx = idx * 3 + 0;
|
const int handle_idx = idx * 3 + 0;
|
||||||
collected_secondary_handle_ids.append(handle_idx);
|
collected_secondary_handle_ids.append(handle_idx);
|
||||||
_secondary_handles_info.write[handle_idx] = info;
|
_secondary_handles_info.write[handle_idx] = info;
|
||||||
|
|
||||||
const Vector3 in = c->get_point_in(idx);
|
|
||||||
secondary_handle_points.append(pos + in);
|
secondary_handle_points.append(pos + in);
|
||||||
handle_lines.append(pos);
|
handle_lines.append(pos);
|
||||||
handle_lines.append(pos + in);
|
handle_lines.append(pos + in);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect out-handles except for the last point.
|
// Collect out-handles except for the last point.
|
||||||
if (idx < c->get_point_count() - 1) {
|
if (idx < c->get_point_count() - 1 && (is_current_point_selected || is_following_point_selected)) {
|
||||||
|
const Vector3 out = c->get_point_out(idx);
|
||||||
|
|
||||||
|
// Display out-handles only when they are "initialized".
|
||||||
|
if (out.length_squared() > 0) {
|
||||||
info.type = HandleType::HANDLE_TYPE_OUT;
|
info.type = HandleType::HANDLE_TYPE_OUT;
|
||||||
const int handle_idx = idx * 3 + 1;
|
const int handle_idx = idx * 3 + 1;
|
||||||
collected_secondary_handle_ids.append(handle_idx);
|
collected_secondary_handle_ids.append(handle_idx);
|
||||||
_secondary_handles_info.write[handle_idx] = info;
|
_secondary_handles_info.write[handle_idx] = info;
|
||||||
|
|
||||||
const Vector3 out = c->get_point_out(idx);
|
|
||||||
secondary_handle_points.append(pos + out);
|
secondary_handle_points.append(pos + out);
|
||||||
handle_lines.append(pos);
|
handle_lines.append(pos);
|
||||||
handle_lines.append(pos + out);
|
handle_lines.append(pos + out);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect tilt-handles.
|
// Collect tilt-handles.
|
||||||
{
|
if (is_current_point_selected || is_previous_point_selected || is_following_point_selected) {
|
||||||
|
// Tilt handle.
|
||||||
{
|
{
|
||||||
info.type = HandleType::HANDLE_TYPE_TILT;
|
info.type = HandleType::HANDLE_TYPE_TILT;
|
||||||
const int handle_idx = idx * 3 + 2;
|
const int handle_idx = idx * 3 + 2;
|
||||||
@@ -423,7 +419,7 @@ void Path3DGizmo::redraw() {
|
|||||||
const Vector3 edge = sin(a) * side + cos(a) * up;
|
const Vector3 edge = sin(a) * side + cos(a) * up;
|
||||||
disk.append(pos + edge * disk_size);
|
disk.append(pos + edge * disk_size);
|
||||||
}
|
}
|
||||||
add_vertices(disk, path_tilt_material, Mesh::PRIMITIVE_LINE_STRIP);
|
add_vertices(disk, is_current_point_selected ? path_tilt_material : path_tilt_muted_material, Mesh::PRIMITIVE_LINE_STRIP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,21 +432,27 @@ void Path3DGizmo::redraw() {
|
|||||||
add_lines(tilt_handle_lines, path_tilt_material);
|
add_lines(tilt_handle_lines, path_tilt_material);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (primary_handle_points.size()) {
|
|
||||||
add_handles(primary_handle_points, handles_material);
|
|
||||||
}
|
|
||||||
if (secondary_handle_points.size()) {
|
if (secondary_handle_points.size()) {
|
||||||
add_handles(secondary_handle_points, sec_handles_material, collected_secondary_handle_ids, false, true);
|
add_handles(secondary_handle_points, sec_handles_material, collected_secondary_handle_ids, false, true);
|
||||||
}
|
}
|
||||||
|
// Draw the gizmo plugin manually, because handles are registered. In which case, the caller code skips drawing the gizmo plugin.
|
||||||
|
gizmo_plugin->redraw(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Path3DGizmo::_update_transform_gizmo() {
|
||||||
|
Node3DEditor::get_singleton()->update_transform_gizmo();
|
||||||
|
}
|
||||||
|
|
||||||
Path3DGizmo::Path3DGizmo(Path3D *p_path, float p_disk_size) {
|
Path3DGizmo::Path3DGizmo(Path3D *p_path, float p_disk_size) {
|
||||||
path = p_path;
|
path = p_path;
|
||||||
disk_size = p_disk_size;
|
disk_size = p_disk_size;
|
||||||
set_node_3d(p_path);
|
set_node_3d(p_path);
|
||||||
orig_in_length = 0;
|
orig_in_length = 0;
|
||||||
orig_out_length = 0;
|
orig_out_length = 0;
|
||||||
|
|
||||||
|
// Connecting to a signal once, rather than plaguing the implementation with calls to `Node3DEditor::update_transform_gizmo`.
|
||||||
|
path->connect("curve_changed", callable_mp(this, &Path3DGizmo::_update_transform_gizmo));
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) {
|
EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) {
|
||||||
@@ -819,10 +821,130 @@ Ref<EditorNode3DGizmo> Path3DGizmoPlugin::create_gizmo(Node3D *p_spatial) {
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Path3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
|
||||||
|
return Object::cast_to<Path3D>(p_spatial) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
String Path3DGizmoPlugin::get_gizmo_name() const {
|
String Path3DGizmoPlugin::get_gizmo_name() const {
|
||||||
return "Path3D";
|
return "Path3D";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Path3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
||||||
|
Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
|
||||||
|
ERR_FAIL_NULL(path);
|
||||||
|
|
||||||
|
Ref<Curve3D> curve = path->get_curve();
|
||||||
|
|
||||||
|
Ref<StandardMaterial3D> handle_material = get_material("handles", p_gizmo);
|
||||||
|
PackedVector3Array handles;
|
||||||
|
|
||||||
|
for (int idx = 0; idx < curve->get_point_count(); ++idx) {
|
||||||
|
// Collect handles.
|
||||||
|
const Vector3 pos = curve->get_point_position(idx);
|
||||||
|
|
||||||
|
handles.append(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handles.size()) {
|
||||||
|
p_gizmo->add_vertices(handles, handle_material, Mesh::PRIMITIVE_POINTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Path3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const {
|
||||||
|
Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
|
||||||
|
ERR_FAIL_NULL_V(path, -1);
|
||||||
|
Ref<Curve3D> curve = path->get_curve();
|
||||||
|
ERR_FAIL_COND_V(curve.is_null(), -1);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < curve->get_point_count(); ++idx) {
|
||||||
|
Vector3 pos = path->get_global_transform().xform(curve->get_point_position(idx));
|
||||||
|
if (p_camera->unproject_position(pos).distance_to(p_point) < 20) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<int> Path3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const {
|
||||||
|
Vector<int> contained_points;
|
||||||
|
|
||||||
|
Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
|
||||||
|
ERR_FAIL_NULL_V(path, contained_points);
|
||||||
|
Ref<Curve3D> curve = path->get_curve();
|
||||||
|
ERR_FAIL_COND_V(curve.is_null(), contained_points);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < curve->get_point_count(); ++idx) {
|
||||||
|
Vector3 pos = path->get_global_transform().xform(curve->get_point_position(idx));
|
||||||
|
bool is_contained_in_frustum = true;
|
||||||
|
for (int i = 0; i < p_frustum.size(); ++i) {
|
||||||
|
if (p_frustum[i].distance_to(pos) > 0) {
|
||||||
|
is_contained_in_frustum = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_contained_in_frustum) {
|
||||||
|
contained_points.push_back(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return contained_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3D Path3DGizmoPlugin::get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const {
|
||||||
|
Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
|
||||||
|
ERR_FAIL_NULL_V(path, Transform3D());
|
||||||
|
Ref<Curve3D> curve = path->get_curve();
|
||||||
|
ERR_FAIL_COND_V(curve.is_null(), Transform3D());
|
||||||
|
ERR_FAIL_INDEX_V(p_id, curve->get_point_count(), Transform3D());
|
||||||
|
|
||||||
|
Basis basis = transformation_locked_basis.has(p_id) ? transformation_locked_basis[p_id] : curve->get_point_baked_posture(p_id, true);
|
||||||
|
Vector3 pos = curve->get_point_position(p_id);
|
||||||
|
|
||||||
|
Transform3D t = Transform3D(basis, pos);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Path3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) {
|
||||||
|
Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
|
||||||
|
ERR_FAIL_NULL(path);
|
||||||
|
Ref<Curve3D> curve = path->get_curve();
|
||||||
|
ERR_FAIL_COND(curve.is_null());
|
||||||
|
ERR_FAIL_INDEX(p_id, curve->get_point_count());
|
||||||
|
|
||||||
|
if (!transformation_locked_basis.has(p_id)) {
|
||||||
|
transformation_locked_basis[p_id] = Basis(curve->get_point_baked_posture(p_id, true));
|
||||||
|
}
|
||||||
|
curve->set_point_position(p_id, p_transform.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Path3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) {
|
||||||
|
Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d());
|
||||||
|
ERR_FAIL_NULL(path);
|
||||||
|
Ref<Curve3D> curve = path->get_curve();
|
||||||
|
ERR_FAIL_COND(curve.is_null());
|
||||||
|
|
||||||
|
transformation_locked_basis.clear();
|
||||||
|
|
||||||
|
if (p_cancel) {
|
||||||
|
for (int i = 0; i < p_ids.size(); ++i) {
|
||||||
|
curve->set_point_position(p_ids[i], p_restore[i].origin);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
||||||
|
|
||||||
|
undo_redo->create_action(TTR("Set Curve Point Position"));
|
||||||
|
|
||||||
|
for (int i = 0; i < p_ids.size(); ++i) {
|
||||||
|
const int idx = p_ids[i];
|
||||||
|
undo_redo->add_do_method(curve.ptr(), "set_point_position", idx, curve->get_point_position(idx));
|
||||||
|
undo_redo->add_undo_method(curve.ptr(), "set_point_position", idx, p_restore[i].origin);
|
||||||
|
}
|
||||||
|
undo_redo->commit_action();
|
||||||
|
}
|
||||||
|
|
||||||
int Path3DGizmoPlugin::get_priority() const {
|
int Path3DGizmoPlugin::get_priority() const {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -835,6 +957,7 @@ Path3DGizmoPlugin::Path3DGizmoPlugin(float p_disk_size) {
|
|||||||
create_material("path_material", path_color);
|
create_material("path_material", path_color);
|
||||||
create_material("path_thin_material", Color(0.6, 0.6, 0.6));
|
create_material("path_thin_material", Color(0.6, 0.6, 0.6));
|
||||||
create_material("path_tilt_material", path_tilt_color);
|
create_material("path_tilt_material", path_tilt_color);
|
||||||
|
create_material("path_tilt_muted_material", path_tilt_color * 0.7);
|
||||||
create_handle_material("handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons)));
|
create_handle_material("handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons)));
|
||||||
create_handle_material("sec_handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorCurveHandle"), EditorStringName(EditorIcons)));
|
create_handle_material("sec_handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorCurveHandle"), EditorStringName(EditorIcons)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ class Path3DGizmo : public EditorNode3DGizmo {
|
|||||||
// Cache information of secondary handles.
|
// Cache information of secondary handles.
|
||||||
Vector<HandleInfo> _secondary_handles_info;
|
Vector<HandleInfo> _secondary_handles_info;
|
||||||
|
|
||||||
|
void _update_transform_gizmo();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual String get_handle_name(int p_id, bool p_secondary) const override;
|
virtual String get_handle_name(int p_id, bool p_secondary) const override;
|
||||||
virtual Variant get_handle_value(int p_id, bool p_secondary) const override;
|
virtual Variant get_handle_value(int p_id, bool p_secondary) const override;
|
||||||
@@ -78,11 +80,25 @@ class Path3DGizmoPlugin : public EditorNode3DGizmoPlugin {
|
|||||||
|
|
||||||
float disk_size = 0.8;
|
float disk_size = 0.8;
|
||||||
|
|
||||||
|
// Locking basis is meant to ensure a predictable behavior during translation of the curve points in "local space transform mode".
|
||||||
|
// Without the locking, the gizmo/point, in "local space transform mode", wouldn't follow a straight path and would curve and twitch in an unpredictable way.
|
||||||
|
HashMap<int, Basis> transformation_locked_basis;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Ref<EditorNode3DGizmo> create_gizmo(Node3D *p_spatial) override;
|
Ref<EditorNode3DGizmo> create_gizmo(Node3D *p_spatial) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual bool has_gizmo(Node3D *p_spatial) override;
|
||||||
String get_gizmo_name() const override;
|
String get_gizmo_name() const override;
|
||||||
|
|
||||||
|
virtual void redraw(EditorNode3DGizmo *p_gizmo) override;
|
||||||
|
|
||||||
|
virtual int subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const override;
|
||||||
|
virtual Vector<int> subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const override;
|
||||||
|
virtual Transform3D get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
|
||||||
|
virtual void set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) override;
|
||||||
|
virtual void commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel = false) override;
|
||||||
|
|
||||||
int get_priority() const override;
|
int get_priority() const override;
|
||||||
Path3DGizmoPlugin(float p_disk_size);
|
Path3DGizmoPlugin(float p_disk_size);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user