Merge pull request #63249 from V-Sekai/animation_tree_editor_read_only
Add read-only mode to AnimationTreeEditor plugins
This commit is contained in:
commit
f9998455ce
|
@ -221,6 +221,9 @@
|
|||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="arrange_nodes_button_hidden" type="bool" setter="set_arrange_nodes_button_hidden" getter="is_arrange_nodes_button_hidden" default="false">
|
||||
If [code]true[/code], the Arrange Nodes button is hidden.
|
||||
</member>
|
||||
<member name="clip_contents" type="bool" setter="set_clip_contents" getter="is_clipping_contents" overrides="Control" default="true" />
|
||||
<member name="connection_lines_antialiased" type="bool" setter="set_connection_lines_antialiased" getter="is_connection_lines_antialiased" default="true">
|
||||
If [code]true[/code], the lines between nodes will use antialiasing.
|
||||
|
|
|
@ -156,7 +156,7 @@
|
|||
<description>
|
||||
Sets properties of the slot with ID [param idx].
|
||||
If [param enable_left]/[param enable_right], a port will appear and the slot will be able to be connected from this side.
|
||||
[param type_left]/[param type_right] is an arbitrary type of the port. Only ports with the same type values can be connected.
|
||||
[param type_left]/[param type_right] is an arbitrary type of the port. Only ports with the same type values can be connected and negative values will disallow all connections to be made via user inputs.
|
||||
[param color_left]/[param color_right] is the tint of the port's icon on this side.
|
||||
[param custom_left]/[param custom_right] is a custom texture for this side's port.
|
||||
[b]Note:[/b] This method only sets properties of the slot. To create the slot, add a [Control]-derived child to the GraphNode.
|
||||
|
@ -208,7 +208,7 @@
|
|||
<param index="0" name="idx" type="int" />
|
||||
<param index="1" name="type_left" type="int" />
|
||||
<description>
|
||||
Sets the left (input) type of the slot [param idx] to [param type_left].
|
||||
Sets the left (input) type of the slot [param idx] to [param type_left]. If the value is negative, all connections will be disallowed to be created via user inputs.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_slot_type_right">
|
||||
|
@ -216,7 +216,7 @@
|
|||
<param index="0" name="idx" type="int" />
|
||||
<param index="1" name="type_right" type="int" />
|
||||
<description>
|
||||
Sets the right (output) type of the slot [param idx] to [param type_right].
|
||||
Sets the right (output) type of the slot [param idx] to [param type_right]. If the value is negative, all connections will be disallowed to be created via user inputs.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
|
@ -224,6 +224,9 @@
|
|||
<member name="comment" type="bool" setter="set_comment" getter="is_comment" default="false">
|
||||
If [code]true[/code], the GraphNode is a comment node.
|
||||
</member>
|
||||
<member name="draggable" type="bool" setter="set_draggable" getter="is_draggable" default="true">
|
||||
If [code]true[/code], the user can drag the GraphNode.
|
||||
</member>
|
||||
<member name="language" type="String" setter="set_language" getter="get_language" default="""">
|
||||
Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
|
||||
</member>
|
||||
|
@ -239,6 +242,9 @@
|
|||
If [code]true[/code], the user can resize the GraphNode.
|
||||
[b]Note:[/b] Dragging the handle will only emit the [signal resize_request] signal, the GraphNode needs to be resized manually.
|
||||
</member>
|
||||
<member name="selectable" type="bool" setter="set_selectable" getter="is_selectable" default="true">
|
||||
If [code]true[/code], the user can select the GraphNode.
|
||||
</member>
|
||||
<member name="selected" type="bool" setter="set_selected" getter="is_selected" default="false">
|
||||
If [code]true[/code], the GraphNode is selected.
|
||||
</member>
|
||||
|
|
|
@ -149,6 +149,10 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) {
|
|||
}
|
||||
|
||||
void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<InputEventMouseButton> mb = p_event;
|
||||
|
||||
if (grabbing_grabber) {
|
||||
|
|
|
@ -48,7 +48,9 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
|
||||
if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) {
|
||||
if (selected_point != -1) {
|
||||
_erase_selected();
|
||||
if (!read_only) {
|
||||
_erase_selected();
|
||||
}
|
||||
accept_event();
|
||||
}
|
||||
}
|
||||
|
@ -56,62 +58,64 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
Ref<InputEventMouseButton> mb = p_event;
|
||||
|
||||
if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (mb->get_button_index() == MouseButton::LEFT && tool_create->is_pressed()))) {
|
||||
menu->clear();
|
||||
animations_menu->clear();
|
||||
animations_to_add.clear();
|
||||
if (!read_only) {
|
||||
menu->clear();
|
||||
animations_menu->clear();
|
||||
animations_to_add.clear();
|
||||
|
||||
List<StringName> classes;
|
||||
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
|
||||
classes.sort_custom<StringName::AlphCompare>();
|
||||
List<StringName> classes;
|
||||
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
|
||||
classes.sort_custom<StringName::AlphCompare>();
|
||||
|
||||
menu->add_submenu_item(TTR("Add Animation"), "animations");
|
||||
menu->add_submenu_item(TTR("Add Animation"), "animations");
|
||||
|
||||
AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
|
||||
ERR_FAIL_COND(!gp);
|
||||
AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
|
||||
ERR_FAIL_COND(!gp);
|
||||
|
||||
if (gp->has_node(gp->get_animation_player())) {
|
||||
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
|
||||
if (gp->has_node(gp->get_animation_player())) {
|
||||
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
|
||||
|
||||
if (ap) {
|
||||
List<StringName> names;
|
||||
ap->get_animation_list(&names);
|
||||
if (ap) {
|
||||
List<StringName> names;
|
||||
ap->get_animation_list(&names);
|
||||
|
||||
for (const StringName &E : names) {
|
||||
animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E);
|
||||
animations_to_add.push_back(E);
|
||||
for (const StringName &E : names) {
|
||||
animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E);
|
||||
animations_to_add.push_back(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const StringName &E : classes) {
|
||||
String name = String(E).replace_first("AnimationNode", "");
|
||||
if (name == "Animation" || name == "StartState" || name == "EndState") {
|
||||
continue;
|
||||
for (const StringName &E : classes) {
|
||||
String name = String(E).replace_first("AnimationNode", "");
|
||||
if (name == "Animation" || name == "StartState" || name == "EndState") {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = menu->get_item_count();
|
||||
menu->add_item(vformat(TTR("Add %s"), name), idx);
|
||||
menu->set_item_metadata(idx, E);
|
||||
}
|
||||
|
||||
int idx = menu->get_item_count();
|
||||
menu->add_item(vformat(TTR("Add %s"), name), idx);
|
||||
menu->set_item_metadata(idx, E);
|
||||
}
|
||||
|
||||
Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
if (clipb.is_valid()) {
|
||||
Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
if (clipb.is_valid()) {
|
||||
menu->add_separator();
|
||||
menu->add_item(TTR("Paste"), MENU_PASTE);
|
||||
}
|
||||
menu->add_separator();
|
||||
menu->add_item(TTR("Paste"), MENU_PASTE);
|
||||
}
|
||||
menu->add_separator();
|
||||
menu->add_item(TTR("Load..."), MENU_LOAD_FILE);
|
||||
menu->add_item(TTR("Load..."), MENU_LOAD_FILE);
|
||||
|
||||
menu->set_position(blend_space_draw->get_screen_position() + mb->get_position());
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
menu->set_position(blend_space_draw->get_screen_position() + mb->get_position());
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
|
||||
add_point_pos = (mb->get_position() / blend_space_draw->get_size()).x;
|
||||
add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
add_point_pos += blend_space->get_min_space();
|
||||
add_point_pos = (mb->get_position() / blend_space_draw->get_size()).x;
|
||||
add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
add_point_pos += blend_space->get_min_space();
|
||||
|
||||
if (snap->is_pressed()) {
|
||||
add_point_pos = Math::snapped(add_point_pos, blend_space->get_snap());
|
||||
if (snap->is_pressed()) {
|
||||
add_point_pos = Math::snapped(add_point_pos, blend_space->get_snap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,31 +142,33 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
}
|
||||
|
||||
if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MouseButton::LEFT) {
|
||||
if (dragging_selected) {
|
||||
// move
|
||||
float point = blend_space->get_blend_point_position(selected_point);
|
||||
point += drag_ofs.x;
|
||||
if (!read_only) {
|
||||
if (dragging_selected) {
|
||||
// move
|
||||
float point = blend_space->get_blend_point_position(selected_point);
|
||||
point += drag_ofs.x;
|
||||
|
||||
if (snap->is_pressed()) {
|
||||
point = Math::snapped(point, blend_space->get_snap());
|
||||
if (snap->is_pressed()) {
|
||||
point = Math::snapped(point, blend_space->get_snap());
|
||||
}
|
||||
|
||||
updating = true;
|
||||
undo_redo->create_action(TTR("Move Node Point"));
|
||||
undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point);
|
||||
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
|
||||
undo_redo->add_do_method(this, "_update_space");
|
||||
undo_redo->add_undo_method(this, "_update_space");
|
||||
undo_redo->add_do_method(this, "_update_edited_point_pos");
|
||||
undo_redo->add_undo_method(this, "_update_edited_point_pos");
|
||||
undo_redo->commit_action();
|
||||
updating = false;
|
||||
_update_edited_point_pos();
|
||||
}
|
||||
|
||||
updating = true;
|
||||
undo_redo->create_action(TTR("Move Node Point"));
|
||||
undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point);
|
||||
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
|
||||
undo_redo->add_do_method(this, "_update_space");
|
||||
undo_redo->add_undo_method(this, "_update_space");
|
||||
undo_redo->add_do_method(this, "_update_edited_point_pos");
|
||||
undo_redo->add_undo_method(this, "_update_edited_point_pos");
|
||||
undo_redo->commit_action();
|
||||
updating = false;
|
||||
_update_edited_point_pos();
|
||||
dragging_selected_attempt = false;
|
||||
dragging_selected = false;
|
||||
blend_space_draw->update();
|
||||
}
|
||||
|
||||
dragging_selected_attempt = false;
|
||||
dragging_selected = false;
|
||||
blend_space_draw->update();
|
||||
}
|
||||
|
||||
// *set* the blend
|
||||
|
@ -255,10 +261,12 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
|
|||
for (int i = 0; i < blend_space->get_blend_point_count(); i++) {
|
||||
float point = blend_space->get_blend_point_position(i);
|
||||
|
||||
if (dragging_selected && selected_point == i) {
|
||||
point += drag_ofs.x;
|
||||
if (snap->is_pressed()) {
|
||||
point = Math::snapped(point, blend_space->get_snap());
|
||||
if (!read_only) {
|
||||
if (dragging_selected && selected_point == i) {
|
||||
point += drag_ofs.x;
|
||||
if (snap->is_pressed()) {
|
||||
point = Math::snapped(point, blend_space->get_snap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +483,7 @@ void AnimationNodeBlendSpace1DEditor::_update_edited_point_pos() {
|
|||
|
||||
void AnimationNodeBlendSpace1DEditor::_update_tool_erase() {
|
||||
bool point_valid = selected_point >= 0 && selected_point < blend_space->get_blend_point_count();
|
||||
tool_erase->set_disabled(!point_valid);
|
||||
tool_erase->set_disabled(!point_valid || read_only);
|
||||
|
||||
if (point_valid) {
|
||||
Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point);
|
||||
|
@ -486,7 +494,11 @@ void AnimationNodeBlendSpace1DEditor::_update_tool_erase() {
|
|||
open_editor->hide();
|
||||
}
|
||||
|
||||
edit_hb->show();
|
||||
if (!read_only) {
|
||||
edit_hb->show();
|
||||
} else {
|
||||
edit_hb->hide();
|
||||
}
|
||||
} else {
|
||||
edit_hb->hide();
|
||||
}
|
||||
|
@ -590,10 +602,20 @@ bool AnimationNodeBlendSpace1DEditor::can_edit(const Ref<AnimationNode> &p_node)
|
|||
|
||||
void AnimationNodeBlendSpace1DEditor::edit(const Ref<AnimationNode> &p_node) {
|
||||
blend_space = p_node;
|
||||
read_only = false;
|
||||
|
||||
if (!blend_space.is_null()) {
|
||||
read_only = EditorNode::get_singleton()->is_resource_read_only(blend_space);
|
||||
|
||||
_update_space();
|
||||
}
|
||||
|
||||
tool_create->set_disabled(read_only);
|
||||
edit_value->set_editable(!read_only);
|
||||
label_value->set_editable(!read_only);
|
||||
min_value->set_editable(!read_only);
|
||||
max_value->set_editable(!read_only);
|
||||
sync->set_disabled(read_only);
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace1DEditor *AnimationNodeBlendSpace1DEditor::singleton = nullptr;
|
||||
|
|
|
@ -46,6 +46,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
|
|||
GDCLASS(AnimationNodeBlendSpace1DEditor, AnimationTreeNodeEditorPlugin);
|
||||
|
||||
Ref<AnimationNodeBlendSpace1D> blend_space;
|
||||
bool read_only = false;
|
||||
|
||||
HBoxContainer *goto_parent_hb = nullptr;
|
||||
Button *goto_parent = nullptr;
|
||||
|
|
|
@ -60,11 +60,29 @@ void AnimationNodeBlendSpace2DEditor::edit(const Ref<AnimationNode> &p_node) {
|
|||
blend_space->disconnect("triangles_updated", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_blend_space_changed));
|
||||
}
|
||||
blend_space = p_node;
|
||||
read_only = false;
|
||||
|
||||
if (!blend_space.is_null()) {
|
||||
read_only = EditorNode::get_singleton()->is_resource_read_only(blend_space);
|
||||
|
||||
blend_space->connect("triangles_updated", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_blend_space_changed));
|
||||
_update_space();
|
||||
}
|
||||
|
||||
tool_create->set_disabled(read_only);
|
||||
interpolation->set_disabled(read_only);
|
||||
max_x_value->set_editable(!read_only);
|
||||
min_x_value->set_editable(!read_only);
|
||||
max_y_value->set_editable(!read_only);
|
||||
min_y_value->set_editable(!read_only);
|
||||
label_x->set_editable(!read_only);
|
||||
label_y->set_editable(!read_only);
|
||||
edit_x->set_editable(!read_only);
|
||||
edit_y->set_editable(!read_only);
|
||||
tool_triangle->set_disabled(read_only);
|
||||
auto_triangles->set_disabled(read_only);
|
||||
sync->set_disabled(read_only);
|
||||
interpolation->set_disabled(read_only);
|
||||
}
|
||||
|
||||
StringName AnimationNodeBlendSpace2DEditor::get_blend_position_path() const {
|
||||
|
@ -76,7 +94,9 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
Ref<InputEventKey> k = p_event;
|
||||
if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) {
|
||||
if (selected_point != -1 || selected_triangle != -1) {
|
||||
_erase_selected();
|
||||
if (!read_only) {
|
||||
_erase_selected();
|
||||
}
|
||||
accept_event();
|
||||
}
|
||||
}
|
||||
|
@ -84,57 +104,59 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
Ref<InputEventMouseButton> mb = p_event;
|
||||
|
||||
if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (mb->get_button_index() == MouseButton::LEFT && tool_create->is_pressed()))) {
|
||||
menu->clear();
|
||||
animations_menu->clear();
|
||||
animations_to_add.clear();
|
||||
List<StringName> classes;
|
||||
classes.sort_custom<StringName::AlphCompare>();
|
||||
if (!read_only) {
|
||||
menu->clear();
|
||||
animations_menu->clear();
|
||||
animations_to_add.clear();
|
||||
List<StringName> classes;
|
||||
classes.sort_custom<StringName::AlphCompare>();
|
||||
|
||||
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
|
||||
menu->add_submenu_item(TTR("Add Animation"), "animations");
|
||||
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
|
||||
menu->add_submenu_item(TTR("Add Animation"), "animations");
|
||||
|
||||
AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
|
||||
ERR_FAIL_COND(!gp);
|
||||
if (gp && gp->has_node(gp->get_animation_player())) {
|
||||
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
|
||||
if (ap) {
|
||||
List<StringName> names;
|
||||
ap->get_animation_list(&names);
|
||||
for (const StringName &E : names) {
|
||||
animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E);
|
||||
animations_to_add.push_back(E);
|
||||
AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
|
||||
ERR_FAIL_COND(!gp);
|
||||
if (gp && gp->has_node(gp->get_animation_player())) {
|
||||
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
|
||||
if (ap) {
|
||||
List<StringName> names;
|
||||
ap->get_animation_list(&names);
|
||||
for (const StringName &E : names) {
|
||||
animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E);
|
||||
animations_to_add.push_back(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const StringName &E : classes) {
|
||||
String name = String(E).replace_first("AnimationNode", "");
|
||||
if (name == "Animation" || name == "StartState" || name == "EndState") {
|
||||
continue; // nope
|
||||
for (const StringName &E : classes) {
|
||||
String name = String(E).replace_first("AnimationNode", "");
|
||||
if (name == "Animation" || name == "StartState" || name == "EndState") {
|
||||
continue; // nope
|
||||
}
|
||||
int idx = menu->get_item_count();
|
||||
menu->add_item(vformat(TTR("Add %s"), name), idx);
|
||||
menu->set_item_metadata(idx, E);
|
||||
}
|
||||
int idx = menu->get_item_count();
|
||||
menu->add_item(vformat(TTR("Add %s"), name), idx);
|
||||
menu->set_item_metadata(idx, E);
|
||||
}
|
||||
|
||||
Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
if (clipb.is_valid()) {
|
||||
Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
if (clipb.is_valid()) {
|
||||
menu->add_separator();
|
||||
menu->add_item(TTR("Paste"), MENU_PASTE);
|
||||
}
|
||||
menu->add_separator();
|
||||
menu->add_item(TTR("Paste"), MENU_PASTE);
|
||||
}
|
||||
menu->add_separator();
|
||||
menu->add_item(TTR("Load..."), MENU_LOAD_FILE);
|
||||
menu->add_item(TTR("Load..."), MENU_LOAD_FILE);
|
||||
|
||||
menu->set_position(blend_space_draw->get_screen_position() + mb->get_position());
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
add_point_pos = (mb->get_position() / blend_space_draw->get_size());
|
||||
add_point_pos.y = 1.0 - add_point_pos.y;
|
||||
add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
add_point_pos += blend_space->get_min_space();
|
||||
menu->set_position(blend_space_draw->get_screen_position() + mb->get_position());
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
add_point_pos = (mb->get_position() / blend_space_draw->get_size());
|
||||
add_point_pos.y = 1.0 - add_point_pos.y;
|
||||
add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
add_point_pos += blend_space->get_min_space();
|
||||
|
||||
if (snap->is_pressed()) {
|
||||
add_point_pos = add_point_pos.snapped(blend_space->get_snap());
|
||||
if (snap->is_pressed()) {
|
||||
add_point_pos = add_point_pos.snapped(blend_space->get_snap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,17 +244,19 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
point = point.snapped(blend_space->get_snap());
|
||||
}
|
||||
|
||||
updating = true;
|
||||
undo_redo->create_action(TTR("Move Node Point"));
|
||||
undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point);
|
||||
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
|
||||
undo_redo->add_do_method(this, "_update_space");
|
||||
undo_redo->add_undo_method(this, "_update_space");
|
||||
undo_redo->add_do_method(this, "_update_edited_point_pos");
|
||||
undo_redo->add_undo_method(this, "_update_edited_point_pos");
|
||||
undo_redo->commit_action();
|
||||
updating = false;
|
||||
_update_edited_point_pos();
|
||||
if (!read_only) {
|
||||
updating = true;
|
||||
undo_redo->create_action(TTR("Move Node Point"));
|
||||
undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point);
|
||||
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point));
|
||||
undo_redo->add_do_method(this, "_update_space");
|
||||
undo_redo->add_undo_method(this, "_update_space");
|
||||
undo_redo->add_do_method(this, "_update_edited_point_pos");
|
||||
undo_redo->add_undo_method(this, "_update_edited_point_pos");
|
||||
undo_redo->commit_action();
|
||||
updating = false;
|
||||
_update_edited_point_pos();
|
||||
}
|
||||
}
|
||||
dragging_selected_attempt = false;
|
||||
dragging_selected = false;
|
||||
|
@ -259,7 +283,9 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
|
||||
if (mm.is_valid() && dragging_selected_attempt) {
|
||||
dragging_selected = true;
|
||||
drag_ofs = ((mm->get_position() - drag_from) / blend_space_draw->get_size()) * (blend_space->get_max_space() - blend_space->get_min_space()) * Vector2(1, -1);
|
||||
if (!read_only) {
|
||||
drag_ofs = ((mm->get_position() - drag_from) / blend_space_draw->get_size()) * (blend_space->get_max_space() - blend_space->get_min_space()) * Vector2(1, -1);
|
||||
}
|
||||
blend_space_draw->update();
|
||||
_update_edited_point_pos();
|
||||
}
|
||||
|
@ -355,7 +381,10 @@ void AnimationNodeBlendSpace2DEditor::_add_animation_type(int p_index) {
|
|||
}
|
||||
|
||||
void AnimationNodeBlendSpace2DEditor::_update_tool_erase() {
|
||||
tool_erase->set_disabled(!(selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) && !(selected_triangle >= 0 && selected_triangle < blend_space->get_triangle_count()));
|
||||
tool_erase->set_disabled(
|
||||
(!(selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) && !(selected_triangle >= 0 && selected_triangle < blend_space->get_triangle_count())) ||
|
||||
read_only);
|
||||
|
||||
if (selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) {
|
||||
Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point);
|
||||
if (AnimationTreeEditor::get_singleton()->can_edit(an)) {
|
||||
|
@ -363,7 +392,11 @@ void AnimationNodeBlendSpace2DEditor::_update_tool_erase() {
|
|||
} else {
|
||||
open_editor->hide();
|
||||
}
|
||||
edit_hb->show();
|
||||
if (!read_only) {
|
||||
edit_hb->show();
|
||||
} else {
|
||||
edit_hb->hide();
|
||||
}
|
||||
} else {
|
||||
edit_hb->hide();
|
||||
}
|
||||
|
@ -503,10 +536,12 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
|
|||
points.clear();
|
||||
for (int i = 0; i < blend_space->get_blend_point_count(); i++) {
|
||||
Vector2 point = blend_space->get_blend_point_position(i);
|
||||
if (dragging_selected && selected_point == i) {
|
||||
point += drag_ofs;
|
||||
if (snap->is_pressed()) {
|
||||
point = point.snapped(blend_space->get_snap());
|
||||
if (!read_only) {
|
||||
if (dragging_selected && selected_point == i) {
|
||||
point += drag_ofs;
|
||||
if (snap->is_pressed()) {
|
||||
point = point.snapped(blend_space->get_snap());
|
||||
}
|
||||
}
|
||||
}
|
||||
point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
|
|
|
@ -46,6 +46,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
|
|||
GDCLASS(AnimationNodeBlendSpace2DEditor, AnimationTreeNodeEditorPlugin);
|
||||
|
||||
Ref<AnimationNodeBlendSpace2D> blend_space;
|
||||
bool read_only = false;
|
||||
|
||||
PanelContainer *panel = nullptr;
|
||||
Button *tool_blend = nullptr;
|
||||
|
|
|
@ -134,6 +134,8 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
GraphNode *node = memnew(GraphNode);
|
||||
graph->add_child(node);
|
||||
|
||||
node->set_draggable(!read_only);
|
||||
|
||||
Ref<AnimationNode> agnode = blend_tree->get_node(E);
|
||||
ERR_CONTINUE(!agnode.is_valid());
|
||||
|
||||
|
@ -146,9 +148,10 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
if (String(E) != "output") {
|
||||
LineEdit *name = memnew(LineEdit);
|
||||
name->set_text(E);
|
||||
name->set_editable(!read_only);
|
||||
name->set_expand_to_text_length_enabled(true);
|
||||
node->add_child(name);
|
||||
node->set_slot(0, false, 0, Color(), true, 0, get_theme_color(SNAME("font_color"), SNAME("Label")));
|
||||
node->set_slot(0, false, 0, Color(), true, read_only ? -1 : 0, get_theme_color(SNAME("font_color"), SNAME("Label")));
|
||||
name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed).bind(agnode), CONNECT_DEFERRED);
|
||||
name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out).bind(name, agnode), CONNECT_DEFERRED);
|
||||
base = 1;
|
||||
|
@ -160,7 +163,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
Label *in_name = memnew(Label);
|
||||
node->add_child(in_name);
|
||||
in_name->set_text(agnode->get_input_name(i));
|
||||
node->set_slot(base + i, true, 0, get_theme_color(SNAME("font_color"), SNAME("Label")), false, 0, Color());
|
||||
node->set_slot(base + i, true, read_only ? -1 : 0, get_theme_color(SNAME("font_color"), SNAME("Label")), false, 0, Color());
|
||||
}
|
||||
|
||||
List<PropertyInfo> pinfo;
|
||||
|
@ -172,6 +175,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
String base_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E) + "/" + F.name;
|
||||
EditorProperty *prop = EditorInspector::instantiate_property_editor(AnimationTreeEditor::get_singleton()->get_tree(), F.type, base_path, F.hint, F.hint_string, F.usage);
|
||||
if (prop) {
|
||||
prop->set_read_only(read_only);
|
||||
prop->set_object_and_property(AnimationTreeEditor::get_singleton()->get_tree(), base_path);
|
||||
prop->update_property();
|
||||
prop->set_name_split_ratio(0);
|
||||
|
@ -195,12 +199,16 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
|
||||
if (agnode->has_filter()) {
|
||||
node->add_child(memnew(HSeparator));
|
||||
Button *edit_filters = memnew(Button);
|
||||
edit_filters->set_text(TTR("Edit Filters"));
|
||||
edit_filters->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons")));
|
||||
node->add_child(edit_filters);
|
||||
edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters).bind(E), CONNECT_DEFERRED);
|
||||
edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER);
|
||||
Button *inspect_filters = memnew(Button);
|
||||
if (read_only) {
|
||||
inspect_filters->set_text(TTR("Inspect Filters"));
|
||||
} else {
|
||||
inspect_filters->set_text(TTR("Edit Filters"));
|
||||
}
|
||||
inspect_filters->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons")));
|
||||
node->add_child(inspect_filters);
|
||||
inspect_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_inspect_filters).bind(E), CONNECT_DEFERRED);
|
||||
inspect_filters->set_h_size_flags(SIZE_SHRINK_CENTER);
|
||||
}
|
||||
|
||||
Ref<AnimationNodeAnimation> anim = agnode;
|
||||
|
@ -208,6 +216,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
MenuButton *mb = memnew(MenuButton);
|
||||
mb->set_text(anim->get_animation());
|
||||
mb->set_icon(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")));
|
||||
mb->set_disabled(read_only);
|
||||
Array options;
|
||||
|
||||
node->add_child(memnew(HSeparator));
|
||||
|
@ -370,10 +379,18 @@ void AnimationNodeBlendTreeEditor::_popup(bool p_has_input_ports, const Vector2
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_popup_request(const Vector2 &p_position) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
_popup(false, graph->get_screen_position() + graph->get_local_mouse_position(), p_position);
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<AnimationNode> node = blend_tree->get_node(p_from);
|
||||
if (node.is_valid()) {
|
||||
from_node = p_from;
|
||||
|
@ -382,6 +399,10 @@ void AnimationNodeBlendTreeEditor::_connection_to_empty(const String &p_from, in
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<AnimationNode> node = blend_tree->get_node(p_to);
|
||||
if (node.is_valid()) {
|
||||
to_node = p_to;
|
||||
|
@ -402,6 +423,10 @@ void AnimationNodeBlendTreeEditor::_node_dragged(const Vector2 &p_from, const Ve
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_connection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
AnimationNodeBlendTree::ConnectionError err = blend_tree->can_connect_node(p_to, p_to_index, p_from);
|
||||
|
||||
if (err != AnimationNodeBlendTree::CONNECTION_OK) {
|
||||
|
@ -418,6 +443,10 @@ void AnimationNodeBlendTreeEditor::_connection_request(const String &p_from, int
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
graph->disconnect_node(p_from, p_from_index, p_to, p_to_index);
|
||||
|
||||
updating = true;
|
||||
|
@ -445,6 +474,10 @@ void AnimationNodeBlendTreeEditor::_anim_selected(int p_index, Array p_options,
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
undo_redo->create_action(TTR("Delete Node"));
|
||||
undo_redo->add_do_method(blend_tree.ptr(), "remove_node", p_which);
|
||||
undo_redo->add_undo_method(blend_tree.ptr(), "add_node", p_which, blend_tree->get_node(p_which), blend_tree.ptr()->get_node_position(p_which));
|
||||
|
@ -464,6 +497,10 @@ void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) {
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray<StringName> &p_nodes) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<StringName> to_erase;
|
||||
|
||||
if (p_nodes.is_empty()) {
|
||||
|
@ -495,6 +532,10 @@ void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray<String
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_node_selected(Object *p_node) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
GraphNode *gn = Object::cast_to<GraphNode>(p_node);
|
||||
ERR_FAIL_COND(!gn);
|
||||
|
||||
|
@ -679,7 +720,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
|
|||
}
|
||||
}
|
||||
|
||||
ti->set_editable(0, true);
|
||||
ti->set_editable(0, !read_only);
|
||||
ti->set_selectable(0, true);
|
||||
ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
||||
ti->set_text(0, concat);
|
||||
|
@ -692,7 +733,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
|
|||
ti = filters->create_item(ti);
|
||||
ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
||||
ti->set_text(0, concat);
|
||||
ti->set_editable(0, true);
|
||||
ti->set_editable(0, !read_only);
|
||||
ti->set_selectable(0, true);
|
||||
ti->set_checked(0, anode->is_path_filtered(path));
|
||||
ti->set_metadata(0, path);
|
||||
|
@ -714,7 +755,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
|
|||
ti = filters->create_item(ti);
|
||||
ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
||||
ti->set_text(0, types_text);
|
||||
ti->set_editable(0, true);
|
||||
ti->set_editable(0, !read_only);
|
||||
ti->set_selectable(0, true);
|
||||
ti->set_checked(0, anode->is_path_filtered(path));
|
||||
ti->set_metadata(0, path);
|
||||
|
@ -727,7 +768,15 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
|
|||
return true;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_edit_filters(const String &p_which) {
|
||||
void AnimationNodeBlendTreeEditor::_inspect_filters(const String &p_which) {
|
||||
if (read_only) {
|
||||
filter_dialog->set_title(TTR("Inspect Filtered Tracks:"));
|
||||
} else {
|
||||
filter_dialog->set_title(TTR("Edit Filtered Tracks:"));
|
||||
}
|
||||
|
||||
filter_enabled->set_disabled(read_only);
|
||||
|
||||
Ref<AnimationNode> anode = blend_tree->get_node(p_which);
|
||||
ERR_FAIL_COND(!anode.is_valid());
|
||||
|
||||
|
@ -838,6 +887,10 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
|
|||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_scroll_changed(const Vector2 &p_scroll) {
|
||||
if (read_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (updating) {
|
||||
return;
|
||||
}
|
||||
|
@ -944,13 +997,20 @@ void AnimationNodeBlendTreeEditor::edit(const Ref<AnimationNode> &p_node) {
|
|||
|
||||
blend_tree = p_node;
|
||||
|
||||
read_only = false;
|
||||
|
||||
if (blend_tree.is_null()) {
|
||||
hide();
|
||||
} else {
|
||||
read_only = EditorNode::get_singleton()->is_resource_read_only(blend_tree);
|
||||
|
||||
blend_tree->connect("removed_from_graph", callable_mp(this, &AnimationNodeBlendTreeEditor::_removed_from_graph));
|
||||
|
||||
_update_graph();
|
||||
}
|
||||
|
||||
add_node->set_disabled(read_only);
|
||||
graph->set_arrange_nodes_button_hidden(read_only);
|
||||
}
|
||||
|
||||
AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
|
||||
|
@ -986,6 +1046,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
|
|||
graph->get_zoom_hbox()->move_child(add_node, 0);
|
||||
add_node->get_popup()->connect("id_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_add_node));
|
||||
add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu).bind(false));
|
||||
add_node->set_disabled(read_only);
|
||||
|
||||
add_options.push_back(AddOption("Animation", "AnimationNodeAnimation"));
|
||||
add_options.push_back(AddOption("OneShot", "AnimationNodeOneShot", 2));
|
||||
|
|
|
@ -47,6 +47,9 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
|
|||
GDCLASS(AnimationNodeBlendTreeEditor, AnimationTreeNodeEditorPlugin);
|
||||
|
||||
Ref<AnimationNodeBlendTree> blend_tree;
|
||||
|
||||
bool read_only = false;
|
||||
|
||||
GraphEdit *graph = nullptr;
|
||||
MenuButton *add_node = nullptr;
|
||||
Vector2 position_from_popup_menu;
|
||||
|
@ -106,7 +109,7 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
|
|||
void _delete_nodes_request(const TypedArray<StringName> &p_nodes);
|
||||
|
||||
bool _update_filters(const Ref<AnimationNode> &anode);
|
||||
void _edit_filters(const String &p_which);
|
||||
void _inspect_filters(const String &p_which);
|
||||
void _filter_edited();
|
||||
void _filter_toggled();
|
||||
Ref<AnimationNode> _filter_edit;
|
||||
|
|
|
@ -56,7 +56,11 @@ bool AnimationNodeStateMachineEditor::can_edit(const Ref<AnimationNode> &p_node)
|
|||
void AnimationNodeStateMachineEditor::edit(const Ref<AnimationNode> &p_node) {
|
||||
state_machine = p_node;
|
||||
|
||||
read_only = false;
|
||||
|
||||
if (state_machine.is_valid()) {
|
||||
read_only = EditorNode::get_singleton()->is_resource_read_only(state_machine);
|
||||
|
||||
selected_transition_from = StringName();
|
||||
selected_transition_to = StringName();
|
||||
selected_transition_index = -1;
|
||||
|
@ -66,6 +70,9 @@ void AnimationNodeStateMachineEditor::edit(const Ref<AnimationNode> &p_node) {
|
|||
_update_mode();
|
||||
_update_graph();
|
||||
}
|
||||
|
||||
tool_create->set_disabled(read_only);
|
||||
tool_connect->set_disabled(read_only);
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
@ -77,7 +84,9 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
Ref<InputEventKey> k = p_event;
|
||||
if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) {
|
||||
if (selected_node != StringName() || !selected_nodes.is_empty() || selected_transition_to != StringName() || selected_transition_from != StringName()) {
|
||||
_erase_selected();
|
||||
if (!read_only) {
|
||||
_erase_selected();
|
||||
}
|
||||
accept_event();
|
||||
}
|
||||
}
|
||||
|
@ -95,9 +104,11 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
Ref<InputEventMouseButton> mb = p_event;
|
||||
|
||||
// Add new node
|
||||
if (mb.is_valid() && mb->is_pressed() && !box_selecting && !connecting && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == MouseButton::LEFT))) {
|
||||
connecting_from = StringName();
|
||||
_open_menu(mb->get_position());
|
||||
if (!read_only) {
|
||||
if (mb.is_valid() && mb->is_pressed() && !box_selecting && !connecting && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == MouseButton::LEFT))) {
|
||||
connecting_from = StringName();
|
||||
_open_menu(mb->get_position());
|
||||
}
|
||||
}
|
||||
|
||||
// Select node or push a field inside
|
||||
|
@ -121,22 +132,24 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
return;
|
||||
}
|
||||
|
||||
if (node_rects[i].name.has_point(mb->get_position()) && state_machine->can_edit_node(node_rects[i].node_name)) { // edit name
|
||||
Ref<StyleBox> line_sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"));
|
||||
if (!read_only) {
|
||||
if (node_rects[i].name.has_point(mb->get_position()) && state_machine->can_edit_node(node_rects[i].node_name)) { // edit name
|
||||
Ref<StyleBox> line_sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"));
|
||||
|
||||
Rect2 edit_rect = node_rects[i].name;
|
||||
edit_rect.position -= line_sb->get_offset();
|
||||
edit_rect.size += line_sb->get_minimum_size();
|
||||
Rect2 edit_rect = node_rects[i].name;
|
||||
edit_rect.position -= line_sb->get_offset();
|
||||
edit_rect.size += line_sb->get_minimum_size();
|
||||
|
||||
name_edit_popup->set_position(state_machine_draw->get_screen_position() + edit_rect.position);
|
||||
name_edit_popup->set_size(edit_rect.size);
|
||||
name_edit->set_text(node_rects[i].node_name);
|
||||
name_edit_popup->popup();
|
||||
name_edit->grab_focus();
|
||||
name_edit->select_all();
|
||||
name_edit_popup->set_position(state_machine_draw->get_screen_position() + edit_rect.position);
|
||||
name_edit_popup->set_size(edit_rect.size);
|
||||
name_edit->set_text(node_rects[i].node_name);
|
||||
name_edit_popup->popup();
|
||||
name_edit->grab_focus();
|
||||
name_edit->select_all();
|
||||
|
||||
prev_name = node_rects[i].node_name;
|
||||
return;
|
||||
prev_name = node_rects[i].node_name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (node_rects[i].edit.has_point(mb->get_position())) { //edit name
|
||||
|
@ -319,7 +332,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
}
|
||||
|
||||
// Move mouse while connecting
|
||||
if (mm.is_valid() && connecting) {
|
||||
if (mm.is_valid() && connecting && !read_only) {
|
||||
connecting_to = mm->get_position();
|
||||
connecting_to_node = StringName();
|
||||
state_machine_draw->update();
|
||||
|
@ -333,7 +346,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
}
|
||||
|
||||
// Move mouse while moving a node
|
||||
if (mm.is_valid() && dragging_selected_attempt) {
|
||||
if (mm.is_valid() && dragging_selected_attempt && !read_only) {
|
||||
dragging_selected = true;
|
||||
drag_ofs = mm->get_position() - drag_from;
|
||||
snap_x = StringName();
|
||||
|
@ -478,17 +491,21 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
}
|
||||
|
||||
Control::CursorShape AnimationNodeStateMachineEditor::get_cursor_shape(const Point2 &p_pos) const {
|
||||
// Put ibeam (text cursor) over names to make it clearer that they are editable.
|
||||
Transform2D xform = panel->get_transform() * state_machine_draw->get_transform();
|
||||
Point2 pos = xform.xform_inv(p_pos);
|
||||
Control::CursorShape cursor_shape = get_default_cursor_shape();
|
||||
if (!read_only) {
|
||||
// Put ibeam (text cursor) over names to make it clearer that they are editable.
|
||||
Transform2D xform = panel->get_transform() * state_machine_draw->get_transform();
|
||||
Point2 pos = xform.xform_inv(p_pos);
|
||||
|
||||
for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order.
|
||||
if (node_rects[i].node.has_point(pos)) {
|
||||
if (node_rects[i].name.has_point(pos)) {
|
||||
cursor_shape = Control::CURSOR_IBEAM;
|
||||
for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order.
|
||||
if (node_rects[i].node.has_point(pos)) {
|
||||
if (node_rects[i].name.has_point(pos)) {
|
||||
if (state_machine->can_edit_node(node_rects[i].node_name)) {
|
||||
cursor_shape = Control::CURSOR_IBEAM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cursor_shape;
|
||||
|
@ -1848,9 +1865,9 @@ void AnimationNodeStateMachineEditor::_update_mode() {
|
|||
tool_erase_hb->show();
|
||||
bool nothing_selected = selected_nodes.is_empty() && selected_transition_from == StringName() && selected_transition_to == StringName();
|
||||
bool start_end_selected = selected_nodes.size() == 1 && (*selected_nodes.begin() == state_machine->start_node || *selected_nodes.begin() == state_machine->end_node);
|
||||
tool_erase->set_disabled(nothing_selected || start_end_selected);
|
||||
tool_erase->set_disabled(nothing_selected || start_end_selected || read_only);
|
||||
|
||||
if (selected_nodes.is_empty() || start_end_selected) {
|
||||
if (selected_nodes.is_empty() || start_end_selected || read_only) {
|
||||
tool_group->set_disabled(true);
|
||||
tool_group->set_visible(true);
|
||||
tool_ungroup->set_visible(false);
|
||||
|
|
|
@ -47,6 +47,8 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
|
|||
|
||||
Ref<AnimationNodeStateMachine> state_machine;
|
||||
|
||||
bool read_only = false;
|
||||
|
||||
Button *tool_select = nullptr;
|
||||
Button *tool_create = nullptr;
|
||||
Button *tool_connect = nullptr;
|
||||
|
|
|
@ -607,13 +607,16 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
connecting_color = Object::cast_to<GraphNode>(to)->get_connection_input_color(E.to_port);
|
||||
connecting_target = false;
|
||||
connecting_to = pos;
|
||||
just_disconnected = true;
|
||||
|
||||
emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
|
||||
to = get_node(String(connecting_from)); //maybe it was erased
|
||||
if (Object::cast_to<GraphNode>(to)) {
|
||||
connecting = true;
|
||||
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
|
||||
if (connecting_type >= 0) {
|
||||
just_disconnected = true;
|
||||
|
||||
emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
|
||||
to = get_node(String(connecting_from)); //maybe it was erased
|
||||
if (Object::cast_to<GraphNode>(to)) {
|
||||
connecting = true;
|
||||
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -621,7 +624,6 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
}
|
||||
}
|
||||
|
||||
connecting = true;
|
||||
connecting_from = gn->get_name();
|
||||
connecting_index = j;
|
||||
connecting_out = true;
|
||||
|
@ -629,8 +631,11 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
connecting_color = gn->get_connection_output_color(j);
|
||||
connecting_target = false;
|
||||
connecting_to = pos;
|
||||
just_disconnected = false;
|
||||
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
|
||||
if (connecting_type >= 0) {
|
||||
connecting = true;
|
||||
just_disconnected = false;
|
||||
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -657,11 +662,13 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
connecting_to = pos;
|
||||
just_disconnected = true;
|
||||
|
||||
emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
|
||||
fr = get_node(String(connecting_from)); //maybe it was erased
|
||||
if (Object::cast_to<GraphNode>(fr)) {
|
||||
connecting = true;
|
||||
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
|
||||
if (connecting_type >= 0) {
|
||||
emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
|
||||
fr = get_node(String(connecting_from)); //maybe it was erased
|
||||
if (Object::cast_to<GraphNode>(fr)) {
|
||||
connecting = true;
|
||||
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -669,7 +676,6 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
}
|
||||
}
|
||||
|
||||
connecting = true;
|
||||
connecting_from = gn->get_name();
|
||||
connecting_index = j;
|
||||
connecting_out = false;
|
||||
|
@ -677,8 +683,11 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
connecting_color = gn->get_connection_input_color(j);
|
||||
connecting_target = false;
|
||||
connecting_to = pos;
|
||||
just_disconnected = false;
|
||||
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
|
||||
if (connecting_type >= 0) {
|
||||
connecting = true;
|
||||
just_disconnected = false;
|
||||
emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1127,7 +1136,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
|
|||
drag_accum += mm->get_relative();
|
||||
for (int i = get_child_count() - 1; i >= 0; i--) {
|
||||
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
|
||||
if (gn && gn->is_selected()) {
|
||||
if (gn && gn->is_selected() && gn->is_draggable()) {
|
||||
Vector2 pos = (gn->get_drag_from() * zoom + drag_accum) / zoom;
|
||||
|
||||
// Snapping can be toggled temporarily by holding down Ctrl.
|
||||
|
@ -1166,7 +1175,9 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
|
|||
} else if (gn->is_selected() && !box_selection_mode_additive) {
|
||||
emit_signal(SNAME("node_deselected"), gn);
|
||||
}
|
||||
gn->set_selected(box_selection_mode_additive);
|
||||
if (gn->is_selectable()) {
|
||||
gn->set_selected(box_selection_mode_additive);
|
||||
}
|
||||
} else {
|
||||
bool select = (previous_selected.find(gn) != nullptr);
|
||||
if (gn->is_selected() && !select) {
|
||||
|
@ -1174,7 +1185,9 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
|
|||
} else if (!gn->is_selected() && select) {
|
||||
emit_signal(SNAME("node_selected"), gn);
|
||||
}
|
||||
gn->set_selected(select);
|
||||
if (gn->is_selectable()) {
|
||||
gn->set_selected(select);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1193,7 +1206,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
|
|||
continue;
|
||||
}
|
||||
|
||||
bool select = (previous_selected.find(gn) != nullptr);
|
||||
bool select = (gn->is_selectable() && previous_selected.find(gn) != nullptr);
|
||||
if (gn->is_selected() && !select) {
|
||||
emit_signal(SNAME("node_deselected"), gn);
|
||||
} else if (!gn->is_selected() && select) {
|
||||
|
@ -1285,7 +1298,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
|
|||
GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i));
|
||||
if (o_gn) {
|
||||
if (o_gn == gn) {
|
||||
o_gn->set_selected(true);
|
||||
o_gn->set_selected(o_gn->is_selectable());
|
||||
} else {
|
||||
if (o_gn->is_selected()) {
|
||||
emit_signal(SNAME("node_deselected"), o_gn);
|
||||
|
@ -1296,7 +1309,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
|
|||
}
|
||||
}
|
||||
|
||||
gn->set_selected(true);
|
||||
gn->set_selected(gn->is_selectable());
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i));
|
||||
if (!o_gn) {
|
||||
|
@ -1711,6 +1724,19 @@ bool GraphEdit::is_minimap_enabled() const {
|
|||
return minimap_button->is_pressed();
|
||||
}
|
||||
|
||||
void GraphEdit::set_arrange_nodes_button_hidden(bool p_enable) {
|
||||
arrange_nodes_button_hidden = p_enable;
|
||||
if (arrange_nodes_button_hidden) {
|
||||
layout_button->hide();
|
||||
} else {
|
||||
layout_button->show();
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphEdit::is_arrange_nodes_button_hidden() const {
|
||||
return arrange_nodes_button_hidden;
|
||||
}
|
||||
|
||||
void GraphEdit::_minimap_toggled() {
|
||||
if (is_minimap_enabled()) {
|
||||
minimap->set_visible(true);
|
||||
|
@ -2343,6 +2369,9 @@ void GraphEdit::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_minimap_enabled", "enable"), &GraphEdit::set_minimap_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_minimap_enabled"), &GraphEdit::is_minimap_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_arrange_nodes_button_hidden", "enable"), &GraphEdit::set_arrange_nodes_button_hidden);
|
||||
ClassDB::bind_method(D_METHOD("is_arrange_nodes_button_hidden"), &GraphEdit::is_arrange_nodes_button_hidden);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_right_disconnects", "enable"), &GraphEdit::set_right_disconnects);
|
||||
ClassDB::bind_method(D_METHOD("is_right_disconnects_enabled"), &GraphEdit::is_right_disconnects_enabled);
|
||||
|
||||
|
@ -2382,6 +2411,9 @@ void GraphEdit::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimap_size", PROPERTY_HINT_NONE, "suffix:px"), "set_minimap_size", "get_minimap_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "minimap_opacity"), "set_minimap_opacity", "get_minimap_opacity");
|
||||
|
||||
ADD_GROUP("UI", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arrange_nodes_button_hidden"), "set_arrange_nodes_button_hidden", "is_arrange_nodes_button_hidden");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("connection_request", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot")));
|
||||
ADD_SIGNAL(MethodInfo("disconnection_request", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot")));
|
||||
ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2, "position")));
|
||||
|
|
|
@ -133,6 +133,8 @@ private:
|
|||
void _pan_callback(Vector2 p_scroll_vec);
|
||||
void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
|
||||
|
||||
bool arrange_nodes_button_hidden = false;
|
||||
|
||||
bool connecting = false;
|
||||
String connecting_from;
|
||||
bool connecting_out = false;
|
||||
|
@ -323,6 +325,9 @@ public:
|
|||
void set_minimap_enabled(bool p_enable);
|
||||
bool is_minimap_enabled() const;
|
||||
|
||||
void set_arrange_nodes_button_hidden(bool p_enable);
|
||||
bool is_arrange_nodes_button_hidden() const;
|
||||
|
||||
GraphEditFilter *get_top_layer() const { return top_layer; }
|
||||
GraphEditMinimap *get_minimap() const { return minimap; }
|
||||
void get_connection_list(List<Connection> *r_connections) const;
|
||||
|
|
|
@ -1003,6 +1003,22 @@ bool GraphNode::is_resizable() const {
|
|||
return resizable;
|
||||
}
|
||||
|
||||
void GraphNode::set_draggable(bool p_draggable) {
|
||||
draggable = p_draggable;
|
||||
}
|
||||
|
||||
bool GraphNode::is_draggable() {
|
||||
return draggable;
|
||||
}
|
||||
|
||||
void GraphNode::set_selectable(bool p_selectable) {
|
||||
selectable = p_selectable;
|
||||
}
|
||||
|
||||
bool GraphNode::is_selectable() {
|
||||
return selectable;
|
||||
}
|
||||
|
||||
Vector<int> GraphNode::get_allowed_size_flags_horizontal() const {
|
||||
Vector<int> flags;
|
||||
flags.append(SIZE_FILL);
|
||||
|
@ -1064,6 +1080,12 @@ void GraphNode::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &GraphNode::set_resizable);
|
||||
ClassDB::bind_method(D_METHOD("is_resizable"), &GraphNode::is_resizable);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_draggable", "draggable"), &GraphNode::set_draggable);
|
||||
ClassDB::bind_method(D_METHOD("is_draggable"), &GraphNode::is_draggable);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_selectable", "selectable"), &GraphNode::set_selectable);
|
||||
ClassDB::bind_method(D_METHOD("is_selectable"), &GraphNode::is_selectable);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_selected", "selected"), &GraphNode::set_selected);
|
||||
ClassDB::bind_method(D_METHOD("is_selected"), &GraphNode::is_selected);
|
||||
|
||||
|
@ -1089,6 +1111,8 @@ void GraphNode::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_position_offset", "get_position_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draggable"), "set_draggable", "is_draggable");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selectable"), "set_selectable", "is_selectable");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selected"), "set_selected", "is_selected");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "comment"), "set_comment", "is_comment");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "overlay", PROPERTY_HINT_ENUM, "Disabled,Breakpoint,Position"), "set_overlay", "get_overlay");
|
||||
|
|
|
@ -67,6 +67,8 @@ private:
|
|||
Vector2 position_offset;
|
||||
bool comment = false;
|
||||
bool resizable = false;
|
||||
bool draggable = true;
|
||||
bool selectable = true;
|
||||
|
||||
bool resizing = false;
|
||||
Vector2 resizing_from;
|
||||
|
@ -183,6 +185,12 @@ public:
|
|||
void set_resizable(bool p_enable);
|
||||
bool is_resizable() const;
|
||||
|
||||
void set_draggable(bool p_draggable);
|
||||
bool is_draggable();
|
||||
|
||||
void set_selectable(bool p_selectable);
|
||||
bool is_selectable();
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
|
||||
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
|
||||
|
|
Loading…
Reference in New Issue