Add ability to transform parent nodes without affecting global transform of its children
Revert
This commit is contained in:
parent
220b0b2f74
commit
e8e3cf1fdb
3 changed files with 125 additions and 0 deletions
|
|
@ -625,6 +625,10 @@ void Node3DEditorViewport::cancel_transform() {
|
|||
sp->set_global_transform(se->original);
|
||||
}
|
||||
|
||||
for (const KeyValue<Node3D *, Transform3D> &pair : _edit.children_original_globals) {
|
||||
pair.key->set_global_transform(pair.value);
|
||||
}
|
||||
|
||||
collision_reposition = false;
|
||||
finish_transform();
|
||||
set_message(TTRC("Transform Aborted."), 3);
|
||||
|
|
@ -1136,6 +1140,24 @@ void Node3DEditorViewport::_compute_edit(const Point2 &p_point) {
|
|||
sel_item->original = sel_item->sp->get_global_gizmo_transform();
|
||||
}
|
||||
}
|
||||
|
||||
if (spatial_editor->is_preserve_children_transform_enabled() && _edit.children_original_globals.is_empty()) {
|
||||
const List<Node *> &selection = editor_selection->get_top_selected_node_list();
|
||||
for (Node *E : selection) {
|
||||
Node3D *sp = Object::cast_to<Node3D>(E);
|
||||
if (!sp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int child_count = sp->get_child_count();
|
||||
for (int i = 0; i < child_count; i++) {
|
||||
Node3D *child = Object::cast_to<Node3D>(sp->get_child(i));
|
||||
if (child) {
|
||||
_edit.children_original_globals[child] = child->get_global_transform();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Key _get_key_modifier_setting(const String &p_property) {
|
||||
|
|
@ -1437,11 +1459,33 @@ void Node3DEditorViewport::_transform_gizmo_apply(Node3D *p_node, const Transfor
|
|||
return;
|
||||
}
|
||||
|
||||
bool preserve_children = spatial_editor->is_preserve_children_transform_enabled();
|
||||
|
||||
Vector<Transform3D> children_global_transforms;
|
||||
Vector<Node3D *> node3d_children;
|
||||
|
||||
if (preserve_children) {
|
||||
int child_count = p_node->get_child_count();
|
||||
for (int i = 0; i < child_count; i++) {
|
||||
Node3D *child = Object::cast_to<Node3D>(p_node->get_child(i));
|
||||
if (child) {
|
||||
children_global_transforms.push_back(child->get_global_transform());
|
||||
node3d_children.push_back(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_local) {
|
||||
p_node->set_transform(p_transform);
|
||||
} else {
|
||||
p_node->set_global_transform(p_transform);
|
||||
}
|
||||
|
||||
if (preserve_children) {
|
||||
for (int i = 0; i < node3d_children.size(); i++) {
|
||||
node3d_children[i]->set_global_transform(children_global_transforms[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local, bool p_orthogonal, bool p_view_axis) {
|
||||
|
|
@ -5160,6 +5204,8 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_
|
|||
|
||||
void Node3DEditorViewport::begin_transform(TransformMode p_mode, bool instant) {
|
||||
if (get_selected_count() > 0) {
|
||||
_edit.children_original_globals.clear();
|
||||
|
||||
_edit.mode = p_mode;
|
||||
_compute_edit(_edit.mouse_pos);
|
||||
_edit.instant = instant;
|
||||
|
|
@ -5218,6 +5264,18 @@ void Node3DEditorViewport::commit_transform() {
|
|||
undo_redo->add_do_method(sp, "set_transform", sp->get_local_gizmo_transform());
|
||||
undo_redo->add_undo_method(sp, "set_transform", se->original_local);
|
||||
}
|
||||
|
||||
if (!_edit.children_original_globals.is_empty()) {
|
||||
for (const KeyValue<Node3D *, Transform3D> &pair : _edit.children_original_globals) {
|
||||
Node3D *child = pair.key;
|
||||
Transform3D original_global = pair.value;
|
||||
Transform3D current_global = child->get_global_transform();
|
||||
|
||||
undo_redo->add_do_method(child, "set_global_transform", current_global);
|
||||
undo_redo->add_undo_method(child, "set_global_transform", original_global);
|
||||
}
|
||||
}
|
||||
|
||||
undo_redo->commit_action();
|
||||
|
||||
collision_reposition = false;
|
||||
|
|
@ -5646,6 +5704,7 @@ void Node3DEditorViewport::finish_transform() {
|
|||
_edit.accumulated_rotation_angle = 0.0;
|
||||
_edit.rotation_angle = 0.0;
|
||||
_edit.gizmo_initiated = false;
|
||||
_edit.children_original_globals.clear();
|
||||
spatial_editor->set_local_coords_enabled(_edit.original_local);
|
||||
spatial_editor->update_transform_gizmo();
|
||||
surface->queue_redraw();
|
||||
|
|
@ -6692,6 +6751,7 @@ Dictionary Node3DEditor::get_state() const {
|
|||
d["scale_snap"] = snap_scale_value;
|
||||
|
||||
d["local_coords"] = tool_option_button[TOOL_OPT_LOCAL_COORDS]->is_pressed();
|
||||
d["preserve_children_transform"] = tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->is_pressed();
|
||||
|
||||
int vc = 0;
|
||||
if (view_layout_menu->get_popup()->is_item_checked(view_layout_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT))) {
|
||||
|
|
@ -6786,6 +6846,10 @@ void Node3DEditor::set_state(const Dictionary &p_state) {
|
|||
|
||||
_snap_update();
|
||||
|
||||
if (d.has("preserve_children_transform")) {
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_pressed(d["preserve_children_transform"]);
|
||||
}
|
||||
|
||||
if (d.has("local_coords")) {
|
||||
tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_pressed(d["local_coords"]);
|
||||
update_transform_gizmo();
|
||||
|
|
@ -7028,6 +7092,47 @@ void Node3DEditor::_menu_item_toggled(bool pressed, int p_option) {
|
|||
viewports[i]->update_transform_gizmo_highlight();
|
||||
}
|
||||
} break;
|
||||
|
||||
case MENU_TOOL_PRESERVE_CHILDREN_TRANSFORM: {
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_pressed(pressed);
|
||||
if (pressed) {
|
||||
EditorNode::get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &Node3DEditor::_undo_redo_inspector_callback));
|
||||
} else {
|
||||
EditorNode::get_editor_data().remove_undo_redo_inspector_hook_callback(callable_mp(this, &Node3DEditor::_undo_redo_inspector_callback));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void Node3DEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p_edited, const String &p_property, const Variant &p_new_value) {
|
||||
Node3D *node = Object::cast_to<Node3D>(p_edited);
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const char *transform_properties[] = { "position", "rotation", "scale", "quaternion", "basis", "transform", nullptr };
|
||||
bool is_transform_prop = false;
|
||||
for (int i = 0; transform_properties[i]; i++) {
|
||||
if (p_property == transform_properties[i]) {
|
||||
is_transform_prop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_transform_prop) {
|
||||
return;
|
||||
}
|
||||
|
||||
EditorUndoRedoManager *undo_redo = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
|
||||
ERR_FAIL_NULL(undo_redo);
|
||||
|
||||
int child_count = node->get_child_count();
|
||||
for (int i = 0; i < child_count; i++) {
|
||||
Node3D *child = Object::cast_to<Node3D>(node->get_child(i));
|
||||
if (child) {
|
||||
Transform3D child_global = child->get_global_transform();
|
||||
undo_redo->add_do_method(child, "set_global_transform", child_global);
|
||||
undo_redo->add_undo_method(child, "set_global_transform", child_global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8619,6 +8724,7 @@ void Node3DEditor::_update_theme() {
|
|||
tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_button_icon(get_editor_theme_icon(SNAME("Object")));
|
||||
tool_option_button[TOOL_OPT_USE_SNAP]->set_button_icon(get_editor_theme_icon(SNAME("Snap")));
|
||||
tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_button_icon(get_editor_theme_icon(SNAME("Trackball")));
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_button_icon(get_editor_theme_icon(SNAME("Pin")));
|
||||
|
||||
view_layout_menu->get_popup()->set_item_icon(view_layout_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_editor_theme_icon(SNAME("Panels1")));
|
||||
view_layout_menu->get_popup()->set_item_icon(view_layout_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_editor_theme_icon(SNAME("Panels2")));
|
||||
|
|
@ -9596,6 +9702,16 @@ Node3DEditor::Node3DEditor() {
|
|||
tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_shortcut_context(this);
|
||||
tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_accessibility_name(TTRC("Use Trackball"));
|
||||
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM] = memnew(Button);
|
||||
main_menu_hbox->add_child(tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]);
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_toggle_mode(true);
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->connect(SceneStringName(toggled), callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_PRESERVE_CHILDREN_TRANSFORM));
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_shortcut(ED_SHORTCUT("spatial_editor/preserve_children_transform", TTRC("Preserve Children Transform"), Key::P));
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_shortcut_context(this);
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_accessibility_name(TTRC("Preserve Children Transform"));
|
||||
tool_option_button[TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->set_tooltip_text(TTRC("When enabled, transforming a node will preserve the global transform of its children.\nThis also applies when editing transform properties in the Inspector."));
|
||||
|
||||
main_menu_hbox->add_child(memnew(VSeparator));
|
||||
sun_button = memnew(Button);
|
||||
sun_button->set_tooltip_text(TTRC("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled."));
|
||||
|
|
|
|||
|
|
@ -356,6 +356,8 @@ private:
|
|||
Vector3 initial_click_vector;
|
||||
Vector3 previous_rotation_vector;
|
||||
bool gizmo_initiated = false;
|
||||
|
||||
HashMap<Node3D *, Transform3D> children_original_globals;
|
||||
} _edit;
|
||||
|
||||
Ref<View3DController> view_3d_controller;
|
||||
|
|
@ -583,6 +585,7 @@ public:
|
|||
TOOL_OPT_LOCAL_COORDS,
|
||||
TOOL_OPT_USE_SNAP,
|
||||
TOOL_OPT_USE_TRACKBALL,
|
||||
TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM,
|
||||
TOOL_OPT_MAX
|
||||
};
|
||||
|
||||
|
|
@ -686,6 +689,7 @@ private:
|
|||
MENU_TOOL_LOCAL_COORDS,
|
||||
MENU_TOOL_USE_SNAP,
|
||||
MENU_TOOL_USE_TRACKBALL,
|
||||
MENU_TOOL_PRESERVE_CHILDREN_TRANSFORM,
|
||||
MENU_TRANSFORM_CONFIGURE_SNAP,
|
||||
MENU_TRANSFORM_DIALOG,
|
||||
MENU_VIEW_USE_1_VIEWPORT,
|
||||
|
|
@ -877,6 +881,8 @@ private:
|
|||
|
||||
void _update_theme();
|
||||
|
||||
void _undo_redo_inspector_callback(Object *p_undo_redo, Object *p_edited, const String &p_property, const Variant &p_new_value);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
//void _gui_input(InputEvent p_event);
|
||||
|
|
@ -901,6 +907,7 @@ public:
|
|||
ToolMode get_tool_mode() const { return tool_mode; }
|
||||
bool are_local_coords_enabled() const { return tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); }
|
||||
void set_local_coords_enabled(bool on) const { tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_pressed(on); }
|
||||
bool is_preserve_children_transform_enabled() const { return tool_option_button[Node3DEditor::TOOL_OPT_PRESERVE_CHILDREN_TRANSFORM]->is_pressed(); }
|
||||
bool is_snap_enabled() const { return snap_enabled ^ snap_key_enabled; }
|
||||
real_t get_translate_snap() const;
|
||||
real_t get_rotate_snap() const;
|
||||
|
|
|
|||
|
|
@ -801,6 +801,8 @@ void CSGShape3D::update_shape() {
|
|||
|
||||
set_base(root_mesh->get_rid());
|
||||
|
||||
update_gizmos();
|
||||
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
_update_collision_faces();
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue