Massive rewrite to AnimationTree. Many APIs changed in order to:
-Reuse resources -Expose properties in AnimationTree
This commit is contained in:
parent
1b66b08fdb
commit
c7e4527a88
34 changed files with 3856 additions and 2937 deletions
|
@ -1476,8 +1476,13 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str
|
|||
|
||||
Signal::Target target(p_to_object->get_instance_id(), p_to_method);
|
||||
if (s->slot_map.has(target)) {
|
||||
ERR_EXPLAIN("Signal '" + p_signal + "' is already connected to given method '" + p_to_method + "' in that object.");
|
||||
ERR_FAIL_COND_V(s->slot_map.has(target), ERR_INVALID_PARAMETER);
|
||||
if (p_flags & CONNECT_REFERENCE_COUNTED) {
|
||||
s->slot_map[target].reference_count++;
|
||||
return OK;
|
||||
} else {
|
||||
ERR_EXPLAIN("Signal '" + p_signal + "' is already connected to given method '" + p_to_method + "' in that object.");
|
||||
ERR_FAIL_COND_V(s->slot_map.has(target), ERR_INVALID_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
Signal::Slot slot;
|
||||
|
@ -1491,6 +1496,10 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str
|
|||
conn.binds = p_binds;
|
||||
slot.conn = conn;
|
||||
slot.cE = p_to_object->connections.push_back(conn);
|
||||
if (p_flags & CONNECT_REFERENCE_COUNTED) {
|
||||
slot.reference_count = 1;
|
||||
}
|
||||
|
||||
s->slot_map[target] = slot;
|
||||
|
||||
return OK;
|
||||
|
@ -1539,7 +1548,14 @@ void Object::disconnect(const StringName &p_signal, Object *p_to_object, const S
|
|||
ERR_FAIL();
|
||||
}
|
||||
|
||||
p_to_object->connections.erase(s->slot_map[target].cE);
|
||||
Signal::Slot *slot = &s->slot_map[target];
|
||||
|
||||
slot->reference_count--; // by default is zero, if it was not referenced it will go below it
|
||||
if (slot->reference_count >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
p_to_object->connections.erase(slot->cE);
|
||||
s->slot_map.erase(target);
|
||||
|
||||
if (s->slot_map.empty() && ClassDB::has_signal(get_class_name(), p_signal)) {
|
||||
|
@ -1761,6 +1777,7 @@ void Object::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(CONNECT_DEFERRED);
|
||||
BIND_ENUM_CONSTANT(CONNECT_PERSIST);
|
||||
BIND_ENUM_CONSTANT(CONNECT_ONESHOT);
|
||||
BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
|
||||
void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) {
|
||||
|
|
|
@ -392,7 +392,8 @@ public:
|
|||
|
||||
CONNECT_DEFERRED = 1,
|
||||
CONNECT_PERSIST = 2, // hint for scene to save this connection
|
||||
CONNECT_ONESHOT = 4
|
||||
CONNECT_ONESHOT = 4,
|
||||
CONNECT_REFERENCE_COUNTED = 8,
|
||||
};
|
||||
|
||||
struct Connection {
|
||||
|
@ -443,8 +444,10 @@ private:
|
|||
|
||||
struct Slot {
|
||||
|
||||
int reference_count;
|
||||
Connection conn;
|
||||
List<Connection>::Element *cE;
|
||||
Slot() { reference_count = 0; }
|
||||
};
|
||||
|
||||
MethodInfo user;
|
||||
|
|
|
@ -1533,9 +1533,10 @@ void EditorInspector::update_tree() {
|
|||
|
||||
if (capitalize_paths)
|
||||
path_name = path_name.capitalize();
|
||||
|
||||
Color c = sscolor;
|
||||
c.a /= level;
|
||||
section->setup(path_name, acc_path, object, c, use_folding);
|
||||
section->setup(path_name, path_name, object, c, use_folding);
|
||||
|
||||
item_path[acc_path] = section->get_vbox();
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#include "editor/plugins/animation_player_editor_plugin.h"
|
||||
#include "editor/plugins/animation_state_machine_editor.h"
|
||||
#include "editor/plugins/animation_tree_editor_plugin.h"
|
||||
#include "editor/plugins/animation_tree_player_editor_plugin.h"
|
||||
#include "editor/plugins/asset_library_editor_plugin.h"
|
||||
#include "editor/plugins/audio_stream_editor_plugin.h"
|
||||
#include "editor/plugins/baked_lightmap_editor_plugin.h"
|
||||
|
@ -5589,16 +5590,13 @@ EditorNode::EditorNode() {
|
|||
|
||||
add_editor_plugin(memnew(ShaderEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(VisualShaderEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(AnimationNodeBlendTreeEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(AnimationNodeBlendSpace1DEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(AnimationNodeBlendSpace2DEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(AnimationNodeStateMachineEditorPlugin(this)));
|
||||
|
||||
add_editor_plugin(memnew(CameraEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(ThemeEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(MultiMeshEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(MeshInstanceEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(AnimationTreeEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(AnimationTreePlayerEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(MeshLibraryEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(StyleBoxEditorPlugin(this)));
|
||||
add_editor_plugin(memnew(SpriteEditorPlugin(this)));
|
||||
|
|
|
@ -36,6 +36,16 @@
|
|||
|
||||
void InspectorDock::_menu_option(int p_option) {
|
||||
switch (p_option) {
|
||||
case RESOURCE_MAKE_BUILT_IN: {
|
||||
_unref_resource();
|
||||
} break;
|
||||
case RESOURCE_COPY: {
|
||||
_copy_resource();
|
||||
} break;
|
||||
case RESOURCE_EDIT_CLIPBOARD: {
|
||||
_paste_resource();
|
||||
} break;
|
||||
|
||||
case RESOURCE_SAVE: {
|
||||
_save_resource(false);
|
||||
} break;
|
||||
|
@ -400,10 +410,11 @@ void InspectorDock::update(Object *p_object) {
|
|||
p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS);
|
||||
p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS);
|
||||
p->add_separator();
|
||||
p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Paste Resource")), RESOURCE_PASTE);
|
||||
|
||||
p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource Clipboard")), RESOURCE_EDIT_CLIPBOARD);
|
||||
if (is_resource) {
|
||||
p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
|
||||
p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_UNREF);
|
||||
p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_MAKE_BUILT_IN);
|
||||
}
|
||||
|
||||
if (is_resource || is_node) {
|
||||
|
|
|
@ -51,13 +51,12 @@ class InspectorDock : public VBoxContainer {
|
|||
GDCLASS(InspectorDock, VBoxContainer);
|
||||
|
||||
enum MenuOptions {
|
||||
RESOURCE_NEW,
|
||||
RESOURCE_LOAD,
|
||||
RESOURCE_SAVE,
|
||||
RESOURCE_SAVE_AS,
|
||||
RESOURCE_UNREF,
|
||||
RESOURCE_MAKE_BUILT_IN,
|
||||
RESOURCE_COPY,
|
||||
RESOURCE_PASTE,
|
||||
RESOURCE_EDIT_CLIPBOARD,
|
||||
OBJECT_COPY_PARAMS,
|
||||
OBJECT_PASTE_PARAMS,
|
||||
OBJECT_UNIQUE_RESOURCES,
|
||||
|
|
|
@ -3,41 +3,11 @@
|
|||
#include "os/keyboard.h"
|
||||
#include "scene/animation/animation_blend_tree.h"
|
||||
|
||||
void AnimationNodeBlendSpace1DEditorPlugin::edit(Object *p_object) {
|
||||
anim_tree_editor->edit(Object::cast_to<AnimationNodeBlendSpace1D>(p_object));
|
||||
StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
|
||||
StringName path = AnimationTreeEditor::get_singleton()->get_base_path()+"blend_position";
|
||||
return path;
|
||||
}
|
||||
|
||||
bool AnimationNodeBlendSpace1DEditorPlugin::handles(Object *p_object) const {
|
||||
return p_object->is_class("AnimationNodeBlendSpace1D");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditorPlugin::make_visible(bool p_visible) {
|
||||
|
||||
if (p_visible) {
|
||||
button->show();
|
||||
editor->make_bottom_panel_item_visible(anim_tree_editor);
|
||||
anim_tree_editor->set_process(true);
|
||||
} else {
|
||||
if (anim_tree_editor->is_visible_in_tree()) {
|
||||
editor->hide_bottom_panel();
|
||||
}
|
||||
|
||||
button->hide();
|
||||
anim_tree_editor->set_process(false);
|
||||
}
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace1DEditorPlugin::AnimationNodeBlendSpace1DEditorPlugin(EditorNode *p_node) {
|
||||
editor = p_node;
|
||||
anim_tree_editor = memnew(AnimationNodeBlendSpace1DEditor);
|
||||
anim_tree_editor->set_custom_minimum_size(Size2(0, 150 * EDSCALE));
|
||||
|
||||
button = editor->add_bottom_panel_item(TTR("BlendSpace1D"), anim_tree_editor);
|
||||
button->hide();
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace1DEditorPlugin::~AnimationNodeBlendSpace1DEditorPlugin() {
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) {
|
||||
Ref<InputEventKey> k = p_event;
|
||||
|
@ -62,7 +32,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
|
||||
menu->add_submenu_item(TTR("Add Animation"), "animations");
|
||||
|
||||
AnimationTree *gp = blend_space->get_tree();
|
||||
AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
|
||||
ERR_FAIL_COND(!gp);
|
||||
|
||||
if (gp->has_node(gp->get_animation_player())) {
|
||||
|
@ -85,10 +55,18 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
continue;
|
||||
|
||||
int idx = menu->get_item_count();
|
||||
menu->add_item(vformat("Add %s", name));
|
||||
menu->add_item(vformat("Add %s", name),idx);
|
||||
menu->set_item_metadata(idx, E->get());
|
||||
}
|
||||
|
||||
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("Load.."), MENU_LOAD_FILE);
|
||||
|
||||
menu->set_global_position(blend_space_draw->get_global_transform().xform(mb->get_position()));
|
||||
menu->popup();
|
||||
|
||||
|
@ -158,7 +136,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
|
||||
blend_pos += blend_space->get_min_space();
|
||||
|
||||
blend_space->set_blend_pos(blend_pos);
|
||||
AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(),blend_pos);
|
||||
blend_space_draw->update();
|
||||
}
|
||||
|
||||
|
@ -181,7 +159,8 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
|
||||
blend_pos += blend_space->get_min_space();
|
||||
|
||||
blend_space->set_blend_pos(blend_pos);
|
||||
AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(),blend_pos);
|
||||
|
||||
blend_space_draw->update();
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +256,9 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
|
|||
color.a *= 0.5;
|
||||
}
|
||||
|
||||
float point = blend_space->get_blend_pos();
|
||||
float point = AnimationTreeEditor::get_singleton()->get_tree()->get(get_blend_position_path());
|
||||
|
||||
|
||||
point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
point *= s.width;
|
||||
|
||||
|
@ -299,12 +280,6 @@ void AnimationNodeBlendSpace1DEditor::_update_space() {
|
|||
|
||||
updating = true;
|
||||
|
||||
if (blend_space->get_parent().is_valid()) {
|
||||
goto_parent_hb->show();
|
||||
} else {
|
||||
goto_parent_hb->hide();
|
||||
}
|
||||
|
||||
max_value->set_value(blend_space->get_max_space());
|
||||
min_value->set_value(blend_space->get_min_space());
|
||||
|
||||
|
@ -355,15 +330,47 @@ void AnimationNodeBlendSpace1DEditor::_snap_toggled() {
|
|||
blend_space_draw->update();
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditor::_file_opened(const String &p_file) {
|
||||
|
||||
file_loaded = ResourceLoader::load(p_file);
|
||||
if (file_loaded.is_valid()) {
|
||||
_add_menu_type(MENU_LOAD_FILE_CONFIRM);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditor::_add_menu_type(int p_index) {
|
||||
String type = menu->get_item_metadata(p_index);
|
||||
Ref<AnimationRootNode> node;
|
||||
if (p_index == MENU_LOAD_FILE) {
|
||||
|
||||
Object *obj = ClassDB::instance(type);
|
||||
ERR_FAIL_COND(!obj);
|
||||
AnimationNode *an = Object::cast_to<AnimationNode>(obj);
|
||||
ERR_FAIL_COND(!an);
|
||||
open_file->clear_filters();
|
||||
List<String> filters;
|
||||
ResourceLoader::get_recognized_extensions_for_type("AnimationRootNode", &filters);
|
||||
for (List<String>::Element *E = filters.front(); E; E = E->next()) {
|
||||
open_file->add_filter("*." + E->get());
|
||||
}
|
||||
open_file->popup_centered_ratio();
|
||||
return;
|
||||
} else if (p_index == MENU_LOAD_FILE_CONFIRM) {
|
||||
node = file_loaded;
|
||||
file_loaded.unref();
|
||||
} else if (p_index == MENU_PASTE) {
|
||||
|
||||
Ref<AnimationNode> node(an);
|
||||
node = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
} else {
|
||||
String type = menu->get_item_metadata(p_index);
|
||||
|
||||
Object *obj = ClassDB::instance(type);
|
||||
ERR_FAIL_COND(!obj);
|
||||
AnimationNode *an = Object::cast_to<AnimationNode>(obj);
|
||||
ERR_FAIL_COND(!an);
|
||||
|
||||
node = Ref<AnimationNode>(an);
|
||||
}
|
||||
|
||||
if (!node.is_valid()) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("This type of node can't be used. Only root nodes are allowed."));
|
||||
return;
|
||||
}
|
||||
|
||||
updating = true;
|
||||
undo_redo->create_action("Add Node Point");
|
||||
|
@ -438,7 +445,7 @@ void AnimationNodeBlendSpace1DEditor::_update_tool_erase() {
|
|||
if (point_valid) {
|
||||
Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point);
|
||||
|
||||
if (EditorNode::get_singleton()->item_has_editor(an.ptr())) {
|
||||
if (AnimationTreeEditor::get_singleton()->can_edit(an)) {
|
||||
open_editor->show();
|
||||
} else {
|
||||
open_editor->hide();
|
||||
|
@ -490,17 +497,11 @@ void AnimationNodeBlendSpace1DEditor::_open_editor() {
|
|||
if (selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) {
|
||||
Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point);
|
||||
ERR_FAIL_COND(an.is_null());
|
||||
EditorNode::get_singleton()->edit_item(an.ptr());
|
||||
AnimationTreeEditor::get_singleton()->enter_editor(itos(selected_point));
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditor::_goto_parent() {
|
||||
EditorNode::get_singleton()->edit_item(blend_space->get_parent().ptr());
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditor::_removed_from_graph() {
|
||||
EditorNode::get_singleton()->edit_item(NULL);
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditor::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
|
||||
|
@ -513,18 +514,16 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) {
|
|||
tool_erase->set_icon(get_icon("Remove", "EditorIcons"));
|
||||
snap->set_icon(get_icon("SnapGrid", "EditorIcons"));
|
||||
open_editor->set_icon(get_icon("Edit", "EditorIcons"));
|
||||
goto_parent->set_icon(get_icon("MoveUp", "EditorIcons"));
|
||||
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_PROCESS) {
|
||||
String error;
|
||||
|
||||
if (!blend_space->get_tree()) {
|
||||
error = TTR("BlendSpace1D does not belong to an AnimationTree node.");
|
||||
} else if (!blend_space->get_tree()->is_active()) {
|
||||
if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
|
||||
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
|
||||
} else if (blend_space->get_tree()->is_state_invalid()) {
|
||||
error = blend_space->get_tree()->get_invalid_state_reason();
|
||||
} else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
|
||||
error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
|
||||
}
|
||||
|
||||
if (error != error_label->get_text()) {
|
||||
|
@ -536,6 +535,10 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
set_process(is_visible_in_tree());
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditor::_bind_methods() {
|
||||
|
@ -556,28 +559,26 @@ void AnimationNodeBlendSpace1DEditor::_bind_methods() {
|
|||
ClassDB::bind_method("_update_edited_point_pos", &AnimationNodeBlendSpace1DEditor::_update_edited_point_pos);
|
||||
|
||||
ClassDB::bind_method("_open_editor", &AnimationNodeBlendSpace1DEditor::_open_editor);
|
||||
ClassDB::bind_method("_goto_parent", &AnimationNodeBlendSpace1DEditor::_goto_parent);
|
||||
|
||||
ClassDB::bind_method("_removed_from_graph", &AnimationNodeBlendSpace1DEditor::_removed_from_graph);
|
||||
ClassDB::bind_method("_file_opened", &AnimationNodeBlendSpace1DEditor::_file_opened);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1DEditor::edit(AnimationNodeBlendSpace1D *p_blend_space) {
|
||||
bool AnimationNodeBlendSpace1DEditor::can_edit(const Ref<AnimationNode> &p_node) {
|
||||
|
||||
if (blend_space.is_valid()) {
|
||||
blend_space->disconnect("removed_from_graph", this, "_removed_from_graph");
|
||||
}
|
||||
Ref<AnimationNodeBlendSpace1D> b1d=p_node;
|
||||
return b1d.is_valid();
|
||||
}
|
||||
|
||||
if (p_blend_space) {
|
||||
blend_space = Ref<AnimationNodeBlendSpace1D>(p_blend_space);
|
||||
} else {
|
||||
blend_space.unref();
|
||||
}
|
||||
void AnimationNodeBlendSpace1DEditor::edit(const Ref<AnimationNode> &p_node) {
|
||||
|
||||
if (blend_space.is_null()) {
|
||||
hide();
|
||||
} else {
|
||||
blend_space->connect("removed_from_graph", this, "_removed_from_graph");
|
||||
|
||||
|
||||
blend_space=p_node;
|
||||
|
||||
if (!blend_space.is_null()) {
|
||||
_update_space();
|
||||
}
|
||||
}
|
||||
|
@ -594,14 +595,6 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
|
|||
Ref<ButtonGroup> bg;
|
||||
bg.instance();
|
||||
|
||||
goto_parent_hb = memnew(HBoxContainer);
|
||||
top_hb->add_child(goto_parent_hb);
|
||||
|
||||
goto_parent = memnew(ToolButton);
|
||||
goto_parent->connect("pressed", this, "_goto_parent", varray(), CONNECT_DEFERRED);
|
||||
goto_parent_hb->add_child(goto_parent);
|
||||
goto_parent_hb->add_child(memnew(VSeparator));
|
||||
goto_parent_hb->hide();
|
||||
|
||||
tool_blend = memnew(ToolButton);
|
||||
tool_blend->set_toggle_mode(true);
|
||||
|
@ -726,13 +719,20 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
|
|||
|
||||
menu = memnew(PopupMenu);
|
||||
add_child(menu);
|
||||
menu->connect("index_pressed", this, "_add_menu_type");
|
||||
menu->connect("id_pressed", this, "_add_menu_type");
|
||||
|
||||
animations_menu = memnew(PopupMenu);
|
||||
menu->add_child(animations_menu);
|
||||
animations_menu->set_name("animations");
|
||||
animations_menu->connect("index_pressed", this, "_add_animation_type");
|
||||
|
||||
open_file = memnew(EditorFileDialog);
|
||||
add_child(open_file);
|
||||
open_file->set_title(TTR("Open Animation Node"));
|
||||
open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
||||
open_file->connect("file_selected", this, "_file_opened");
|
||||
undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
selected_point = -1;
|
||||
dragging_selected = false;
|
||||
dragging_selected_attempt = false;
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
#include "scene/gui/graph_edit.h"
|
||||
#include "scene/gui/popup.h"
|
||||
#include "scene/gui/tree.h"
|
||||
#include "editor/plugins/animation_tree_editor_plugin.h"
|
||||
|
||||
class AnimationNodeBlendSpace1DEditor : public VBoxContainer {
|
||||
class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
|
||||
|
||||
GDCLASS(AnimationNodeBlendSpace1DEditor, VBoxContainer)
|
||||
GDCLASS(AnimationNodeBlendSpace1DEditor, AnimationTreeNodeEditorPlugin)
|
||||
|
||||
Ref<AnimationNodeBlendSpace1D> blend_space;
|
||||
|
||||
|
@ -81,7 +82,17 @@ class AnimationNodeBlendSpace1DEditor : public VBoxContainer {
|
|||
|
||||
void _goto_parent();
|
||||
|
||||
void _removed_from_graph();
|
||||
EditorFileDialog *open_file;
|
||||
Ref<AnimationNode> file_loaded;
|
||||
void _file_opened(const String &p_file);
|
||||
|
||||
enum {
|
||||
MENU_LOAD_FILE = 1000,
|
||||
MENU_PASTE = 1001,
|
||||
MENU_LOAD_FILE_CONFIRM = 1002
|
||||
};
|
||||
|
||||
StringName get_blend_position_path() const;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
@ -89,29 +100,9 @@ protected:
|
|||
|
||||
public:
|
||||
static AnimationNodeBlendSpace1DEditor *get_singleton() { return singleton; }
|
||||
void edit(AnimationNodeBlendSpace1D *p_blend_space);
|
||||
virtual bool can_edit(const Ref<AnimationNode> &p_node);
|
||||
virtual void edit(const Ref<AnimationNode> &p_node);
|
||||
AnimationNodeBlendSpace1DEditor();
|
||||
};
|
||||
|
||||
class AnimationNodeBlendSpace1DEditorPlugin : public EditorPlugin {
|
||||
|
||||
GDCLASS(AnimationNodeBlendSpace1DEditorPlugin, EditorPlugin)
|
||||
|
||||
AnimationNodeBlendSpace1DEditor *anim_tree_editor;
|
||||
EditorNode *editor;
|
||||
Button *button;
|
||||
|
||||
public:
|
||||
virtual String get_name() const { return "BlendSpace1D"; }
|
||||
|
||||
bool has_main_screen() const { return false; }
|
||||
|
||||
virtual void edit(Object *p_object);
|
||||
virtual bool handles(Object *p_object) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
AnimationNodeBlendSpace1DEditorPlugin(EditorNode *p_node);
|
||||
~AnimationNodeBlendSpace1DEditorPlugin();
|
||||
};
|
||||
|
||||
#endif // ANIMATION_BLEND_SPACE_1D_EDITOR_H
|
||||
|
|
|
@ -11,27 +11,26 @@
|
|||
#include "scene/gui/panel.h"
|
||||
#include "scene/main/viewport.h"
|
||||
|
||||
void AnimationNodeBlendSpace2DEditor::edit(AnimationNodeBlendSpace2D *p_blend_space) {
|
||||
bool AnimationNodeBlendSpace2DEditor::can_edit(const Ref<AnimationNode> &p_node) {
|
||||
|
||||
if (blend_space.is_valid()) {
|
||||
blend_space->disconnect("removed_from_graph", this, "_removed_from_graph");
|
||||
}
|
||||
Ref<AnimationNodeBlendSpace2D> bs2d=p_node;
|
||||
return bs2d.is_valid();
|
||||
}
|
||||
|
||||
if (p_blend_space) {
|
||||
blend_space = Ref<AnimationNodeBlendSpace2D>(p_blend_space);
|
||||
} else {
|
||||
blend_space.unref();
|
||||
}
|
||||
void AnimationNodeBlendSpace2DEditor::edit(const Ref<AnimationNode> &p_node) {
|
||||
|
||||
if (blend_space.is_null()) {
|
||||
hide();
|
||||
} else {
|
||||
blend_space->connect("removed_from_graph", this, "_removed_from_graph");
|
||||
blend_space = p_node;
|
||||
|
||||
if (!blend_space.is_null()) {
|
||||
_update_space();
|
||||
}
|
||||
}
|
||||
|
||||
StringName AnimationNodeBlendSpace2DEditor::get_blend_position_path() const {
|
||||
StringName path = AnimationTreeEditor::get_singleton()->get_base_path()+"blend_position";
|
||||
return path;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
Ref<InputEventKey> k = p_event;
|
||||
|
@ -54,7 +53,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
|
||||
menu->add_submenu_item(TTR("Add Animation"), "animations");
|
||||
|
||||
AnimationTree *gp = blend_space->get_tree();
|
||||
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()));
|
||||
|
@ -74,10 +73,19 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
if (name == "Animation")
|
||||
continue; // nope
|
||||
int idx = menu->get_item_count();
|
||||
menu->add_item(vformat("Add %s", name));
|
||||
menu->add_item(vformat("Add %s", name),idx);
|
||||
menu->set_item_metadata(idx, E->get());
|
||||
}
|
||||
|
||||
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("Load.."), MENU_LOAD_FILE);
|
||||
|
||||
|
||||
menu->set_global_position(blend_space_draw->get_global_transform().xform(mb->get_position()));
|
||||
menu->popup();
|
||||
add_point_pos = (mb->get_position() / blend_space_draw->get_size());
|
||||
|
@ -203,7 +211,8 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
blend_pos += blend_space->get_min_space();
|
||||
|
||||
blend_space->set_blend_position(blend_pos);
|
||||
AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(),blend_pos);
|
||||
|
||||
blend_space_draw->update();
|
||||
}
|
||||
|
||||
|
@ -237,21 +246,54 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
|
|||
blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
blend_pos += blend_space->get_min_space();
|
||||
|
||||
blend_space->set_blend_position(blend_pos);
|
||||
AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(),blend_pos);
|
||||
|
||||
blend_space_draw->update();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2DEditor::_file_opened(const String &p_file) {
|
||||
|
||||
file_loaded = ResourceLoader::load(p_file);
|
||||
if (file_loaded.is_valid()) {
|
||||
_add_menu_type(MENU_LOAD_FILE_CONFIRM);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2DEditor::_add_menu_type(int p_index) {
|
||||
|
||||
String type = menu->get_item_metadata(p_index);
|
||||
Ref<AnimationRootNode> node;
|
||||
if (p_index == MENU_LOAD_FILE) {
|
||||
|
||||
Object *obj = ClassDB::instance(type);
|
||||
ERR_FAIL_COND(!obj);
|
||||
AnimationNode *an = Object::cast_to<AnimationNode>(obj);
|
||||
ERR_FAIL_COND(!an);
|
||||
open_file->clear_filters();
|
||||
List<String> filters;
|
||||
ResourceLoader::get_recognized_extensions_for_type("AnimationRootNode", &filters);
|
||||
for (List<String>::Element *E = filters.front(); E; E = E->next()) {
|
||||
open_file->add_filter("*." + E->get());
|
||||
}
|
||||
open_file->popup_centered_ratio();
|
||||
return;
|
||||
} else if (p_index == MENU_LOAD_FILE_CONFIRM) {
|
||||
node = file_loaded;
|
||||
file_loaded.unref();
|
||||
} else if (p_index == MENU_PASTE) {
|
||||
|
||||
Ref<AnimationNode> node(an);
|
||||
node = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
} else {
|
||||
String type = menu->get_item_metadata(p_index);
|
||||
|
||||
Object *obj = ClassDB::instance(type);
|
||||
ERR_FAIL_COND(!obj);
|
||||
AnimationNode *an = Object::cast_to<AnimationNode>(obj);
|
||||
ERR_FAIL_COND(!an);
|
||||
|
||||
node = Ref<AnimationNode>(an);
|
||||
}
|
||||
|
||||
if (!node.is_valid()) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("This type of node can't be used. Only root nodes are allowed."));
|
||||
return;
|
||||
}
|
||||
|
||||
updating = true;
|
||||
undo_redo->create_action("Add Node Point");
|
||||
|
@ -288,7 +330,7 @@ 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()));
|
||||
if (selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) {
|
||||
Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point);
|
||||
if (EditorNode::get_singleton()->item_has_editor(an.ptr())) {
|
||||
if (AnimationTreeEditor::get_singleton()->can_edit(an)) {
|
||||
open_editor->show();
|
||||
} else {
|
||||
open_editor->hide();
|
||||
|
@ -490,13 +532,15 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
|
|||
color.a *= 0.5;
|
||||
}
|
||||
|
||||
Vector2 point = blend_space->get_blend_position();
|
||||
Vector2 blend_pos = AnimationTreeEditor::get_singleton()->get_tree()->get(get_blend_position_path());
|
||||
Vector2 point = blend_pos;
|
||||
|
||||
point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
point *= s;
|
||||
point.y = s.height - point.y;
|
||||
|
||||
if (blend_space->get_triangle_count()) {
|
||||
Vector2 closest = blend_space->get_closest_point(blend_space->get_blend_position());
|
||||
Vector2 closest = blend_space->get_closest_point(blend_pos);
|
||||
closest = (closest - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
|
||||
closest *= s;
|
||||
closest.y = s.height - closest.y;
|
||||
|
@ -527,12 +571,6 @@ void AnimationNodeBlendSpace2DEditor::_update_space() {
|
|||
|
||||
updating = true;
|
||||
|
||||
if (blend_space->get_parent().is_valid()) {
|
||||
goto_parent_hb->show();
|
||||
} else {
|
||||
goto_parent_hb->hide();
|
||||
}
|
||||
|
||||
if (blend_space->get_auto_triangles()) {
|
||||
tool_triangle->hide();
|
||||
} else {
|
||||
|
@ -685,7 +723,6 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
|
|||
tool_erase->set_icon(get_icon("Remove", "EditorIcons"));
|
||||
snap->set_icon(get_icon("SnapGrid", "EditorIcons"));
|
||||
open_editor->set_icon(get_icon("Edit", "EditorIcons"));
|
||||
goto_parent->set_icon(get_icon("MoveUp", "EditorIcons"));
|
||||
auto_triangles->set_icon(get_icon("AutoTriangle", "EditorIcons"));
|
||||
}
|
||||
|
||||
|
@ -693,12 +730,12 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
|
|||
|
||||
String error;
|
||||
|
||||
if (!blend_space->get_tree()) {
|
||||
if (!AnimationTreeEditor::get_singleton()->get_tree()) {
|
||||
error = TTR("BlendSpace2D does not belong to an AnimationTree node.");
|
||||
} else if (!blend_space->get_tree()->is_active()) {
|
||||
} else if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
|
||||
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
|
||||
} else if (blend_space->get_tree()->is_state_invalid()) {
|
||||
error = blend_space->get_tree()->get_invalid_state_reason();
|
||||
} else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
|
||||
error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
|
||||
} else if (blend_space->get_triangle_count() == 0) {
|
||||
error = TTR("No triangles exist, so no blending can take place.");
|
||||
}
|
||||
|
@ -712,22 +749,22 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
set_process(is_visible_in_tree());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AnimationNodeBlendSpace2DEditor::_open_editor() {
|
||||
|
||||
if (selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) {
|
||||
Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point);
|
||||
ERR_FAIL_COND(!an.is_valid());
|
||||
EditorNode::get_singleton()->edit_item(an.ptr());
|
||||
ERR_FAIL_COND(an.is_null());
|
||||
AnimationTreeEditor::get_singleton()->enter_editor(itos(selected_point));
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2DEditor::_goto_parent() {
|
||||
|
||||
EditorNode::get_singleton()->edit_item(blend_space->get_parent().ptr());
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2DEditor::_removed_from_graph() {
|
||||
EditorNode::get_singleton()->edit_item(NULL);
|
||||
}
|
||||
|
@ -761,11 +798,13 @@ void AnimationNodeBlendSpace2DEditor::_bind_methods() {
|
|||
ClassDB::bind_method("_update_edited_point_pos", &AnimationNodeBlendSpace2DEditor::_update_edited_point_pos);
|
||||
|
||||
ClassDB::bind_method("_open_editor", &AnimationNodeBlendSpace2DEditor::_open_editor);
|
||||
ClassDB::bind_method("_goto_parent", &AnimationNodeBlendSpace2DEditor::_goto_parent);
|
||||
|
||||
ClassDB::bind_method("_removed_from_graph", &AnimationNodeBlendSpace2DEditor::_removed_from_graph);
|
||||
|
||||
ClassDB::bind_method("_auto_triangles_toggled", &AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled);
|
||||
|
||||
ClassDB::bind_method("_file_opened", &AnimationNodeBlendSpace2DEditor::_file_opened);
|
||||
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace2DEditor *AnimationNodeBlendSpace2DEditor::singleton = NULL;
|
||||
|
@ -781,14 +820,6 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
|
|||
Ref<ButtonGroup> bg;
|
||||
bg.instance();
|
||||
|
||||
goto_parent_hb = memnew(HBoxContainer);
|
||||
top_hb->add_child(goto_parent_hb);
|
||||
goto_parent = memnew(ToolButton);
|
||||
goto_parent->connect("pressed", this, "_goto_parent", varray(), CONNECT_DEFERRED);
|
||||
goto_parent_hb->add_child(goto_parent);
|
||||
goto_parent_hb->add_child(memnew(VSeparator));
|
||||
goto_parent_hb->hide();
|
||||
|
||||
tool_blend = memnew(ToolButton);
|
||||
tool_blend->set_toggle_mode(true);
|
||||
tool_blend->set_button_group(bg);
|
||||
|
@ -968,13 +999,20 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
|
|||
|
||||
menu = memnew(PopupMenu);
|
||||
add_child(menu);
|
||||
menu->connect("index_pressed", this, "_add_menu_type");
|
||||
menu->connect("id_pressed", this, "_add_menu_type");
|
||||
|
||||
animations_menu = memnew(PopupMenu);
|
||||
menu->add_child(animations_menu);
|
||||
animations_menu->set_name("animations");
|
||||
animations_menu->connect("index_pressed", this, "_add_animation_type");
|
||||
|
||||
open_file = memnew(EditorFileDialog);
|
||||
add_child(open_file);
|
||||
open_file->set_title(TTR("Open Animation Node"));
|
||||
open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
||||
open_file->connect("file_selected", this, "_file_opened");
|
||||
undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
selected_point = -1;
|
||||
selected_triangle = -1;
|
||||
|
||||
|
@ -982,42 +1020,3 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
|
|||
dragging_selected_attempt = false;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2DEditorPlugin::edit(Object *p_object) {
|
||||
|
||||
anim_tree_editor->edit(Object::cast_to<AnimationNodeBlendSpace2D>(p_object));
|
||||
}
|
||||
|
||||
bool AnimationNodeBlendSpace2DEditorPlugin::handles(Object *p_object) const {
|
||||
|
||||
return p_object->is_class("AnimationNodeBlendSpace2D");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2DEditorPlugin::make_visible(bool p_visible) {
|
||||
|
||||
if (p_visible) {
|
||||
//editor->hide_animation_player_editors();
|
||||
//editor->animation_panel_make_visible(true);
|
||||
button->show();
|
||||
editor->make_bottom_panel_item_visible(anim_tree_editor);
|
||||
anim_tree_editor->set_process(true);
|
||||
} else {
|
||||
|
||||
if (anim_tree_editor->is_visible_in_tree())
|
||||
editor->hide_bottom_panel();
|
||||
button->hide();
|
||||
anim_tree_editor->set_process(false);
|
||||
}
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace2DEditorPlugin::AnimationNodeBlendSpace2DEditorPlugin(EditorNode *p_node) {
|
||||
|
||||
editor = p_node;
|
||||
anim_tree_editor = memnew(AnimationNodeBlendSpace2DEditor);
|
||||
anim_tree_editor->set_custom_minimum_size(Size2(0, 300));
|
||||
|
||||
button = editor->add_bottom_panel_item(TTR("BlendSpace2D"), anim_tree_editor);
|
||||
button->hide();
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace2DEditorPlugin::~AnimationNodeBlendSpace2DEditorPlugin() {
|
||||
}
|
||||
|
|
|
@ -9,18 +9,17 @@
|
|||
#include "scene/gui/graph_edit.h"
|
||||
#include "scene/gui/popup.h"
|
||||
#include "scene/gui/tree.h"
|
||||
#include "editor/plugins/animation_tree_editor_plugin.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
class AnimationNodeBlendSpace2DEditor : public VBoxContainer {
|
||||
class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
|
||||
|
||||
GDCLASS(AnimationNodeBlendSpace2DEditor, VBoxContainer);
|
||||
GDCLASS(AnimationNodeBlendSpace2DEditor, AnimationTreeNodeEditorPlugin);
|
||||
|
||||
Ref<AnimationNodeBlendSpace2D> blend_space;
|
||||
|
||||
HBoxContainer *goto_parent_hb;
|
||||
ToolButton *goto_parent;
|
||||
|
||||
PanelContainer *panel;
|
||||
ToolButton *tool_blend;
|
||||
|
@ -93,38 +92,32 @@ class AnimationNodeBlendSpace2DEditor : public VBoxContainer {
|
|||
void _edit_point_pos(double);
|
||||
void _open_editor();
|
||||
|
||||
void _goto_parent();
|
||||
|
||||
void _removed_from_graph();
|
||||
|
||||
void _auto_triangles_toggled();
|
||||
|
||||
StringName get_blend_position_path() const;
|
||||
|
||||
EditorFileDialog *open_file;
|
||||
Ref<AnimationNode> file_loaded;
|
||||
void _file_opened(const String &p_file);
|
||||
|
||||
enum {
|
||||
MENU_LOAD_FILE = 1000,
|
||||
MENU_PASTE = 1001,
|
||||
MENU_LOAD_FILE_CONFIRM = 1002
|
||||
};
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static AnimationNodeBlendSpace2DEditor *get_singleton() { return singleton; }
|
||||
void edit(AnimationNodeBlendSpace2D *p_blend_space);
|
||||
virtual bool can_edit(const Ref<AnimationNode> &p_node);
|
||||
virtual void edit(const Ref<AnimationNode> &p_node);
|
||||
AnimationNodeBlendSpace2DEditor();
|
||||
};
|
||||
|
||||
class AnimationNodeBlendSpace2DEditorPlugin : public EditorPlugin {
|
||||
|
||||
GDCLASS(AnimationNodeBlendSpace2DEditorPlugin, EditorPlugin);
|
||||
|
||||
AnimationNodeBlendSpace2DEditor *anim_tree_editor;
|
||||
EditorNode *editor;
|
||||
Button *button;
|
||||
|
||||
public:
|
||||
virtual String get_name() const { return "BlendSpace2D"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_object);
|
||||
virtual bool handles(Object *p_object) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
AnimationNodeBlendSpace2DEditorPlugin(EditorNode *p_node);
|
||||
~AnimationNodeBlendSpace2DEditorPlugin();
|
||||
};
|
||||
#endif // ANIMATION_BLEND_SPACE_2D_EDITOR_H
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/project_settings.h"
|
||||
#include "editor/editor_inspector.h"
|
||||
#include "os/input.h"
|
||||
#include "os/keyboard.h"
|
||||
#include "scene/animation/animation_player.h"
|
||||
|
@ -9,27 +10,6 @@
|
|||
#include "scene/gui/panel.h"
|
||||
#include "scene/main/viewport.h"
|
||||
|
||||
void AnimationNodeBlendTreeEditor::edit(AnimationNodeBlendTree *p_blend_tree) {
|
||||
|
||||
if (blend_tree.is_valid()) {
|
||||
blend_tree->disconnect("removed_from_graph", this, "_removed_from_graph");
|
||||
}
|
||||
|
||||
if (p_blend_tree) {
|
||||
blend_tree = Ref<AnimationNodeBlendTree>(p_blend_tree);
|
||||
} else {
|
||||
blend_tree.unref();
|
||||
}
|
||||
|
||||
if (blend_tree.is_null()) {
|
||||
hide();
|
||||
} else {
|
||||
blend_tree->connect("removed_from_graph", this, "_removed_from_graph");
|
||||
|
||||
_update_graph();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::add_custom_type(const String &p_name, const Ref<Script> &p_script) {
|
||||
|
||||
for (int i = 0; i < add_options.size(); i++) {
|
||||
|
@ -58,10 +38,19 @@ void AnimationNodeBlendTreeEditor::remove_custom_type(const Ref<Script> &p_scrip
|
|||
|
||||
void AnimationNodeBlendTreeEditor::_update_options_menu() {
|
||||
|
||||
print_line("update options");
|
||||
add_node->get_popup()->clear();
|
||||
for (int i = 0; i < add_options.size(); i++) {
|
||||
add_node->get_popup()->add_item(add_options[i].name);
|
||||
add_node->get_popup()->add_item(add_options[i].name, i);
|
||||
}
|
||||
|
||||
Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
if (clipb.is_valid()) {
|
||||
add_node->get_popup()->add_separator();
|
||||
add_node->get_popup()->add_item(TTR("Paste"), MENU_PASTE);
|
||||
}
|
||||
add_node->get_popup()->add_separator();
|
||||
add_node->get_popup()->add_item(TTR("Load.."), MENU_LOAD_FILE);
|
||||
}
|
||||
|
||||
Size2 AnimationNodeBlendTreeEditor::get_minimum_size() const {
|
||||
|
@ -69,18 +58,28 @@ Size2 AnimationNodeBlendTreeEditor::get_minimum_size() const {
|
|||
return Size2(10, 200);
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_property_changed(const StringName &p_property, const Variant &p_value) {
|
||||
|
||||
AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_tree();
|
||||
updating = true;
|
||||
undo_redo->create_action("Parameter Changed: " + String(p_property), UndoRedo::MERGE_ENDS);
|
||||
undo_redo->add_do_property(tree, p_property, p_value);
|
||||
undo_redo->add_undo_property(tree, p_property, tree->get(p_property));
|
||||
undo_redo->add_do_method(this, "_update_graph");
|
||||
undo_redo->add_undo_method(this, "_update_graph");
|
||||
undo_redo->commit_action();
|
||||
updating = false;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_update_graph() {
|
||||
|
||||
if (updating)
|
||||
return;
|
||||
|
||||
visible_properties.clear();
|
||||
|
||||
graph->set_scroll_ofs(blend_tree->get_graph_offset() * EDSCALE);
|
||||
|
||||
if (blend_tree->get_parent().is_valid()) {
|
||||
goto_parent->show();
|
||||
} else {
|
||||
goto_parent->hide();
|
||||
}
|
||||
graph->clear_connections();
|
||||
//erase all nodes
|
||||
for (int i = 0; i < graph->get_child_count(); i++) {
|
||||
|
@ -107,7 +106,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
agnode->connect("changed", this, "_node_changed", varray(agnode->get_instance_id()), CONNECT_DEFERRED);
|
||||
}
|
||||
|
||||
node->set_offset(agnode->get_position() * EDSCALE);
|
||||
node->set_offset(blend_tree->get_node_position(E->get()) * EDSCALE);
|
||||
|
||||
node->set_title(agnode->get_caption());
|
||||
node->set_name(E->get());
|
||||
|
@ -133,9 +132,28 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
node->set_slot(base + i, true, 0, get_color("font_color", "Label"), false, 0, Color());
|
||||
}
|
||||
|
||||
node->connect("dragged", this, "_node_dragged", varray(agnode));
|
||||
List<PropertyInfo> pinfo;
|
||||
agnode->get_parameter_list(&pinfo);
|
||||
for (List<PropertyInfo>::Element *F = pinfo.front(); F; F = F->next()) {
|
||||
|
||||
if (EditorNode::get_singleton()->item_has_editor(agnode.ptr())) {
|
||||
if (!(F->get().usage & PROPERTY_USAGE_EDITOR)) {
|
||||
continue;
|
||||
}
|
||||
String base_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E->get()) + "/" + F->get().name;
|
||||
EditorProperty *prop = EditorInspector::instantiate_property_editor(AnimationTreeEditor::get_singleton()->get_tree(), F->get().type, base_path, F->get().hint, F->get().hint_string, F->get().usage);
|
||||
if (prop) {
|
||||
prop->set_object_and_property(AnimationTreeEditor::get_singleton()->get_tree(), base_path);
|
||||
prop->update_property();
|
||||
prop->set_name_split_ratio(0);
|
||||
prop->connect("property_changed", this, "_property_changed");
|
||||
node->add_child(prop);
|
||||
visible_properties.push_back(prop);
|
||||
}
|
||||
}
|
||||
|
||||
node->connect("dragged", this, "_node_dragged", varray(E->get()));
|
||||
|
||||
if (AnimationTreeEditor::get_singleton()->can_edit(agnode)) {
|
||||
node->add_child(memnew(HSeparator));
|
||||
Button *open_in_editor = memnew(Button);
|
||||
open_in_editor->set_text(TTR("Open Editor"));
|
||||
|
@ -169,7 +187,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
|
||||
ProgressBar *pb = memnew(ProgressBar);
|
||||
|
||||
AnimationTree *player = anim->get_tree();
|
||||
AnimationTree *player = AnimationTreeEditor::get_singleton()->get_tree();
|
||||
if (player->has_node(player->get_animation_player())) {
|
||||
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(player->get_node(player->get_animation_player()));
|
||||
if (ap) {
|
||||
|
@ -194,6 +212,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
mb->get_popup()->connect("index_pressed", this, "_anim_selected", varray(options, E->get()), CONNECT_DEFERRED);
|
||||
}
|
||||
|
||||
/* should be no longer necesary, as the boolean works
|
||||
Ref<AnimationNodeOneShot> oneshot = agnode;
|
||||
if (oneshot.is_valid()) {
|
||||
|
||||
|
@ -209,7 +228,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
play_stop->add_child(stop);
|
||||
play_stop->add_spacer();
|
||||
node->add_child(play_stop);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
List<AnimationNodeBlendTree::NodeConnection> connections;
|
||||
|
@ -225,16 +244,44 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
|
|||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
|
||||
void AnimationNodeBlendTreeEditor::_file_opened(const String &p_file) {
|
||||
|
||||
ERR_FAIL_INDEX(p_idx, add_options.size());
|
||||
file_loaded = ResourceLoader::load(p_file);
|
||||
if (file_loaded.is_valid()) {
|
||||
_add_node(MENU_LOAD_FILE_CONFIRM);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
|
||||
|
||||
Ref<AnimationNode> anode;
|
||||
|
||||
if (add_options[p_idx].type != String()) {
|
||||
String base_name;
|
||||
|
||||
if (p_idx == MENU_LOAD_FILE) {
|
||||
|
||||
open_file->clear_filters();
|
||||
List<String> filters;
|
||||
ResourceLoader::get_recognized_extensions_for_type("AnimationNode", &filters);
|
||||
for (List<String>::Element *E = filters.front(); E; E = E->next()) {
|
||||
open_file->add_filter("*." + E->get());
|
||||
}
|
||||
open_file->popup_centered_ratio();
|
||||
return;
|
||||
} else if (p_idx == MENU_LOAD_FILE_CONFIRM) {
|
||||
anode = file_loaded;
|
||||
file_loaded.unref();
|
||||
base_name = anode->get_class();
|
||||
} else if (p_idx == MENU_PASTE) {
|
||||
|
||||
anode = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
ERR_FAIL_COND(!anode.is_valid());
|
||||
base_name = anode->get_class();
|
||||
} else if (add_options[p_idx].type != String()) {
|
||||
AnimationNode *an = Object::cast_to<AnimationNode>(ClassDB::instance(add_options[p_idx].type));
|
||||
ERR_FAIL_COND(!an);
|
||||
anode = Ref<AnimationNode>(an);
|
||||
base_name = add_options[p_idx].name;
|
||||
} else {
|
||||
ERR_FAIL_COND(add_options[p_idx].script.is_null());
|
||||
String base_type = add_options[p_idx].script->get_instance_base_type();
|
||||
|
@ -242,13 +289,16 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
|
|||
ERR_FAIL_COND(!an);
|
||||
anode = Ref<AnimationNode>(an);
|
||||
anode->set_script(add_options[p_idx].script.get_ref_ptr());
|
||||
base_name = add_options[p_idx].name;
|
||||
}
|
||||
|
||||
Ref<AnimationNodeOutput> out = anode;
|
||||
if (out.is_valid()) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Output node can't be added to the blend tree."));
|
||||
return;
|
||||
}
|
||||
Point2 instance_pos = graph->get_scroll_ofs() + graph->get_size() * 0.5;
|
||||
|
||||
anode->set_position(instance_pos / EDSCALE);
|
||||
|
||||
String base_name = add_options[p_idx].name;
|
||||
int base = 1;
|
||||
String name = base_name;
|
||||
while (blend_tree->has_node(name)) {
|
||||
|
@ -257,19 +307,19 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
|
|||
}
|
||||
|
||||
undo_redo->create_action("Add Node to BlendTree");
|
||||
undo_redo->add_do_method(blend_tree.ptr(), "add_node", name, anode);
|
||||
undo_redo->add_do_method(blend_tree.ptr(), "add_node", name, anode, instance_pos / EDSCALE);
|
||||
undo_redo->add_undo_method(blend_tree.ptr(), "remove_node", name);
|
||||
undo_redo->add_do_method(this, "_update_graph");
|
||||
undo_redo->add_undo_method(this, "_update_graph");
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, Ref<AnimationNode> p_node) {
|
||||
void AnimationNodeBlendTreeEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, const StringName &p_which) {
|
||||
|
||||
updating = true;
|
||||
undo_redo->create_action("Node Moved");
|
||||
undo_redo->add_do_method(p_node.ptr(), "set_position", p_to / EDSCALE);
|
||||
undo_redo->add_undo_method(p_node.ptr(), "set_position", p_from / EDSCALE);
|
||||
undo_redo->add_do_method(blend_tree.ptr(), "set_node_position", p_which, p_to / EDSCALE);
|
||||
undo_redo->add_undo_method(blend_tree.ptr(), "set_node_position", p_which, p_from / EDSCALE);
|
||||
undo_redo->add_do_method(this, "_update_graph");
|
||||
undo_redo->add_undo_method(this, "_update_graph");
|
||||
undo_redo->commit_action();
|
||||
|
@ -342,20 +392,6 @@ void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) {
|
|||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_oneshot_start(const StringName &p_name) {
|
||||
|
||||
Ref<AnimationNodeOneShot> os = blend_tree->get_node(p_name);
|
||||
ERR_FAIL_COND(!os.is_valid());
|
||||
os->start();
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_oneshot_stop(const StringName &p_name) {
|
||||
|
||||
Ref<AnimationNodeOneShot> os = blend_tree->get_node(p_name);
|
||||
ERR_FAIL_COND(!os.is_valid());
|
||||
os->stop();
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_node_selected(Object *p_node) {
|
||||
|
||||
GraphNode *gn = Object::cast_to<GraphNode>(p_node);
|
||||
|
@ -373,13 +409,7 @@ void AnimationNodeBlendTreeEditor::_open_in_editor(const String &p_which) {
|
|||
|
||||
Ref<AnimationNode> an = blend_tree->get_node(p_which);
|
||||
ERR_FAIL_COND(!an.is_valid())
|
||||
EditorNode::get_singleton()->edit_item(an.ptr());
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_open_parent() {
|
||||
if (blend_tree->get_parent().is_valid()) {
|
||||
EditorNode::get_singleton()->edit_item(blend_tree->get_parent().ptr());
|
||||
}
|
||||
AnimationTreeEditor::get_singleton()->enter_editor(p_which);
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_filter_toggled() {
|
||||
|
@ -417,14 +447,14 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
|
|||
if (updating || _filter_edit != anode)
|
||||
return false;
|
||||
|
||||
NodePath player_path = anode->get_tree()->get_animation_player();
|
||||
NodePath player_path = AnimationTreeEditor::get_singleton()->get_tree()->get_animation_player();
|
||||
|
||||
if (!anode->get_tree()->has_node(player_path)) {
|
||||
if (!AnimationTreeEditor::get_singleton()->get_tree()->has_node(player_path)) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("No animation player set, so unable to retrieve track names."));
|
||||
return false;
|
||||
}
|
||||
|
||||
AnimationPlayer *player = Object::cast_to<AnimationPlayer>(anode->get_tree()->get_node(player_path));
|
||||
AnimationPlayer *player = Object::cast_to<AnimationPlayer>(AnimationTreeEditor::get_singleton()->get_tree()->get_node(player_path));
|
||||
if (!player) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Player path set is invalid, so unable to retrieve track names."));
|
||||
return false;
|
||||
|
@ -593,8 +623,6 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
|
|||
|
||||
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
|
||||
|
||||
goto_parent->set_icon(get_icon("MoveUp", "EditorIcons"));
|
||||
|
||||
error_panel->add_style_override("panel", get_stylebox("bg", "Tree"));
|
||||
error_label->add_color_override("font_color", get_color("error_color", "Editor"));
|
||||
}
|
||||
|
@ -603,12 +631,10 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
|
|||
|
||||
String error;
|
||||
|
||||
if (!blend_tree->get_tree()) {
|
||||
error = TTR("BlendTree does not belong to an AnimationTree node.");
|
||||
} else if (!blend_tree->get_tree()->is_active()) {
|
||||
if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
|
||||
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
|
||||
} else if (blend_tree->get_tree()->is_state_invalid()) {
|
||||
error = blend_tree->get_tree()->get_invalid_state_reason();
|
||||
} else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
|
||||
error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
|
||||
}
|
||||
|
||||
if (error != error_label->get_text()) {
|
||||
|
@ -624,13 +650,13 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
|
|||
blend_tree->get_node_connections(&conns);
|
||||
for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = conns.front(); E; E = E->next()) {
|
||||
float activity = 0;
|
||||
if (blend_tree->get_tree() && !blend_tree->get_tree()->is_state_invalid()) {
|
||||
if (AnimationTreeEditor::get_singleton()->get_tree() && !AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
|
||||
activity = blend_tree->get_connection_activity(E->get().input_node, E->get().input_index);
|
||||
}
|
||||
graph->set_connection_activity(E->get().output_node, 0, E->get().input_node, E->get().input_index, activity);
|
||||
}
|
||||
|
||||
AnimationTree *graph_player = blend_tree->get_tree();
|
||||
AnimationTree *graph_player = AnimationTreeEditor::get_singleton()->get_tree();
|
||||
AnimationPlayer *player = NULL;
|
||||
if (graph_player->has_node(graph_player->get_animation_player())) {
|
||||
player = Object::cast_to<AnimationPlayer>(graph_player->get_node(graph_player->get_animation_player()));
|
||||
|
@ -650,6 +676,14 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < visible_properties.size(); i++) {
|
||||
visible_properties[i]->update_property();
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
set_process(is_visible_in_tree());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -664,9 +698,9 @@ void AnimationNodeBlendTreeEditor::_scroll_changed(const Vector2 &p_scroll) {
|
|||
void AnimationNodeBlendTreeEditor::_node_changed(ObjectID p_node) {
|
||||
|
||||
AnimationNode *an = Object::cast_to<AnimationNode>(ObjectDB::get_instance(p_node));
|
||||
if (an && an->get_parent() == blend_tree) {
|
||||
_update_graph();
|
||||
}
|
||||
//if (an && an->get_parent() == blend_tree) {
|
||||
_update_graph();
|
||||
//}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_bind_methods() {
|
||||
|
@ -680,17 +714,17 @@ void AnimationNodeBlendTreeEditor::_bind_methods() {
|
|||
ClassDB::bind_method("_disconnection_request", &AnimationNodeBlendTreeEditor::_disconnection_request);
|
||||
ClassDB::bind_method("_node_selected", &AnimationNodeBlendTreeEditor::_node_selected);
|
||||
ClassDB::bind_method("_open_in_editor", &AnimationNodeBlendTreeEditor::_open_in_editor);
|
||||
ClassDB::bind_method("_open_parent", &AnimationNodeBlendTreeEditor::_open_parent);
|
||||
ClassDB::bind_method("_scroll_changed", &AnimationNodeBlendTreeEditor::_scroll_changed);
|
||||
ClassDB::bind_method("_delete_request", &AnimationNodeBlendTreeEditor::_delete_request);
|
||||
ClassDB::bind_method("_edit_filters", &AnimationNodeBlendTreeEditor::_edit_filters);
|
||||
ClassDB::bind_method("_update_filters", &AnimationNodeBlendTreeEditor::_update_filters);
|
||||
ClassDB::bind_method("_filter_edited", &AnimationNodeBlendTreeEditor::_filter_edited);
|
||||
ClassDB::bind_method("_filter_toggled", &AnimationNodeBlendTreeEditor::_filter_toggled);
|
||||
ClassDB::bind_method("_oneshot_start", &AnimationNodeBlendTreeEditor::_oneshot_start);
|
||||
ClassDB::bind_method("_oneshot_stop", &AnimationNodeBlendTreeEditor::_oneshot_stop);
|
||||
ClassDB::bind_method("_node_changed", &AnimationNodeBlendTreeEditor::_node_changed);
|
||||
ClassDB::bind_method("_removed_from_graph", &AnimationNodeBlendTreeEditor::_removed_from_graph);
|
||||
ClassDB::bind_method("_property_changed", &AnimationNodeBlendTreeEditor::_property_changed);
|
||||
ClassDB::bind_method("_file_opened", &AnimationNodeBlendTreeEditor::_file_opened);
|
||||
ClassDB::bind_method("_update_options_menu", &AnimationNodeBlendTreeEditor::_update_options_menu);
|
||||
|
||||
ClassDB::bind_method("_anim_selected", &AnimationNodeBlendTreeEditor::_anim_selected);
|
||||
}
|
||||
|
@ -708,7 +742,9 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
|
|||
|
||||
ERR_FAIL_COND(new_name == "" || new_name.find(".") != -1 || new_name.find("/") != -1)
|
||||
|
||||
ERR_FAIL_COND(new_name == prev_name);
|
||||
if (new_name == prev_name) {
|
||||
return; //nothing to do
|
||||
}
|
||||
|
||||
String base_name = new_name;
|
||||
int base = 1;
|
||||
|
@ -718,22 +754,61 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
|
|||
name = base_name + " " + itos(base);
|
||||
}
|
||||
|
||||
String base_path = AnimationTreeEditor::get_singleton()->get_base_path();
|
||||
|
||||
updating = true;
|
||||
undo_redo->create_action("Node Renamed");
|
||||
undo_redo->add_do_method(blend_tree.ptr(), "rename_node", prev_name, name);
|
||||
undo_redo->add_undo_method(blend_tree.ptr(), "rename_node", name, prev_name);
|
||||
undo_redo->add_do_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + prev_name, base_path + name);
|
||||
undo_redo->add_undo_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + name, base_path + prev_name);
|
||||
undo_redo->add_do_method(this, "_update_graph");
|
||||
undo_redo->add_undo_method(this, "_update_graph");
|
||||
undo_redo->commit_action();
|
||||
updating = false;
|
||||
gn->set_name(new_name);
|
||||
gn->set_size(gn->get_minimum_size());
|
||||
|
||||
//change editors accordingly
|
||||
for (int i = 0; i < visible_properties.size(); i++) {
|
||||
String pname = visible_properties[i]->get_edited_property().operator String();
|
||||
if (pname.begins_with(base_path + prev_name)) {
|
||||
String new_name = pname.replace_first(base_path + prev_name, base_path + name);
|
||||
visible_properties[i]->set_object_and_property(visible_properties[i]->get_edited_object(), new_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::_node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node) {
|
||||
_node_renamed(le->call("get_text"), p_node);
|
||||
}
|
||||
|
||||
bool AnimationNodeBlendTreeEditor::can_edit(const Ref<AnimationNode> &p_node) {
|
||||
Ref<AnimationNodeBlendTree> bt = p_node;
|
||||
return bt.is_valid();
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditor::edit(const Ref<AnimationNode> &p_node) {
|
||||
|
||||
if (blend_tree.is_valid()) {
|
||||
blend_tree->disconnect("removed_from_graph", this, "_removed_from_graph");
|
||||
}
|
||||
|
||||
if (p_node.is_valid()) {
|
||||
blend_tree = p_node;
|
||||
} else {
|
||||
blend_tree.unref();
|
||||
}
|
||||
|
||||
if (blend_tree.is_null()) {
|
||||
hide();
|
||||
} else {
|
||||
blend_tree->connect("removed_from_graph", this, "_removed_from_graph");
|
||||
|
||||
_update_graph();
|
||||
}
|
||||
}
|
||||
|
||||
AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
|
||||
|
||||
singleton = this;
|
||||
|
@ -757,13 +832,8 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
|
|||
graph->get_zoom_hbox()->add_child(add_node);
|
||||
add_node->set_text(TTR("Add Node.."));
|
||||
graph->get_zoom_hbox()->move_child(add_node, 0);
|
||||
add_node->get_popup()->connect("index_pressed", this, "_add_node");
|
||||
|
||||
goto_parent = memnew(Button);
|
||||
graph->get_zoom_hbox()->add_child(goto_parent);
|
||||
graph->get_zoom_hbox()->move_child(goto_parent, 0);
|
||||
goto_parent->hide();
|
||||
goto_parent->connect("pressed", this, "_open_parent");
|
||||
add_node->get_popup()->connect("id_pressed", this, "_add_node");
|
||||
add_node->connect("about_to_show", this, "_update_options_menu");
|
||||
|
||||
add_options.push_back(AddOption("Animation", "AnimationNodeAnimation"));
|
||||
add_options.push_back(AddOption("OneShot", "AnimationNodeOneShot"));
|
||||
|
@ -804,45 +874,10 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() {
|
|||
filters->set_hide_root(true);
|
||||
filters->connect("item_edited", this, "_filter_edited");
|
||||
|
||||
open_file = memnew(EditorFileDialog);
|
||||
add_child(open_file);
|
||||
open_file->set_title(TTR("Open Animation Node"));
|
||||
open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
||||
open_file->connect("file_selected", this, "_file_opened");
|
||||
undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditorPlugin::edit(Object *p_object) {
|
||||
|
||||
anim_tree_editor->edit(Object::cast_to<AnimationNodeBlendTree>(p_object));
|
||||
}
|
||||
|
||||
bool AnimationNodeBlendTreeEditorPlugin::handles(Object *p_object) const {
|
||||
|
||||
return p_object->is_class("AnimationNodeBlendTree");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTreeEditorPlugin::make_visible(bool p_visible) {
|
||||
|
||||
if (p_visible) {
|
||||
//editor->hide_animation_player_editors();
|
||||
//editor->animation_panel_make_visible(true);
|
||||
button->show();
|
||||
editor->make_bottom_panel_item_visible(anim_tree_editor);
|
||||
anim_tree_editor->set_process(true);
|
||||
} else {
|
||||
|
||||
if (anim_tree_editor->is_visible_in_tree())
|
||||
editor->hide_bottom_panel();
|
||||
button->hide();
|
||||
anim_tree_editor->set_process(false);
|
||||
}
|
||||
}
|
||||
|
||||
AnimationNodeBlendTreeEditorPlugin::AnimationNodeBlendTreeEditorPlugin(EditorNode *p_node) {
|
||||
|
||||
editor = p_node;
|
||||
anim_tree_editor = memnew(AnimationNodeBlendTreeEditor);
|
||||
anim_tree_editor->set_custom_minimum_size(Size2(0, 300));
|
||||
|
||||
button = editor->add_bottom_panel_item(TTR("BlendTree"), anim_tree_editor);
|
||||
button->hide();
|
||||
}
|
||||
|
||||
AnimationNodeBlendTreeEditorPlugin::~AnimationNodeBlendTreeEditorPlugin() {
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_plugin.h"
|
||||
#include "editor/plugins/animation_tree_editor_plugin.h"
|
||||
#include "editor/property_editor.h"
|
||||
#include "scene/animation/animation_blend_tree.h"
|
||||
#include "scene/gui/button.h"
|
||||
|
@ -13,14 +14,13 @@
|
|||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
class AnimationNodeBlendTreeEditor : public VBoxContainer {
|
||||
class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
|
||||
|
||||
GDCLASS(AnimationNodeBlendTreeEditor, VBoxContainer);
|
||||
GDCLASS(AnimationNodeBlendTreeEditor, AnimationTreeNodeEditorPlugin);
|
||||
|
||||
Ref<AnimationNodeBlendTree> blend_tree;
|
||||
GraphEdit *graph;
|
||||
MenuButton *add_node;
|
||||
Button *goto_parent;
|
||||
|
||||
PanelContainer *error_panel;
|
||||
Label *error_label;
|
||||
|
@ -32,6 +32,7 @@ class AnimationNodeBlendTreeEditor : public VBoxContainer {
|
|||
CheckBox *filter_enabled;
|
||||
|
||||
Map<StringName, ProgressBar *> animations;
|
||||
Vector<EditorProperty *> visible_properties;
|
||||
|
||||
void _update_graph();
|
||||
|
||||
|
@ -52,7 +53,7 @@ class AnimationNodeBlendTreeEditor : public VBoxContainer {
|
|||
|
||||
static AnimationNodeBlendTreeEditor *singleton;
|
||||
|
||||
void _node_dragged(const Vector2 &p_from, const Vector2 &p_to, Ref<AnimationNode> p_node);
|
||||
void _node_dragged(const Vector2 &p_from, const Vector2 &p_to, const StringName &p_which);
|
||||
void _node_renamed(const String &p_text, Ref<AnimationNode> p_node);
|
||||
void _node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node);
|
||||
|
||||
|
@ -64,11 +65,8 @@ class AnimationNodeBlendTreeEditor : public VBoxContainer {
|
|||
void _scroll_changed(const Vector2 &p_scroll);
|
||||
void _node_selected(Object *p_node);
|
||||
void _open_in_editor(const String &p_which);
|
||||
void _open_parent();
|
||||
void _anim_selected(int p_index, Array p_options, const String &p_node);
|
||||
void _delete_request(const String &p_which);
|
||||
void _oneshot_start(const StringName &p_name);
|
||||
void _oneshot_stop(const StringName &p_name);
|
||||
|
||||
bool _update_filters(const Ref<AnimationNode> &anode);
|
||||
void _edit_filters(const String &p_which);
|
||||
|
@ -78,8 +76,19 @@ class AnimationNodeBlendTreeEditor : public VBoxContainer {
|
|||
|
||||
void _node_changed(ObjectID p_node);
|
||||
|
||||
void _property_changed(const StringName &p_property, const Variant &p_value);
|
||||
void _removed_from_graph();
|
||||
|
||||
EditorFileDialog *open_file;
|
||||
Ref<AnimationNode> file_loaded;
|
||||
void _file_opened(const String &p_file);
|
||||
|
||||
enum {
|
||||
MENU_LOAD_FILE = 1000,
|
||||
MENU_PASTE = 1001,
|
||||
MENU_LOAD_FILE_CONFIRM = 1002
|
||||
};
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
@ -91,27 +100,11 @@ public:
|
|||
void remove_custom_type(const Ref<Script> &p_script);
|
||||
|
||||
virtual Size2 get_minimum_size() const;
|
||||
void edit(AnimationNodeBlendTree *p_blend_tree);
|
||||
|
||||
virtual bool can_edit(const Ref<AnimationNode> &p_node);
|
||||
virtual void edit(const Ref<AnimationNode> &p_node);
|
||||
|
||||
AnimationNodeBlendTreeEditor();
|
||||
};
|
||||
|
||||
class AnimationNodeBlendTreeEditorPlugin : public EditorPlugin {
|
||||
|
||||
GDCLASS(AnimationNodeBlendTreeEditorPlugin, EditorPlugin);
|
||||
|
||||
AnimationNodeBlendTreeEditor *anim_tree_editor;
|
||||
EditorNode *editor;
|
||||
Button *button;
|
||||
|
||||
public:
|
||||
virtual String get_name() const { return "BlendTree"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_object);
|
||||
virtual bool handles(Object *p_object) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
AnimationNodeBlendTreeEditorPlugin(EditorNode *p_node);
|
||||
~AnimationNodeBlendTreeEditorPlugin();
|
||||
};
|
||||
|
||||
#endif // ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H
|
||||
|
|
|
@ -11,22 +11,17 @@
|
|||
#include "scene/gui/panel.h"
|
||||
#include "scene/main/viewport.h"
|
||||
|
||||
void AnimationNodeStateMachineEditor::edit(AnimationNodeStateMachine *p_state_machine) {
|
||||
bool AnimationNodeStateMachineEditor::can_edit(const Ref<AnimationNode> &p_node) {
|
||||
|
||||
Ref<AnimationNodeStateMachine> ansm = p_node;
|
||||
return ansm.is_valid();
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditor::edit(const Ref<AnimationNode> &p_node) {
|
||||
|
||||
state_machine = p_node;
|
||||
|
||||
if (state_machine.is_valid()) {
|
||||
state_machine->disconnect("removed_from_graph", this, "_removed_from_graph");
|
||||
}
|
||||
|
||||
if (p_state_machine) {
|
||||
state_machine = Ref<AnimationNodeStateMachine>(p_state_machine);
|
||||
} else {
|
||||
state_machine.unref();
|
||||
}
|
||||
|
||||
if (state_machine.is_null()) {
|
||||
hide();
|
||||
} else {
|
||||
state_machine->connect("removed_from_graph", this, "_removed_from_graph");
|
||||
|
||||
selected_transition_from = StringName();
|
||||
selected_transition_to = StringName();
|
||||
|
@ -38,6 +33,10 @@ void AnimationNodeStateMachineEditor::edit(AnimationNodeStateMachine *p_state_ma
|
|||
|
||||
void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
|
||||
if (playback.is_null())
|
||||
return;
|
||||
|
||||
Ref<InputEventKey> k = p_event;
|
||||
if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && !k->is_echo()) {
|
||||
if (selected_node != StringName() || selected_transition_to != StringName() || selected_transition_from != StringName()) {
|
||||
|
@ -59,7 +58,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
|
||||
menu->add_submenu_item(TTR("Add Animation"), "animations");
|
||||
|
||||
AnimationTree *gp = state_machine->get_tree();
|
||||
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()));
|
||||
|
@ -79,9 +78,17 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
if (name == "Animation")
|
||||
continue; // nope
|
||||
int idx = menu->get_item_count();
|
||||
menu->add_item(vformat("Add %s", name));
|
||||
menu->add_item(vformat("Add %s", name), idx);
|
||||
menu->set_item_metadata(idx, E->get());
|
||||
}
|
||||
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("Load.."), MENU_LOAD_FILE);
|
||||
|
||||
menu->set_global_position(state_machine_draw->get_global_transform().xform(mb->get_position()));
|
||||
menu->popup();
|
||||
|
@ -98,18 +105,12 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order
|
||||
|
||||
if (node_rects[i].play.has_point(mb->get_position())) { //edit name
|
||||
if (play_mode->get_selected() == 1 || !state_machine->is_playing()) {
|
||||
if (play_mode->get_selected() == 1 || !playback->is_playing()) {
|
||||
//start
|
||||
state_machine->start(node_rects[i].node_name);
|
||||
playback->start(node_rects[i].node_name);
|
||||
} else {
|
||||
//travel
|
||||
if (!state_machine->travel(node_rects[i].node_name)) {
|
||||
|
||||
state_machine->start(node_rects[i].node_name);
|
||||
//removing this due to usability..
|
||||
//error_time = 5;
|
||||
//error_text = vformat(TTR("No path found from '%s' to '%s'."), state_machine->get_current_node(), node_rects[i].node_name);
|
||||
}
|
||||
playback->travel(node_rects[i].node_name);
|
||||
}
|
||||
state_machine_draw->update();
|
||||
return;
|
||||
|
@ -196,8 +197,8 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
Ref<AnimationNode> an = state_machine->get_node(selected_node);
|
||||
updating = true;
|
||||
undo_redo->create_action("Move Node");
|
||||
undo_redo->add_do_method(an.ptr(), "set_position", an->get_position() + drag_ofs / EDSCALE);
|
||||
undo_redo->add_undo_method(an.ptr(), "set_position", an->get_position());
|
||||
undo_redo->add_do_method(state_machine.ptr(), "set_node_position", selected_node, state_machine->get_node_position(selected_node) + drag_ofs / EDSCALE);
|
||||
undo_redo->add_undo_method(state_machine.ptr(), "set_node_position", selected_node, state_machine->get_node_position(selected_node));
|
||||
undo_redo->add_do_method(this, "_update_graph");
|
||||
undo_redo->add_undo_method(this, "_update_graph");
|
||||
undo_redo->commit_action();
|
||||
|
@ -293,7 +294,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
snap_y = StringName();
|
||||
{
|
||||
//snap
|
||||
Vector2 cpos = state_machine->get_node(selected_node)->get_position() + drag_ofs / EDSCALE;
|
||||
Vector2 cpos = state_machine->get_node_position(selected_node) + drag_ofs / EDSCALE;
|
||||
List<StringName> nodes;
|
||||
state_machine->get_node_list(&nodes);
|
||||
|
||||
|
@ -303,7 +304,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
for (List<StringName>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
if (E->get() == selected_node)
|
||||
continue;
|
||||
Vector2 npos = state_machine->get_node(E->get())->get_position();
|
||||
Vector2 npos = state_machine->get_node_position(E->get());
|
||||
|
||||
float d_x = ABS(npos.x - cpos.x);
|
||||
if (d_x < MIN(5, best_d_x)) {
|
||||
|
@ -372,19 +373,58 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
}
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditor::_file_opened(const String &p_file) {
|
||||
|
||||
file_loaded = ResourceLoader::load(p_file);
|
||||
if (file_loaded.is_valid()) {
|
||||
_add_menu_type(MENU_LOAD_FILE_CONFIRM);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditor::_add_menu_type(int p_index) {
|
||||
|
||||
String type = menu->get_item_metadata(p_index);
|
||||
String base_name;
|
||||
Ref<AnimationRootNode> node;
|
||||
|
||||
Object *obj = ClassDB::instance(type);
|
||||
ERR_FAIL_COND(!obj);
|
||||
AnimationNode *an = Object::cast_to<AnimationNode>(obj);
|
||||
ERR_FAIL_COND(!an);
|
||||
if (p_index == MENU_LOAD_FILE) {
|
||||
|
||||
Ref<AnimationNode> node(an);
|
||||
node->set_position(add_node_pos);
|
||||
open_file->clear_filters();
|
||||
List<String> filters;
|
||||
ResourceLoader::get_recognized_extensions_for_type("AnimationRootNode", &filters);
|
||||
for (List<String>::Element *E = filters.front(); E; E = E->next()) {
|
||||
open_file->add_filter("*." + E->get());
|
||||
}
|
||||
open_file->popup_centered_ratio();
|
||||
return;
|
||||
} else if (p_index == MENU_LOAD_FILE_CONFIRM) {
|
||||
node = file_loaded;
|
||||
file_loaded.unref();
|
||||
} else if (p_index == MENU_PASTE) {
|
||||
|
||||
node = EditorSettings::get_singleton()->get_resource_clipboard();
|
||||
|
||||
} else {
|
||||
String type = menu->get_item_metadata(p_index);
|
||||
|
||||
Object *obj = ClassDB::instance(type);
|
||||
ERR_FAIL_COND(!obj);
|
||||
AnimationNode *an = Object::cast_to<AnimationNode>(obj);
|
||||
ERR_FAIL_COND(!an);
|
||||
|
||||
node = Ref<AnimationNode>(an);
|
||||
base_name = type.replace_first("AnimationNode", "");
|
||||
}
|
||||
|
||||
if (!node.is_valid()) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("This type of node can't be used. Only root nodes are allowed."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (base_name == String()) {
|
||||
|
||||
base_name = node->get_class().replace_first("AnimationNode", "");
|
||||
}
|
||||
|
||||
String base_name = type.replace_first("AnimationNode", "");
|
||||
int base = 1;
|
||||
String name = base_name;
|
||||
while (state_machine->has_node(name)) {
|
||||
|
@ -394,7 +434,7 @@ void AnimationNodeStateMachineEditor::_add_menu_type(int p_index) {
|
|||
|
||||
updating = true;
|
||||
undo_redo->create_action("Add Node");
|
||||
undo_redo->add_do_method(state_machine.ptr(), "add_node", name, node);
|
||||
undo_redo->add_do_method(state_machine.ptr(), "add_node", name, node, add_node_pos);
|
||||
undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name);
|
||||
undo_redo->add_do_method(this, "_update_graph");
|
||||
undo_redo->add_undo_method(this, "_update_graph");
|
||||
|
@ -419,11 +459,9 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) {
|
|||
name = base_name + " " + itos(base);
|
||||
}
|
||||
|
||||
anim->set_position(add_node_pos);
|
||||
|
||||
updating = true;
|
||||
undo_redo->create_action("Add Node");
|
||||
undo_redo->add_do_method(state_machine.ptr(), "add_node", name, anim);
|
||||
undo_redo->add_do_method(state_machine.ptr(), "add_node", name, anim, add_node_pos);
|
||||
undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name);
|
||||
undo_redo->add_do_method(this, "_update_graph");
|
||||
undo_redo->add_undo_method(this, "_update_graph");
|
||||
|
@ -502,6 +540,8 @@ void AnimationNodeStateMachineEditor::_clip_dst_line_to_rect(Vector2 &r_from, Ve
|
|||
|
||||
void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
||||
|
||||
Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
|
||||
|
||||
Ref<StyleBox> style = get_stylebox("frame", "GraphNode");
|
||||
Ref<StyleBox> style_selected = get_stylebox("selectedframe", "GraphNode");
|
||||
|
||||
|
@ -515,10 +555,17 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
|||
linecolor.a *= 0.3;
|
||||
Ref<StyleBox> playing_overlay = get_stylebox("position", "GraphNode");
|
||||
|
||||
bool playing = state_machine->is_playing();
|
||||
StringName current = state_machine->get_current_node();
|
||||
StringName blend_from = state_machine->get_blend_from_node();
|
||||
Vector<StringName> travel_path = state_machine->get_travel_path();
|
||||
bool playing = false;
|
||||
StringName current;
|
||||
StringName blend_from;
|
||||
Vector<StringName> travel_path;
|
||||
|
||||
if (playback.is_valid()) {
|
||||
playing = playback->is_playing();
|
||||
current = playback->get_current_node();
|
||||
blend_from = playback->get_blend_from_node();
|
||||
travel_path = playback->get_travel_path();
|
||||
}
|
||||
|
||||
if (state_machine_draw->has_focus()) {
|
||||
state_machine_draw->draw_rect(Rect2(Point2(), state_machine_draw->get_size()), accent, false);
|
||||
|
@ -534,13 +581,13 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
|||
//snap lines
|
||||
if (dragging_selected) {
|
||||
|
||||
Vector2 from = (state_machine->get_node(selected_node)->get_position() * EDSCALE) + drag_ofs - state_machine->get_graph_offset() * EDSCALE;
|
||||
Vector2 from = (state_machine->get_node_position(selected_node) * EDSCALE) + drag_ofs - state_machine->get_graph_offset() * EDSCALE;
|
||||
if (snap_x != StringName()) {
|
||||
Vector2 to = (state_machine->get_node(snap_x)->get_position() * EDSCALE) - state_machine->get_graph_offset() * EDSCALE;
|
||||
Vector2 to = (state_machine->get_node_position(snap_x) * EDSCALE) - state_machine->get_graph_offset() * EDSCALE;
|
||||
state_machine_draw->draw_line(from, to, linecolor, 2);
|
||||
}
|
||||
if (snap_y != StringName()) {
|
||||
Vector2 to = (state_machine->get_node(snap_y)->get_position() * EDSCALE) - state_machine->get_graph_offset() * EDSCALE;
|
||||
Vector2 to = (state_machine->get_node_position(snap_y) * EDSCALE) - state_machine->get_graph_offset() * EDSCALE;
|
||||
state_machine_draw->draw_line(from, to, linecolor, 2);
|
||||
}
|
||||
}
|
||||
|
@ -563,7 +610,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
|||
}
|
||||
|
||||
Vector2 offset;
|
||||
offset += anode->get_position() * EDSCALE;
|
||||
offset += state_machine->get_node_position(E->get()) * EDSCALE;
|
||||
if (selected_node == E->get() && dragging_selected) {
|
||||
offset += drag_ofs;
|
||||
}
|
||||
|
@ -588,10 +635,10 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
|||
|
||||
//draw conecting line for potential new transition
|
||||
if (connecting) {
|
||||
Vector2 from = (state_machine->get_node(connecting_from)->get_position() * EDSCALE) - state_machine->get_graph_offset() * EDSCALE;
|
||||
Vector2 from = (state_machine->get_node_position(connecting_from) * EDSCALE) - state_machine->get_graph_offset() * EDSCALE;
|
||||
Vector2 to;
|
||||
if (connecting_to_node != StringName()) {
|
||||
to = (state_machine->get_node(connecting_to_node)->get_position() * EDSCALE) - state_machine->get_graph_offset() * EDSCALE;
|
||||
to = (state_machine->get_node_position(connecting_to_node) * EDSCALE) - state_machine->get_graph_offset() * EDSCALE;
|
||||
} else {
|
||||
to = connecting_to;
|
||||
}
|
||||
|
@ -617,15 +664,17 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
|||
TransitionLine tl;
|
||||
tl.from_node = state_machine->get_transition_from(i);
|
||||
Vector2 ofs_from = (dragging_selected && tl.from_node == selected_node) ? drag_ofs : Vector2();
|
||||
tl.from = (state_machine->get_node(tl.from_node)->get_position() * EDSCALE) + ofs_from - state_machine->get_graph_offset() * EDSCALE;
|
||||
tl.from = (state_machine->get_node_position(tl.from_node) * EDSCALE) + ofs_from - state_machine->get_graph_offset() * EDSCALE;
|
||||
|
||||
tl.to_node = state_machine->get_transition_to(i);
|
||||
Vector2 ofs_to = (dragging_selected && tl.to_node == selected_node) ? drag_ofs : Vector2();
|
||||
tl.to = (state_machine->get_node(tl.to_node)->get_position() * EDSCALE) + ofs_to - state_machine->get_graph_offset() * EDSCALE;
|
||||
tl.to = (state_machine->get_node_position(tl.to_node) * EDSCALE) + ofs_to - state_machine->get_graph_offset() * EDSCALE;
|
||||
|
||||
Ref<AnimationNodeStateMachineTransition> tr = state_machine->get_transition(i);
|
||||
tl.disabled = tr->is_disabled();
|
||||
tl.auto_advance = tr->has_auto_advance();
|
||||
tl.advance_condition_name = tr->get_advance_condition_name();
|
||||
tl.advance_condition_state = false;
|
||||
tl.mode = tr->get_switch_mode();
|
||||
tl.width = tr_bidi_offset;
|
||||
|
||||
|
@ -665,7 +714,14 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
|||
}
|
||||
}
|
||||
}
|
||||
_connection_draw(tl.from, tl.to, tl.mode, !tl.disabled, selected, travel, tl.auto_advance);
|
||||
|
||||
bool auto_advance = tl.auto_advance;
|
||||
StringName fullpath = AnimationTreeEditor::get_singleton()->get_base_path() + String(tl.advance_condition_name);
|
||||
if (tl.advance_condition_name != StringName() && bool(AnimationTreeEditor::get_singleton()->get_tree()->get(fullpath))) {
|
||||
tl.advance_condition_state = true;
|
||||
auto_advance = true;
|
||||
}
|
||||
_connection_draw(tl.from, tl.to, tl.mode, !tl.disabled, selected, travel, auto_advance);
|
||||
|
||||
transition_lines.push_back(tl);
|
||||
}
|
||||
|
@ -675,7 +731,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
|||
|
||||
String name = node_rects[i].node_name;
|
||||
Ref<AnimationNode> anode = state_machine->get_node(name);
|
||||
bool needs_editor = EditorNode::get_singleton()->item_has_editor(anode.ptr());
|
||||
bool needs_editor = AnimationTreeEditor::get_singleton()->can_edit(anode);
|
||||
Ref<StyleBox> sb = name == selected_node ? style_selected : style;
|
||||
int strsize = font->get_string_size(name).width;
|
||||
|
||||
|
@ -757,12 +813,14 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
|
|||
|
||||
void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
|
||||
|
||||
if (!state_machine->is_playing())
|
||||
Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
|
||||
|
||||
if (!playback.is_valid() || !playback->is_playing())
|
||||
return;
|
||||
|
||||
int idx = -1;
|
||||
for (int i = 0; node_rects.size(); i++) {
|
||||
if (node_rects[i].node_name == state_machine->get_current_node()) {
|
||||
if (node_rects[i].node_name == playback->get_current_node()) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
|
@ -785,9 +843,9 @@ void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
|
|||
}
|
||||
to.y = from.y;
|
||||
|
||||
float len = MAX(0.0001, state_machine->get_current_length());
|
||||
float len = MAX(0.0001, playback->get_current_length());
|
||||
|
||||
float pos = CLAMP(state_machine->get_current_play_pos(), 0, len);
|
||||
float pos = CLAMP(playback->get_current_play_pos(), 0, len);
|
||||
float c = pos / len;
|
||||
Color fg = get_color("font_color", "Label");
|
||||
Color bg = fg;
|
||||
|
@ -807,12 +865,6 @@ void AnimationNodeStateMachineEditor::_update_graph() {
|
|||
|
||||
updating = true;
|
||||
|
||||
if (state_machine->get_parent().is_valid()) {
|
||||
goto_parent_hbox->show();
|
||||
} else {
|
||||
goto_parent_hbox->hide();
|
||||
}
|
||||
|
||||
state_machine_draw->update();
|
||||
|
||||
updating = false;
|
||||
|
@ -824,7 +876,6 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
|
|||
error_panel->add_style_override("panel", get_stylebox("bg", "Tree"));
|
||||
error_label->add_color_override("font_color", get_color("error_color", "Editor"));
|
||||
panel->add_style_override("panel", get_stylebox("bg", "Tree"));
|
||||
goto_parent->set_icon(get_icon("MoveUp", "EditorIcons"));
|
||||
|
||||
tool_select->set_icon(get_icon("ToolSelect", "EditorIcons"));
|
||||
tool_create->set_icon(get_icon("ToolAddNode", "EditorIcons"));
|
||||
|
@ -856,19 +907,21 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
|
|||
|
||||
String error;
|
||||
|
||||
Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
|
||||
|
||||
if (error_time > 0) {
|
||||
error = error_text;
|
||||
error_time -= get_process_delta_time();
|
||||
} else if (!state_machine->get_tree()) {
|
||||
error = TTR("StateMachine does not belong to an AnimationTree node.");
|
||||
} else if (!state_machine->get_tree()->is_active()) {
|
||||
} else if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
|
||||
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
|
||||
} else if (state_machine->get_tree()->is_state_invalid()) {
|
||||
error = state_machine->get_tree()->get_invalid_state_reason();
|
||||
} else if (state_machine->get_parent().is_valid() && state_machine->get_parent()->is_class("AnimationNodeStateMachine")) {
|
||||
} else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
|
||||
error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
|
||||
/*} else if (state_machine->get_parent().is_valid() && state_machine->get_parent()->is_class("AnimationNodeStateMachine")) {
|
||||
if (state_machine->get_start_node() == StringName() || state_machine->get_end_node() == StringName()) {
|
||||
error = TTR("Start and end nodes are needed for a sub-transition.");
|
||||
}
|
||||
}*/
|
||||
} else if (playback.is_null()) {
|
||||
error = vformat(TTR("No playback resource set at path: %s."), AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
|
||||
}
|
||||
|
||||
if (error != error_label->get_text()) {
|
||||
|
@ -904,14 +957,38 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (transition_lines[i].advance_condition_name != state_machine->get_transition(tidx)->get_advance_condition_name()) {
|
||||
state_machine_draw->update();
|
||||
break;
|
||||
}
|
||||
|
||||
if (transition_lines[i].mode != state_machine->get_transition(tidx)->get_switch_mode()) {
|
||||
state_machine_draw->update();
|
||||
break;
|
||||
}
|
||||
|
||||
bool acstate = transition_lines[i].advance_condition_name != StringName() && bool(AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + String(transition_lines[i].advance_condition_name)));
|
||||
|
||||
if (transition_lines[i].advance_condition_state != acstate) {
|
||||
state_machine_draw->update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool same_travel_path = true;
|
||||
Vector<StringName> tp = state_machine->get_travel_path();
|
||||
Vector<StringName> tp;
|
||||
bool is_playing = false;
|
||||
StringName current_node;
|
||||
StringName blend_from_node;
|
||||
float play_pos = 0;
|
||||
|
||||
if (playback.is_valid()) {
|
||||
tp = playback->get_travel_path();
|
||||
is_playing = playback->is_playing();
|
||||
current_node = playback->get_current_node();
|
||||
blend_from_node = playback->get_blend_from_node();
|
||||
play_pos = playback->get_current_play_pos();
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
|
@ -928,37 +1005,32 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
|
|||
}
|
||||
|
||||
//update if travel state changed
|
||||
if (!same_travel_path || last_active != state_machine->is_playing() || last_current_node != state_machine->get_current_node() || last_blend_from_node != state_machine->get_blend_from_node()) {
|
||||
if (!same_travel_path || last_active != is_playing || last_current_node != current_node || last_blend_from_node != blend_from_node) {
|
||||
|
||||
state_machine_draw->update();
|
||||
last_travel_path = tp;
|
||||
last_current_node = state_machine->get_current_node();
|
||||
last_active = state_machine->is_playing();
|
||||
last_blend_from_node = state_machine->get_blend_from_node();
|
||||
last_current_node = current_node;
|
||||
last_active = is_playing;
|
||||
last_blend_from_node = blend_from_node;
|
||||
state_machine_play_pos->update();
|
||||
}
|
||||
|
||||
if (last_play_pos != state_machine->get_current_play_pos()) {
|
||||
if (last_play_pos != play_pos) {
|
||||
|
||||
last_play_pos = state_machine->get_current_play_pos();
|
||||
last_play_pos = play_pos;
|
||||
state_machine_play_pos->update();
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
over_node = StringName();
|
||||
set_process(is_visible_in_tree());
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditor::_open_editor(const String &p_name) {
|
||||
Ref<AnimationNode> an = state_machine->get_node(p_name);
|
||||
ERR_FAIL_COND(!an.is_valid());
|
||||
EditorNode::get_singleton()->edit_item(an.ptr());
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditor::_goto_parent() {
|
||||
|
||||
EditorNode::get_singleton()->edit_item(state_machine->get_parent().ptr());
|
||||
AnimationTreeEditor::get_singleton()->enter_editor(p_name);
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditor::_removed_from_graph() {
|
||||
|
@ -1114,7 +1186,6 @@ void AnimationNodeStateMachineEditor::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method("_name_edited", &AnimationNodeStateMachineEditor::_name_edited);
|
||||
|
||||
ClassDB::bind_method("_goto_parent", &AnimationNodeStateMachineEditor::_goto_parent);
|
||||
ClassDB::bind_method("_removed_from_graph", &AnimationNodeStateMachineEditor::_removed_from_graph);
|
||||
|
||||
ClassDB::bind_method("_open_editor", &AnimationNodeStateMachineEditor::_open_editor);
|
||||
|
@ -1124,6 +1195,7 @@ void AnimationNodeStateMachineEditor::_bind_methods() {
|
|||
ClassDB::bind_method("_autoplay_selected", &AnimationNodeStateMachineEditor::_autoplay_selected);
|
||||
ClassDB::bind_method("_end_selected", &AnimationNodeStateMachineEditor::_end_selected);
|
||||
ClassDB::bind_method("_update_mode", &AnimationNodeStateMachineEditor::_update_mode);
|
||||
ClassDB::bind_method("_file_opened", &AnimationNodeStateMachineEditor::_file_opened);
|
||||
}
|
||||
|
||||
AnimationNodeStateMachineEditor *AnimationNodeStateMachineEditor::singleton = NULL;
|
||||
|
@ -1136,13 +1208,6 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
|
|||
HBoxContainer *top_hb = memnew(HBoxContainer);
|
||||
add_child(top_hb);
|
||||
|
||||
goto_parent_hbox = memnew(HBoxContainer);
|
||||
goto_parent = memnew(ToolButton);
|
||||
goto_parent->connect("pressed", this, "_goto_parent", varray(), CONNECT_DEFERRED);
|
||||
goto_parent_hbox->add_child(goto_parent);
|
||||
goto_parent_hbox->add_child(memnew(VSeparator));
|
||||
top_hb->add_child(goto_parent_hbox);
|
||||
|
||||
Ref<ButtonGroup> bg;
|
||||
bg.instance();
|
||||
|
||||
|
@ -1248,7 +1313,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
|
|||
|
||||
menu = memnew(PopupMenu);
|
||||
add_child(menu);
|
||||
menu->connect("index_pressed", this, "_add_menu_type");
|
||||
menu->connect("id_pressed", this, "_add_menu_type");
|
||||
|
||||
animations_menu = memnew(PopupMenu);
|
||||
menu->add_child(animations_menu);
|
||||
|
@ -1261,6 +1326,13 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
|
|||
name_edit->connect("text_entered", this, "_name_edited");
|
||||
name_edit->set_as_toplevel(true);
|
||||
|
||||
open_file = memnew(EditorFileDialog);
|
||||
add_child(open_file);
|
||||
open_file->set_title(TTR("Open Animation Node"));
|
||||
open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
||||
open_file->connect("file_selected", this, "_file_opened");
|
||||
undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
over_text = false;
|
||||
|
||||
over_node_what = -1;
|
||||
|
@ -1271,43 +1343,3 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
|
|||
|
||||
error_time = 0;
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditorPlugin::edit(Object *p_object) {
|
||||
|
||||
anim_tree_editor->edit(Object::cast_to<AnimationNodeStateMachine>(p_object));
|
||||
}
|
||||
|
||||
bool AnimationNodeStateMachineEditorPlugin::handles(Object *p_object) const {
|
||||
|
||||
return p_object->is_class("AnimationNodeStateMachine");
|
||||
}
|
||||
|
||||
void AnimationNodeStateMachineEditorPlugin::make_visible(bool p_visible) {
|
||||
|
||||
if (p_visible) {
|
||||
//editor->hide_animation_player_editors();
|
||||
//editor->animation_panel_make_visible(true);
|
||||
button->show();
|
||||
editor->make_bottom_panel_item_visible(anim_tree_editor);
|
||||
anim_tree_editor->set_process(true);
|
||||
} else {
|
||||
|
||||
if (anim_tree_editor->is_visible_in_tree())
|
||||
editor->hide_bottom_panel();
|
||||
button->hide();
|
||||
anim_tree_editor->set_process(false);
|
||||
}
|
||||
}
|
||||
|
||||
AnimationNodeStateMachineEditorPlugin::AnimationNodeStateMachineEditorPlugin(EditorNode *p_node) {
|
||||
|
||||
editor = p_node;
|
||||
anim_tree_editor = memnew(AnimationNodeStateMachineEditor);
|
||||
anim_tree_editor->set_custom_minimum_size(Size2(0, 300));
|
||||
|
||||
button = editor->add_bottom_panel_item(TTR("StateMachine"), anim_tree_editor);
|
||||
button->hide();
|
||||
}
|
||||
|
||||
AnimationNodeStateMachineEditorPlugin::~AnimationNodeStateMachineEditorPlugin() {
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_plugin.h"
|
||||
#include "editor/plugins/animation_tree_editor_plugin.h"
|
||||
#include "editor/property_editor.h"
|
||||
#include "scene/animation/animation_node_state_machine.h"
|
||||
#include "scene/gui/button.h"
|
||||
|
@ -10,9 +11,9 @@
|
|||
#include "scene/gui/popup.h"
|
||||
#include "scene/gui/tree.h"
|
||||
|
||||
class AnimationNodeStateMachineEditor : public VBoxContainer {
|
||||
class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
|
||||
|
||||
GDCLASS(AnimationNodeStateMachineEditor, VBoxContainer);
|
||||
GDCLASS(AnimationNodeStateMachineEditor, AnimationTreeNodeEditorPlugin);
|
||||
|
||||
Ref<AnimationNodeStateMachine> state_machine;
|
||||
|
||||
|
@ -29,9 +30,6 @@ class AnimationNodeStateMachineEditor : public VBoxContainer {
|
|||
OptionButton *transition_mode;
|
||||
OptionButton *play_mode;
|
||||
|
||||
HBoxContainer *goto_parent_hbox;
|
||||
ToolButton *goto_parent;
|
||||
|
||||
PanelContainer *panel;
|
||||
|
||||
StringName selected_node;
|
||||
|
@ -79,8 +77,6 @@ class AnimationNodeStateMachineEditor : public VBoxContainer {
|
|||
void _add_menu_type(int p_index);
|
||||
void _add_animation_type(int p_index);
|
||||
|
||||
void _goto_parent();
|
||||
|
||||
void _removed_from_graph();
|
||||
|
||||
struct NodeRect {
|
||||
|
@ -99,6 +95,8 @@ class AnimationNodeStateMachineEditor : public VBoxContainer {
|
|||
Vector2 from;
|
||||
Vector2 to;
|
||||
AnimationNodeStateMachineTransition::SwitchMode mode;
|
||||
StringName advance_condition_name;
|
||||
bool advance_condition_state;
|
||||
bool disabled;
|
||||
bool auto_advance;
|
||||
float width;
|
||||
|
@ -135,33 +133,25 @@ class AnimationNodeStateMachineEditor : public VBoxContainer {
|
|||
float error_time;
|
||||
String error_text;
|
||||
|
||||
EditorFileDialog *open_file;
|
||||
Ref<AnimationNode> file_loaded;
|
||||
void _file_opened(const String &p_file);
|
||||
|
||||
enum {
|
||||
MENU_LOAD_FILE = 1000,
|
||||
MENU_PASTE = 1001,
|
||||
MENU_LOAD_FILE_CONFIRM = 1002
|
||||
};
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static AnimationNodeStateMachineEditor *get_singleton() { return singleton; }
|
||||
void edit(AnimationNodeStateMachine *p_state_machine);
|
||||
virtual bool can_edit(const Ref<AnimationNode> &p_node);
|
||||
virtual void edit(const Ref<AnimationNode> &p_node);
|
||||
AnimationNodeStateMachineEditor();
|
||||
};
|
||||
|
||||
class AnimationNodeStateMachineEditorPlugin : public EditorPlugin {
|
||||
|
||||
GDCLASS(AnimationNodeStateMachineEditorPlugin, EditorPlugin);
|
||||
|
||||
AnimationNodeStateMachineEditor *anim_tree_editor;
|
||||
EditorNode *editor;
|
||||
Button *button;
|
||||
|
||||
public:
|
||||
virtual String get_name() const { return "StateMachine"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_object);
|
||||
virtual bool handles(Object *p_object) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
AnimationNodeStateMachineEditorPlugin(EditorNode *p_node);
|
||||
~AnimationNodeStateMachineEditorPlugin();
|
||||
};
|
||||
|
||||
#endif // ANIMATION_STATE_MACHINE_EDITOR_H
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,167 +1,65 @@
|
|||
/*************************************************************************/
|
||||
/* animation_tree_editor_plugin.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 ANIMATION_TREE_EDITOR_PLUGIN_H
|
||||
#define ANIMATION_TREE_EDITOR_PLUGIN_H
|
||||
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_plugin.h"
|
||||
#include "editor/property_editor.h"
|
||||
#include "scene/animation/animation_tree_player.h"
|
||||
#include "scene/animation/animation_tree.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/graph_edit.h"
|
||||
#include "scene/gui/popup.h"
|
||||
#include "scene/gui/tree.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
class AnimationTreeEditor : public Control {
|
||||
class AnimationTreeNodeEditorPlugin : public VBoxContainer {
|
||||
GDCLASS(AnimationTreeNodeEditorPlugin, VBoxContainer)
|
||||
public:
|
||||
virtual bool can_edit(const Ref<AnimationNode> &p_node) = 0;
|
||||
virtual void edit(const Ref<AnimationNode> &p_node) = 0;
|
||||
};
|
||||
|
||||
GDCLASS(AnimationTreeEditor, Control);
|
||||
class AnimationTreeEditor : public VBoxContainer {
|
||||
|
||||
static const char *_node_type_names[];
|
||||
GDCLASS(AnimationTreeEditor, VBoxContainer);
|
||||
|
||||
enum ClickType {
|
||||
CLICK_NONE,
|
||||
CLICK_NAME,
|
||||
CLICK_NODE,
|
||||
CLICK_INPUT_SLOT,
|
||||
CLICK_OUTPUT_SLOT,
|
||||
CLICK_PARAMETER
|
||||
};
|
||||
ScrollContainer *path_edit;
|
||||
HBoxContainer *path_hb;
|
||||
|
||||
enum {
|
||||
AnimationTree *tree;
|
||||
PanelContainer *editor_base;
|
||||
|
||||
MENU_GRAPH_CLEAR = 100,
|
||||
MENU_IMPORT_ANIMATIONS = 101,
|
||||
NODE_DISCONNECT,
|
||||
NODE_RENAME,
|
||||
NODE_ERASE,
|
||||
NODE_ADD_INPUT,
|
||||
NODE_DELETE_INPUT,
|
||||
NODE_SET_AUTOADVANCE,
|
||||
NODE_CLEAR_AUTOADVANCE
|
||||
};
|
||||
Vector<String> button_path;
|
||||
Vector<String> edited_path;
|
||||
Vector<AnimationTreeNodeEditorPlugin *> editors;
|
||||
|
||||
bool renaming_edit;
|
||||
StringName edited_node;
|
||||
bool updating_edit;
|
||||
Popup *edit_dialog;
|
||||
HSlider *edit_scroll[2];
|
||||
LineEdit *edit_line[4];
|
||||
OptionButton *edit_option;
|
||||
Label *edit_label[4];
|
||||
Button *edit_button;
|
||||
Button *filter_button;
|
||||
CheckButton *edit_check;
|
||||
EditorFileDialog *file_dialog;
|
||||
int file_op;
|
||||
void _update_path();
|
||||
void _about_to_show_root();
|
||||
ObjectID current_root;
|
||||
|
||||
void _popup_edit_dialog();
|
||||
void _path_button_pressed(int p_path);
|
||||
|
||||
void _setup_edit_dialog(const StringName &p_node);
|
||||
PopupMenu *master_anim_popup;
|
||||
PopupMenu *node_popup;
|
||||
PopupMenu *add_popup;
|
||||
HScrollBar *h_scroll;
|
||||
VScrollBar *v_scroll;
|
||||
MenuButton *add_menu;
|
||||
|
||||
CustomPropertyEditor *property_editor;
|
||||
|
||||
AnimationTreePlayer *anim_tree;
|
||||
List<StringName> order;
|
||||
Set<StringName> active_nodes;
|
||||
|
||||
int last_x, last_y;
|
||||
|
||||
Point2 offset;
|
||||
ClickType click_type;
|
||||
Point2 click_pos;
|
||||
StringName click_node;
|
||||
int click_slot;
|
||||
Point2 click_motion;
|
||||
ClickType rclick_type;
|
||||
StringName rclick_node;
|
||||
int rclick_slot;
|
||||
|
||||
Button *play_button;
|
||||
|
||||
Size2 _get_maximum_size();
|
||||
Size2 get_node_size(const StringName &p_node) const;
|
||||
void _draw_node(const StringName &p_node);
|
||||
|
||||
AcceptDialog *filter_dialog;
|
||||
Tree *filter;
|
||||
|
||||
void _draw_cos_line(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color);
|
||||
void _update_scrollbars();
|
||||
void _scroll_moved(float);
|
||||
void _play_toggled();
|
||||
/*
|
||||
void _node_param_changed();
|
||||
void _node_add_callback();
|
||||
void _node_add(VisualServer::AnimationTreeNodeType p_type);
|
||||
void _node_edit_property(const StringName& p_node);
|
||||
*/
|
||||
|
||||
void _master_anim_menu_item(int p_item);
|
||||
void _node_menu_item(int p_item);
|
||||
void _add_menu_item(int p_item);
|
||||
|
||||
void _filter_edited();
|
||||
void _find_paths_for_filter(const StringName &p_node, Set<String> &paths);
|
||||
void _edit_filters();
|
||||
|
||||
void _edit_oneshot_start();
|
||||
void _edit_dialog_animation_changed();
|
||||
void _edit_dialog_edit_animation();
|
||||
void _edit_dialog_changeds(String);
|
||||
void _edit_dialog_changede(String);
|
||||
void _edit_dialog_changedf(float);
|
||||
void _edit_dialog_changed();
|
||||
void _dialog_changed() const;
|
||||
ClickType _locate_click(const Point2 &p_click, StringName *p_node_id, int *p_slot_index) const;
|
||||
Point2 _get_slot_pos(const StringName &p_node_id, bool p_input, int p_slot);
|
||||
|
||||
StringName _add_node(int p_item);
|
||||
void _file_dialog_selected(String p_path);
|
||||
static Vector<String> get_animation_list();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
void _gui_input(Ref<InputEvent> p_event);
|
||||
static void _bind_methods();
|
||||
|
||||
static AnimationTreeEditor *singleton;
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const;
|
||||
void edit(AnimationTreePlayer *p_anim_tree);
|
||||
AnimationTree *get_tree() { return tree; }
|
||||
void add_plugin(AnimationTreeNodeEditorPlugin *p_editor);
|
||||
void remove_plugin(AnimationTreeNodeEditorPlugin *p_editor);
|
||||
|
||||
String get_base_path();
|
||||
|
||||
bool can_edit(const Ref<AnimationNode> &p_node) const;
|
||||
|
||||
void edit_path(const Vector<String> &p_path);
|
||||
Vector<String> get_edited_path() const;
|
||||
|
||||
void enter_editor(const String &p_path = "");
|
||||
static AnimationTreeEditor *get_singleton() { return singleton; }
|
||||
void edit(AnimationTree *p_tree);
|
||||
AnimationTreeEditor();
|
||||
};
|
||||
|
||||
|
@ -174,7 +72,7 @@ class AnimationTreeEditorPlugin : public EditorPlugin {
|
|||
Button *button;
|
||||
|
||||
public:
|
||||
virtual String get_name() const { return "AnimTree"; }
|
||||
virtual String get_name() const { return "AnimationTree"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_object);
|
||||
virtual bool handles(Object *p_object) const;
|
||||
|
|
1446
editor/plugins/animation_tree_player_editor_plugin.cpp
Normal file
1446
editor/plugins/animation_tree_player_editor_plugin.cpp
Normal file
File diff suppressed because it is too large
Load diff
187
editor/plugins/animation_tree_player_editor_plugin.h
Normal file
187
editor/plugins/animation_tree_player_editor_plugin.h
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*************************************************************************/
|
||||
/* animation_tree_editor_plugin.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 ANIMATION_TREE_PLAYER_EDITOR_PLUGIN_H
|
||||
#define ANIMATION_TREE_PLAYER_EDITOR_PLUGIN_H
|
||||
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_plugin.h"
|
||||
#include "editor/property_editor.h"
|
||||
#include "scene/animation/animation_tree_player.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/popup.h"
|
||||
#include "scene/gui/tree.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
class AnimationTreePlayerEditor : public Control {
|
||||
|
||||
GDCLASS(AnimationTreePlayerEditor, Control);
|
||||
|
||||
static const char *_node_type_names[];
|
||||
|
||||
enum ClickType {
|
||||
CLICK_NONE,
|
||||
CLICK_NAME,
|
||||
CLICK_NODE,
|
||||
CLICK_INPUT_SLOT,
|
||||
CLICK_OUTPUT_SLOT,
|
||||
CLICK_PARAMETER
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
MENU_GRAPH_CLEAR = 100,
|
||||
MENU_IMPORT_ANIMATIONS = 101,
|
||||
NODE_DISCONNECT,
|
||||
NODE_RENAME,
|
||||
NODE_ERASE,
|
||||
NODE_ADD_INPUT,
|
||||
NODE_DELETE_INPUT,
|
||||
NODE_SET_AUTOADVANCE,
|
||||
NODE_CLEAR_AUTOADVANCE
|
||||
};
|
||||
|
||||
bool renaming_edit;
|
||||
StringName edited_node;
|
||||
bool updating_edit;
|
||||
Popup *edit_dialog;
|
||||
HSlider *edit_scroll[2];
|
||||
LineEdit *edit_line[4];
|
||||
OptionButton *edit_option;
|
||||
Label *edit_label[4];
|
||||
Button *edit_button;
|
||||
Button *filter_button;
|
||||
CheckButton *edit_check;
|
||||
EditorFileDialog *file_dialog;
|
||||
int file_op;
|
||||
|
||||
void _popup_edit_dialog();
|
||||
|
||||
void _setup_edit_dialog(const StringName &p_node);
|
||||
PopupMenu *master_anim_popup;
|
||||
PopupMenu *node_popup;
|
||||
PopupMenu *add_popup;
|
||||
HScrollBar *h_scroll;
|
||||
VScrollBar *v_scroll;
|
||||
MenuButton *add_menu;
|
||||
|
||||
CustomPropertyEditor *property_editor;
|
||||
|
||||
AnimationTreePlayer *anim_tree;
|
||||
List<StringName> order;
|
||||
Set<StringName> active_nodes;
|
||||
|
||||
int last_x, last_y;
|
||||
|
||||
Point2 offset;
|
||||
ClickType click_type;
|
||||
Point2 click_pos;
|
||||
StringName click_node;
|
||||
int click_slot;
|
||||
Point2 click_motion;
|
||||
ClickType rclick_type;
|
||||
StringName rclick_node;
|
||||
int rclick_slot;
|
||||
|
||||
Button *play_button;
|
||||
|
||||
Size2 _get_maximum_size();
|
||||
Size2 get_node_size(const StringName &p_node) const;
|
||||
void _draw_node(const StringName &p_node);
|
||||
|
||||
AcceptDialog *filter_dialog;
|
||||
Tree *filter;
|
||||
|
||||
void _draw_cos_line(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color);
|
||||
void _update_scrollbars();
|
||||
void _scroll_moved(float);
|
||||
void _play_toggled();
|
||||
/*
|
||||
void _node_param_changed();
|
||||
void _node_add_callback();
|
||||
void _node_add(VisualServer::AnimationTreeNodeType p_type);
|
||||
void _node_edit_property(const StringName& p_node);
|
||||
*/
|
||||
|
||||
void _master_anim_menu_item(int p_item);
|
||||
void _node_menu_item(int p_item);
|
||||
void _add_menu_item(int p_item);
|
||||
|
||||
void _filter_edited();
|
||||
void _find_paths_for_filter(const StringName &p_node, Set<String> &paths);
|
||||
void _edit_filters();
|
||||
|
||||
void _edit_oneshot_start();
|
||||
void _edit_dialog_animation_changed();
|
||||
void _edit_dialog_edit_animation();
|
||||
void _edit_dialog_changeds(String);
|
||||
void _edit_dialog_changede(String);
|
||||
void _edit_dialog_changedf(float);
|
||||
void _edit_dialog_changed();
|
||||
void _dialog_changed() const;
|
||||
ClickType _locate_click(const Point2 &p_click, StringName *p_node_id, int *p_slot_index) const;
|
||||
Point2 _get_slot_pos(const StringName &p_node_id, bool p_input, int p_slot);
|
||||
|
||||
StringName _add_node(int p_item);
|
||||
void _file_dialog_selected(String p_path);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
void _gui_input(Ref<InputEvent> p_event);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const;
|
||||
void edit(AnimationTreePlayer *p_anim_tree);
|
||||
AnimationTreePlayerEditor();
|
||||
};
|
||||
|
||||
class AnimationTreePlayerEditorPlugin : public EditorPlugin {
|
||||
|
||||
GDCLASS(AnimationTreePlayerEditorPlugin, EditorPlugin);
|
||||
|
||||
AnimationTreePlayerEditor *anim_tree_editor;
|
||||
EditorNode *editor;
|
||||
Button *button;
|
||||
|
||||
public:
|
||||
virtual String get_name() const { return "AnimTree"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_object);
|
||||
virtual bool handles(Object *p_object) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
AnimationTreePlayerEditorPlugin(EditorNode *p_node);
|
||||
~AnimationTreePlayerEditorPlugin();
|
||||
};
|
||||
|
||||
#endif // ANIMATION_TREE_EDITOR_PLUGIN_H
|
|
@ -1394,13 +1394,9 @@ void KinematicBody::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody::get_slide_count);
|
||||
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody::_get_slide_collision);
|
||||
|
||||
ADD_GROUP("Axis Lock", "axis_lock_");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_X);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Y);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_x", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
#include "animation_blend_space_1d.h"
|
||||
|
||||
void AnimationNodeBlendSpace1D::set_tree(AnimationTree *p_player) {
|
||||
|
||||
AnimationRootNode::set_tree(p_player);
|
||||
void AnimationNodeBlendSpace1D::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::REAL,blend_position));
|
||||
}
|
||||
Variant AnimationNodeBlendSpace1D::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < blend_points_used; i++) {
|
||||
blend_points[i].node->set_tree(p_player);
|
||||
}
|
||||
Ref<AnimationNode> AnimationNodeBlendSpace1D::get_child_by_name(const StringName &p_name) {
|
||||
return get_blend_point_node(p_name.operator String().to_int());
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1D::_validate_property(PropertyInfo &property) const {
|
||||
|
@ -20,6 +23,10 @@ void AnimationNodeBlendSpace1D::_validate_property(PropertyInfo &property) const
|
|||
AnimationRootNode::_validate_property(property);
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1D::_tree_changed() {
|
||||
emit_signal("tree_changed");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("add_blend_point", "node", "pos", "at_index"), &AnimationNodeBlendSpace1D::add_blend_point, DEFVAL(-1));
|
||||
ClassDB::bind_method(D_METHOD("set_blend_point_position", "point", "pos"), &AnimationNodeBlendSpace1D::set_blend_point_position);
|
||||
|
@ -38,30 +45,37 @@ void AnimationNodeBlendSpace1D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &AnimationNodeBlendSpace1D::set_snap);
|
||||
ClassDB::bind_method(D_METHOD("get_snap"), &AnimationNodeBlendSpace1D::get_snap);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_blend_pos", "pos"), &AnimationNodeBlendSpace1D::set_blend_pos);
|
||||
ClassDB::bind_method(D_METHOD("get_blend_pos"), &AnimationNodeBlendSpace1D::get_blend_pos);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_value_label", "text"), &AnimationNodeBlendSpace1D::set_value_label);
|
||||
ClassDB::bind_method(D_METHOD("get_value_label"), &AnimationNodeBlendSpace1D::get_value_label);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_add_blend_point", "index", "node"), &AnimationNodeBlendSpace1D::_add_blend_point);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationNodeBlendSpace1D::_tree_changed);
|
||||
|
||||
for (int i = 0; i < MAX_BLEND_POINTS; i++) {
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "_add_blend_point", "get_blend_point_node", i);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_add_blend_point", "get_blend_point_node", i);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "blend_point_" + itos(i) + "/pos", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_blend_point_position", "get_blend_point_position", i);
|
||||
}
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "min_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_min_space", "get_min_space");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_max_space", "get_max_space");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_snap", "get_snap");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "blend_pos", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_blend_pos", "get_blend_pos");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_value_label", "get_value_label");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) {
|
||||
for(int i=0;i<blend_points_used;i++) {
|
||||
ChildNode cn;
|
||||
cn.name=itos(i);
|
||||
cn.node=blend_points[i].node;
|
||||
r_child_nodes->push_back(cn);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1D::add_blend_point(const Ref<AnimationRootNode> &p_node, float p_position, int p_at_index) {
|
||||
ERR_FAIL_COND(blend_points_used >= MAX_BLEND_POINTS);
|
||||
ERR_FAIL_COND(p_node.is_null());
|
||||
ERR_FAIL_COND(p_node->get_parent().is_valid());
|
||||
|
||||
ERR_FAIL_COND(p_at_index < -1 || p_at_index > blend_points_used);
|
||||
|
||||
if (p_at_index == -1 || p_at_index == blend_points_used) {
|
||||
|
@ -75,10 +89,12 @@ void AnimationNodeBlendSpace1D::add_blend_point(const Ref<AnimationRootNode> &p_
|
|||
blend_points[p_at_index].node = p_node;
|
||||
blend_points[p_at_index].position = p_position;
|
||||
|
||||
blend_points[p_at_index].node->set_parent(this);
|
||||
blend_points[p_at_index].node->set_tree(get_tree());
|
||||
blend_points[p_at_index].node->connect("tree_changed",this,"_tree_changed",varray(),CONNECT_REFERENCE_COUNTED);
|
||||
|
||||
blend_points_used++;
|
||||
emit_signal("tree_changed");
|
||||
|
||||
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1D::set_blend_point_position(int p_point, float p_position) {
|
||||
|
@ -92,13 +108,14 @@ void AnimationNodeBlendSpace1D::set_blend_point_node(int p_point, const Ref<Anim
|
|||
ERR_FAIL_COND(p_node.is_null());
|
||||
|
||||
if (blend_points[p_point].node.is_valid()) {
|
||||
blend_points[p_point].node->set_parent(NULL);
|
||||
blend_points[p_point].node->set_tree(NULL);
|
||||
blend_points[p_point].node->disconnect("tree_changed",this,"_tree_changed");
|
||||
}
|
||||
|
||||
blend_points[p_point].node = p_node;
|
||||
blend_points[p_point].node->set_parent(this);
|
||||
blend_points[p_point].node->set_tree(get_tree());
|
||||
blend_points[p_point].node->connect("tree_changed",this,"_tree_changed",varray(),CONNECT_REFERENCE_COUNTED);
|
||||
|
||||
emit_signal("tree_changed");
|
||||
|
||||
}
|
||||
|
||||
float AnimationNodeBlendSpace1D::get_blend_point_position(int p_point) const {
|
||||
|
@ -114,14 +131,16 @@ Ref<AnimationRootNode> AnimationNodeBlendSpace1D::get_blend_point_node(int p_poi
|
|||
void AnimationNodeBlendSpace1D::remove_blend_point(int p_point) {
|
||||
ERR_FAIL_INDEX(p_point, blend_points_used);
|
||||
|
||||
blend_points[p_point].node->set_parent(NULL);
|
||||
blend_points[p_point].node->set_tree(NULL);
|
||||
blend_points[p_point].node->disconnect("tree_changed",this,"_tree_changed");
|
||||
|
||||
for (int i = p_point; i < blend_points_used - 1; i++) {
|
||||
blend_points[i] = blend_points[i + 1];
|
||||
}
|
||||
|
||||
|
||||
blend_points_used--;
|
||||
emit_signal("tree_changed");
|
||||
|
||||
}
|
||||
|
||||
int AnimationNodeBlendSpace1D::get_blend_point_count() const {
|
||||
|
@ -161,13 +180,6 @@ float AnimationNodeBlendSpace1D::get_snap() const {
|
|||
return snap;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1D::set_blend_pos(float p_pos) {
|
||||
blend_pos = p_pos;
|
||||
}
|
||||
|
||||
float AnimationNodeBlendSpace1D::get_blend_pos() const {
|
||||
return blend_pos;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace1D::set_value_label(const String &p_label) {
|
||||
value_label = p_label;
|
||||
|
@ -191,11 +203,14 @@ float AnimationNodeBlendSpace1D::process(float p_time, bool p_seek) {
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
if (blend_points_used == 1) {
|
||||
// only one point available, just play that animation
|
||||
return blend_node(blend_points[0].node, p_time, p_seek, 1.0, FILTER_IGNORE, false);
|
||||
return blend_node(blend_points[0].name,blend_points[0].node, p_time, p_seek, 1.0, FILTER_IGNORE, false);
|
||||
}
|
||||
|
||||
float blend_pos = get_parameter(blend_position);
|
||||
|
||||
float weights[MAX_BLEND_POINTS] = {};
|
||||
|
||||
int point_lower = -1;
|
||||
|
@ -262,7 +277,7 @@ float AnimationNodeBlendSpace1D::process(float p_time, bool p_seek) {
|
|||
float max_time_remaining = 0.0;
|
||||
|
||||
for (int i = 0; i < blend_points_used; i++) {
|
||||
float remaining = blend_node(blend_points[i].node, p_time, p_seek, weights[i], FILTER_IGNORE, false);
|
||||
float remaining = blend_node(blend_points[i].name,blend_points[i].node, p_time, p_seek, weights[i], FILTER_IGNORE, false);
|
||||
|
||||
max_time_remaining = MAX(max_time_remaining, remaining);
|
||||
}
|
||||
|
@ -276,18 +291,19 @@ String AnimationNodeBlendSpace1D::get_caption() const {
|
|||
|
||||
AnimationNodeBlendSpace1D::AnimationNodeBlendSpace1D() {
|
||||
|
||||
for(int i=0;i<MAX_BLEND_POINTS;i++) {
|
||||
blend_points[i].name=itos(i);
|
||||
}
|
||||
blend_points_used = 0;
|
||||
max_space = 1;
|
||||
min_space = -1;
|
||||
|
||||
snap = 0.1;
|
||||
value_label = "value";
|
||||
|
||||
blend_position="blend_position";
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace1D::~AnimationNodeBlendSpace1D() {
|
||||
|
||||
for (int i = 0; i < blend_points_used; i++) {
|
||||
blend_points[i].node->set_parent(this);
|
||||
blend_points[i].node->set_tree(get_tree());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
|
|||
};
|
||||
|
||||
struct BlendPoint {
|
||||
StringName name;
|
||||
Ref<AnimationRootNode> node;
|
||||
float position;
|
||||
};
|
||||
|
@ -18,8 +19,6 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
|
|||
BlendPoint blend_points[MAX_BLEND_POINTS];
|
||||
int blend_points_used;
|
||||
|
||||
float blend_pos;
|
||||
|
||||
float max_space;
|
||||
float min_space;
|
||||
|
||||
|
@ -29,12 +28,21 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
|
|||
|
||||
void _add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node);
|
||||
|
||||
void _tree_changed();
|
||||
|
||||
StringName blend_position;
|
||||
|
||||
protected:
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void set_tree(AnimationTree *p_player);
|
||||
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
virtual void get_child_nodes(List<ChildNode> *r_child_nodes);
|
||||
|
||||
|
||||
void add_blend_point(const Ref<AnimationRootNode> &p_node, float p_position, int p_at_index = -1);
|
||||
void set_blend_point_position(int p_point, float p_position);
|
||||
|
@ -54,15 +62,14 @@ public:
|
|||
void set_snap(float p_snap);
|
||||
float get_snap() const;
|
||||
|
||||
void set_blend_pos(float p_pos);
|
||||
float get_blend_pos() const;
|
||||
|
||||
void set_value_label(const String &p_label);
|
||||
String get_value_label() const;
|
||||
|
||||
float process(float p_time, bool p_seek);
|
||||
String get_caption() const;
|
||||
|
||||
Ref<AnimationNode> get_child_by_name(const StringName &p_name);
|
||||
|
||||
AnimationNodeBlendSpace1D();
|
||||
~AnimationNodeBlendSpace1D();
|
||||
};
|
||||
|
|
|
@ -1,18 +1,27 @@
|
|||
#include "animation_blend_space_2d.h"
|
||||
#include "math/delaunay.h"
|
||||
|
||||
void AnimationNodeBlendSpace2D::set_tree(AnimationTree *p_player) {
|
||||
AnimationRootNode::set_tree(p_player);
|
||||
|
||||
for (int i = 0; i < blend_points_used; i++) {
|
||||
blend_points[i].node->set_tree(p_player);
|
||||
void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::VECTOR2,blend_position));
|
||||
}
|
||||
Variant AnimationNodeBlendSpace2D::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return Vector2();
|
||||
}
|
||||
|
||||
|
||||
void AnimationNodeBlendSpace2D::get_child_nodes(List<ChildNode> *r_child_nodes) {
|
||||
for(int i=0;i<blend_points_used;i++) {
|
||||
ChildNode cn;
|
||||
cn.name=itos(i);
|
||||
cn.node=blend_points[i].node;
|
||||
r_child_nodes->push_back(cn);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2D::add_blend_point(const Ref<AnimationRootNode> &p_node, const Vector2 &p_position, int p_at_index) {
|
||||
ERR_FAIL_COND(blend_points_used >= MAX_BLEND_POINTS);
|
||||
ERR_FAIL_COND(p_node.is_null());
|
||||
ERR_FAIL_COND(p_node->get_parent().is_valid());
|
||||
ERR_FAIL_COND(p_at_index < -1 || p_at_index > blend_points_used);
|
||||
|
||||
if (p_at_index == -1 || p_at_index == blend_points_used) {
|
||||
|
@ -32,13 +41,15 @@ void AnimationNodeBlendSpace2D::add_blend_point(const Ref<AnimationRootNode> &p_
|
|||
blend_points[p_at_index].node = p_node;
|
||||
blend_points[p_at_index].position = p_position;
|
||||
|
||||
blend_points[p_at_index].node->set_parent(this);
|
||||
blend_points[p_at_index].node->set_tree(get_tree());
|
||||
blend_points[p_at_index].node->connect("tree_changed",this,"_tree_changed",varray(),CONNECT_REFERENCE_COUNTED);
|
||||
blend_points_used++;
|
||||
|
||||
|
||||
if (auto_triangles) {
|
||||
trianges_dirty = true;
|
||||
}
|
||||
emit_signal("tree_changed");
|
||||
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2D::set_blend_point_position(int p_point, const Vector2 &p_position) {
|
||||
|
@ -53,12 +64,13 @@ void AnimationNodeBlendSpace2D::set_blend_point_node(int p_point, const Ref<Anim
|
|||
ERR_FAIL_COND(p_node.is_null());
|
||||
|
||||
if (blend_points[p_point].node.is_valid()) {
|
||||
blend_points[p_point].node->set_parent(NULL);
|
||||
blend_points[p_point].node->set_tree(NULL);
|
||||
blend_points[p_point].node->disconnect("tree_changed",this,"_tree_changed");
|
||||
}
|
||||
blend_points[p_point].node = p_node;
|
||||
blend_points[p_point].node->set_parent(this);
|
||||
blend_points[p_point].node->set_tree(get_tree());
|
||||
blend_points[p_point].node->connect("tree_changed",this,"_tree_changed",varray(),CONNECT_REFERENCE_COUNTED);
|
||||
|
||||
emit_signal("tree_changed");
|
||||
|
||||
}
|
||||
Vector2 AnimationNodeBlendSpace2D::get_blend_point_position(int p_point) const {
|
||||
ERR_FAIL_INDEX_V(p_point, blend_points_used, Vector2());
|
||||
|
@ -71,8 +83,7 @@ Ref<AnimationRootNode> AnimationNodeBlendSpace2D::get_blend_point_node(int p_poi
|
|||
void AnimationNodeBlendSpace2D::remove_blend_point(int p_point) {
|
||||
ERR_FAIL_INDEX(p_point, blend_points_used);
|
||||
|
||||
blend_points[p_point].node->set_parent(NULL);
|
||||
blend_points[p_point].node->set_tree(NULL);
|
||||
blend_points[p_point].node->disconnect("tree_changed",this,"_tree_changed");
|
||||
|
||||
for (int i = 0; i < triangles.size(); i++) {
|
||||
bool erase = false;
|
||||
|
@ -95,6 +106,8 @@ void AnimationNodeBlendSpace2D::remove_blend_point(int p_point) {
|
|||
blend_points[i] = blend_points[i + 1];
|
||||
}
|
||||
blend_points_used--;
|
||||
emit_signal("tree_changed");
|
||||
|
||||
}
|
||||
|
||||
int AnimationNodeBlendSpace2D::get_blend_point_count() const {
|
||||
|
@ -217,13 +230,6 @@ Vector2 AnimationNodeBlendSpace2D::get_snap() const {
|
|||
return snap;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2D::set_blend_position(const Vector2 &p_pos) {
|
||||
blend_pos = p_pos;
|
||||
}
|
||||
Vector2 AnimationNodeBlendSpace2D::get_blend_position() const {
|
||||
return blend_pos;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2D::set_x_label(const String &p_label) {
|
||||
x_label = p_label;
|
||||
}
|
||||
|
@ -381,6 +387,8 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
|
|||
|
||||
_update_triangles();
|
||||
|
||||
Vector2 blend_pos = get_parameter(blend_position);
|
||||
|
||||
if (triangles.size() == 0)
|
||||
return 0;
|
||||
|
||||
|
@ -443,7 +451,7 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
|
|||
for (int j = 0; j < 3; j++) {
|
||||
if (i == triangle_points[j]) {
|
||||
//blend with the given weight
|
||||
float t = blend_node(blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false);
|
||||
float t = blend_node(blend_points[i].name,blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false);
|
||||
if (first || t < mind) {
|
||||
mind = t;
|
||||
first = false;
|
||||
|
@ -455,7 +463,7 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
|
|||
|
||||
if (!found) {
|
||||
//ignore
|
||||
blend_node(blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false);
|
||||
blend_node(blend_points[i].name,blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false);
|
||||
}
|
||||
}
|
||||
return mind;
|
||||
|
@ -483,10 +491,19 @@ void AnimationNodeBlendSpace2D::set_auto_triangles(bool p_enable) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool AnimationNodeBlendSpace2D::get_auto_triangles() const {
|
||||
return auto_triangles;
|
||||
}
|
||||
|
||||
Ref<AnimationNode> AnimationNodeBlendSpace2D::get_child_by_name(const StringName &p_name) {
|
||||
return get_blend_point_node(p_name.operator String().to_int());
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2D::_tree_changed() {
|
||||
emit_signal("tree_changed");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendSpace2D::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_blend_point", "node", "pos", "at_index"), &AnimationNodeBlendSpace2D::add_blend_point, DEFVAL(-1));
|
||||
|
@ -511,9 +528,6 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &AnimationNodeBlendSpace2D::set_snap);
|
||||
ClassDB::bind_method(D_METHOD("get_snap"), &AnimationNodeBlendSpace2D::get_snap);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_blend_position", "pos"), &AnimationNodeBlendSpace2D::set_blend_position);
|
||||
ClassDB::bind_method(D_METHOD("get_blend_position"), &AnimationNodeBlendSpace2D::get_blend_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_x_label", "text"), &AnimationNodeBlendSpace2D::set_x_label);
|
||||
ClassDB::bind_method(D_METHOD("get_x_label"), &AnimationNodeBlendSpace2D::get_x_label);
|
||||
|
||||
|
@ -528,10 +542,12 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_auto_triangles", "enable"), &AnimationNodeBlendSpace2D::set_auto_triangles);
|
||||
ClassDB::bind_method(D_METHOD("get_auto_triangles"), &AnimationNodeBlendSpace2D::get_auto_triangles);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationNodeBlendSpace2D::_tree_changed);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_auto_triangles", "get_auto_triangles");
|
||||
|
||||
for (int i = 0; i < MAX_BLEND_POINTS; i++) {
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "_add_blend_point", "get_blend_point_node", i);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "blend_point_" + itos(i) + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_add_blend_point", "get_blend_point_node", i);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::VECTOR2, "blend_point_" + itos(i) + "/pos", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_blend_point_position", "get_blend_point_position", i);
|
||||
}
|
||||
|
||||
|
@ -540,13 +556,15 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "min_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_min_space", "get_min_space");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_max_space", "get_max_space");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_snap", "get_snap");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "blend_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_blend_position", "get_blend_position");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_x_label", "get_x_label");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_y_label", "get_y_label");
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
|
||||
|
||||
for(int i=0;i<MAX_BLEND_POINTS;i++) {
|
||||
blend_points[i].name=itos(i);
|
||||
}
|
||||
auto_triangles = true;
|
||||
blend_points_used = 0;
|
||||
max_space = Vector2(1, 1);
|
||||
|
@ -555,12 +573,10 @@ AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
|
|||
x_label = "x";
|
||||
y_label = "y";
|
||||
trianges_dirty = false;
|
||||
blend_position = "blend_position";
|
||||
}
|
||||
|
||||
AnimationNodeBlendSpace2D::~AnimationNodeBlendSpace2D() {
|
||||
|
||||
for (int i = 0; i < blend_points_used; i++) {
|
||||
blend_points[i].node->set_parent(this);
|
||||
blend_points[i].node->set_tree(get_tree());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ class AnimationNodeBlendSpace2D : public AnimationRootNode {
|
|||
};
|
||||
|
||||
struct BlendPoint {
|
||||
StringName name;
|
||||
Ref<AnimationRootNode> node;
|
||||
Vector2 position;
|
||||
};
|
||||
|
@ -24,7 +25,7 @@ class AnimationNodeBlendSpace2D : public AnimationRootNode {
|
|||
|
||||
Vector<BlendTriangle> triangles;
|
||||
|
||||
Vector2 blend_pos;
|
||||
StringName blend_position;
|
||||
Vector2 max_space;
|
||||
Vector2 min_space;
|
||||
Vector2 snap;
|
||||
|
@ -42,12 +43,19 @@ class AnimationNodeBlendSpace2D : public AnimationRootNode {
|
|||
|
||||
void _update_triangles();
|
||||
|
||||
void _tree_changed();
|
||||
|
||||
|
||||
protected:
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void set_tree(AnimationTree *p_player);
|
||||
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
virtual void get_child_nodes(List<ChildNode> *r_child_nodes);
|
||||
|
||||
void add_blend_point(const Ref<AnimationRootNode> &p_node, const Vector2 &p_position, int p_at_index = -1);
|
||||
void set_blend_point_position(int p_point, const Vector2 &p_position);
|
||||
|
@ -72,9 +80,6 @@ public:
|
|||
void set_snap(const Vector2 &p_snap);
|
||||
Vector2 get_snap() const;
|
||||
|
||||
void set_blend_position(const Vector2 &p_pos);
|
||||
Vector2 get_blend_position() const;
|
||||
|
||||
void set_x_label(const String &p_label);
|
||||
String get_x_label() const;
|
||||
|
||||
|
@ -89,6 +94,8 @@ public:
|
|||
void set_auto_triangles(bool p_enable);
|
||||
bool get_auto_triangles() const;
|
||||
|
||||
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name);
|
||||
|
||||
AnimationNodeBlendSpace2D();
|
||||
~AnimationNodeBlendSpace2D();
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
void AnimationNodeAnimation::set_animation(const StringName &p_name) {
|
||||
animation = p_name;
|
||||
_change_notify("animation");
|
||||
}
|
||||
|
||||
StringName AnimationNodeAnimation::get_animation() const {
|
||||
|
@ -13,43 +14,36 @@ float AnimationNodeAnimation::get_playback_time() const {
|
|||
return time;
|
||||
}
|
||||
|
||||
Vector<String> (*AnimationNodeAnimation::get_editable_animation_list)() = NULL;
|
||||
|
||||
void AnimationNodeAnimation::_validate_property(PropertyInfo &property) const {
|
||||
|
||||
if (property.name == "animation") {
|
||||
AnimationTree *gp = get_tree();
|
||||
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);
|
||||
String anims;
|
||||
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
|
||||
if (E != names.front()) {
|
||||
anims += ",";
|
||||
}
|
||||
anims += String(E->get());
|
||||
}
|
||||
if (anims != String()) {
|
||||
property.hint = PROPERTY_HINT_ENUM;
|
||||
property.hint_string = anims;
|
||||
}
|
||||
if (property.name == "animation" && get_editable_animation_list) {
|
||||
Vector<String> names = get_editable_animation_list();
|
||||
String anims;
|
||||
for (int i = 0; i < names.size(); i++) {
|
||||
|
||||
if (i > 0) {
|
||||
anims += ",";
|
||||
}
|
||||
anims += String(names[i]);
|
||||
}
|
||||
if (anims != String()) {
|
||||
property.hint = PROPERTY_HINT_ENUM;
|
||||
property.hint_string = anims;
|
||||
}
|
||||
}
|
||||
|
||||
AnimationRootNode::_validate_property(property);
|
||||
}
|
||||
|
||||
float AnimationNodeAnimation::process(float p_time, bool p_seek) {
|
||||
|
||||
AnimationPlayer *ap = get_player();
|
||||
AnimationPlayer *ap = state->player;
|
||||
ERR_FAIL_COND_V(!ap, 0);
|
||||
|
||||
Ref<Animation> anim = ap->get_animation(animation);
|
||||
if (!anim.is_valid()) {
|
||||
if (!ap->has_animation(animation)) {
|
||||
|
||||
Ref<AnimationNodeBlendTree> tree = get_parent();
|
||||
if (tree.is_valid()) {
|
||||
AnimationNodeBlendTree *tree = Object::cast_to<AnimationNodeBlendTree>(parent);
|
||||
if (tree) {
|
||||
String name = tree->get_node_name(Ref<AnimationNodeAnimation>(this));
|
||||
make_invalid(vformat(RTR("On BlendTree node '%s', animation not found: '%s'"), name, animation));
|
||||
|
||||
|
@ -60,6 +54,8 @@ float AnimationNodeAnimation::process(float p_time, bool p_seek) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Ref<Animation> anim = ap->get_animation(animation);
|
||||
|
||||
if (p_seek) {
|
||||
time = p_time;
|
||||
step = 0;
|
||||
|
@ -108,6 +104,20 @@ AnimationNodeAnimation::AnimationNodeAnimation() {
|
|||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
void AnimationNodeOneShot::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::BOOL, active));
|
||||
r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", 0));
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, time, PROPERTY_HINT_NONE, "", 0));
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, remaining, PROPERTY_HINT_NONE, "", 0));
|
||||
}
|
||||
Variant AnimationNodeOneShot::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
if (p_parameter == active || p_parameter == prev_active) {
|
||||
return false;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationNodeOneShot::set_fadein_time(float p_time) {
|
||||
|
||||
fade_in = p_time;
|
||||
|
@ -162,18 +172,6 @@ AnimationNodeOneShot::MixMode AnimationNodeOneShot::get_mix_mode() const {
|
|||
return mix;
|
||||
}
|
||||
|
||||
void AnimationNodeOneShot::start() {
|
||||
active = true;
|
||||
do_start = true;
|
||||
}
|
||||
void AnimationNodeOneShot::stop() {
|
||||
active = false;
|
||||
}
|
||||
bool AnimationNodeOneShot::is_active() const {
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
String AnimationNodeOneShot::get_caption() const {
|
||||
return "OneShot";
|
||||
}
|
||||
|
@ -184,8 +182,16 @@ bool AnimationNodeOneShot::has_filter() const {
|
|||
|
||||
float AnimationNodeOneShot::process(float p_time, bool p_seek) {
|
||||
|
||||
bool active = get_parameter(this->active);
|
||||
bool prev_active = get_parameter(this->prev_active);
|
||||
float time = get_parameter(this->time);
|
||||
float remaining = get_parameter(this->remaining);
|
||||
|
||||
if (!active) {
|
||||
//make it as if this node doesn't exist, pass input 0 by.
|
||||
if (prev_active) {
|
||||
set_parameter(this->prev_active, false);
|
||||
}
|
||||
return blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
|
||||
}
|
||||
|
||||
|
@ -193,9 +199,12 @@ float AnimationNodeOneShot::process(float p_time, bool p_seek) {
|
|||
|
||||
if (p_seek)
|
||||
time = p_time;
|
||||
bool do_start = !prev_active;
|
||||
|
||||
if (do_start) {
|
||||
time = 0;
|
||||
os_seek = true;
|
||||
set_parameter(this->prev_active, true);
|
||||
}
|
||||
|
||||
float blend;
|
||||
|
@ -233,10 +242,15 @@ float AnimationNodeOneShot::process(float p_time, bool p_seek) {
|
|||
if (!p_seek) {
|
||||
time += p_time;
|
||||
remaining = os_rem;
|
||||
if (remaining <= 0)
|
||||
active = false;
|
||||
if (remaining <= 0) {
|
||||
set_parameter(this->active, false);
|
||||
set_parameter(this->prev_active, false);
|
||||
}
|
||||
}
|
||||
|
||||
set_parameter(this->time, time);
|
||||
set_parameter(this->remaining, remaining);
|
||||
|
||||
return MAX(main_rem, remaining);
|
||||
}
|
||||
void AnimationNodeOneShot::set_use_sync(bool p_sync) {
|
||||
|
@ -269,10 +283,6 @@ void AnimationNodeOneShot::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_mix_mode", "mode"), &AnimationNodeOneShot::set_mix_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_mix_mode"), &AnimationNodeOneShot::get_mix_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("start"), &AnimationNodeOneShot::start);
|
||||
ClassDB::bind_method(D_METHOD("stop"), &AnimationNodeOneShot::stop);
|
||||
ClassDB::bind_method(D_METHOD("is_active"), &AnimationNodeOneShot::is_active);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync);
|
||||
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync);
|
||||
|
||||
|
@ -297,26 +307,22 @@ AnimationNodeOneShot::AnimationNodeOneShot() {
|
|||
add_input("in");
|
||||
add_input("shot");
|
||||
|
||||
time = 0;
|
||||
fade_in = 0.1;
|
||||
fade_out = 0.1;
|
||||
autorestart = false;
|
||||
autorestart_delay = 1;
|
||||
autorestart_remaining = 0;
|
||||
|
||||
mix = MIX_MODE_BLEND;
|
||||
active = false;
|
||||
do_start = false;
|
||||
sync = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
void AnimationNodeAdd2::set_amount(float p_amount) {
|
||||
amount = p_amount;
|
||||
void AnimationNodeAdd2::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, add_amount, PROPERTY_HINT_RANGE, "0,1,0.01"));
|
||||
}
|
||||
|
||||
float AnimationNodeAdd2::get_amount() const {
|
||||
return amount;
|
||||
Variant AnimationNodeAdd2::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String AnimationNodeAdd2::get_caption() const {
|
||||
|
@ -339,6 +345,7 @@ bool AnimationNodeAdd2::has_filter() const {
|
|||
|
||||
float AnimationNodeAdd2::process(float p_time, bool p_seek) {
|
||||
|
||||
float amount = get_parameter(add_amount);
|
||||
float rem0 = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
|
||||
blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync);
|
||||
|
||||
|
@ -347,32 +354,27 @@ float AnimationNodeAdd2::process(float p_time, bool p_seek) {
|
|||
|
||||
void AnimationNodeAdd2::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &AnimationNodeAdd2::set_amount);
|
||||
ClassDB::bind_method(D_METHOD("get_amount"), &AnimationNodeAdd2::get_amount);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd2::set_use_sync);
|
||||
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd2::is_using_sync);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_amount", "get_amount");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
|
||||
}
|
||||
|
||||
AnimationNodeAdd2::AnimationNodeAdd2() {
|
||||
|
||||
add_amount = "add_amount";
|
||||
add_input("in");
|
||||
add_input("add");
|
||||
amount = 0;
|
||||
sync = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
void AnimationNodeAdd3::set_amount(float p_amount) {
|
||||
amount = p_amount;
|
||||
void AnimationNodeAdd3::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, add_amount, PROPERTY_HINT_RANGE, "-1,1,0.01"));
|
||||
}
|
||||
|
||||
float AnimationNodeAdd3::get_amount() const {
|
||||
return amount;
|
||||
Variant AnimationNodeAdd3::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String AnimationNodeAdd3::get_caption() const {
|
||||
|
@ -395,6 +397,7 @@ bool AnimationNodeAdd3::has_filter() const {
|
|||
|
||||
float AnimationNodeAdd3::process(float p_time, bool p_seek) {
|
||||
|
||||
float amount = get_parameter(add_amount);
|
||||
blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_PASS, !sync);
|
||||
float rem0 = blend_input(1, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
|
||||
blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_PASS, !sync);
|
||||
|
@ -404,39 +407,37 @@ float AnimationNodeAdd3::process(float p_time, bool p_seek) {
|
|||
|
||||
void AnimationNodeAdd3::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &AnimationNodeAdd3::set_amount);
|
||||
ClassDB::bind_method(D_METHOD("get_amount"), &AnimationNodeAdd3::get_amount);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeAdd3::set_use_sync);
|
||||
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeAdd3::is_using_sync);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "amount", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_amount", "get_amount");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
|
||||
}
|
||||
|
||||
AnimationNodeAdd3::AnimationNodeAdd3() {
|
||||
|
||||
add_amount = "add_amount";
|
||||
add_input("-add");
|
||||
add_input("in");
|
||||
add_input("+add");
|
||||
amount = 0;
|
||||
sync = false;
|
||||
}
|
||||
/////////////////////////////////////////////
|
||||
|
||||
void AnimationNodeBlend2::set_amount(float p_amount) {
|
||||
amount = p_amount;
|
||||
void AnimationNodeBlend2::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, blend_amount, PROPERTY_HINT_RANGE, "0,1,0.01"));
|
||||
}
|
||||
Variant AnimationNodeBlend2::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return 0; //for blend amount
|
||||
}
|
||||
|
||||
float AnimationNodeBlend2::get_amount() const {
|
||||
return amount;
|
||||
}
|
||||
String AnimationNodeBlend2::get_caption() const {
|
||||
return "Blend2";
|
||||
}
|
||||
|
||||
float AnimationNodeBlend2::process(float p_time, bool p_seek) {
|
||||
|
||||
float amount = get_parameter(blend_amount);
|
||||
|
||||
float rem0 = blend_input(0, p_time, p_seek, 1.0 - amount, FILTER_BLEND, !sync);
|
||||
float rem1 = blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync);
|
||||
|
||||
|
@ -459,31 +460,25 @@ bool AnimationNodeBlend2::has_filter() const {
|
|||
}
|
||||
void AnimationNodeBlend2::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &AnimationNodeBlend2::set_amount);
|
||||
ClassDB::bind_method(D_METHOD("get_amount"), &AnimationNodeBlend2::get_amount);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend2::set_use_sync);
|
||||
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend2::is_using_sync);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_amount", "get_amount");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
|
||||
}
|
||||
AnimationNodeBlend2::AnimationNodeBlend2() {
|
||||
blend_amount = "blend_amount";
|
||||
add_input("in");
|
||||
add_input("blend");
|
||||
sync = false;
|
||||
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void AnimationNodeBlend3::set_amount(float p_amount) {
|
||||
amount = p_amount;
|
||||
void AnimationNodeBlend3::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, blend_amount, PROPERTY_HINT_RANGE, "-1,1,0.01"));
|
||||
}
|
||||
|
||||
float AnimationNodeBlend3::get_amount() const {
|
||||
return amount;
|
||||
Variant AnimationNodeBlend3::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return 0; //for blend amount
|
||||
}
|
||||
|
||||
String AnimationNodeBlend3::get_caption() const {
|
||||
|
@ -502,6 +497,7 @@ bool AnimationNodeBlend3::is_using_sync() const {
|
|||
|
||||
float AnimationNodeBlend3::process(float p_time, bool p_seek) {
|
||||
|
||||
float amount = get_parameter(blend_amount);
|
||||
float rem0 = blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_IGNORE, !sync);
|
||||
float rem1 = blend_input(1, p_time, p_seek, 1.0 - ABS(amount), FILTER_IGNORE, !sync);
|
||||
float rem2 = blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_IGNORE, !sync);
|
||||
|
@ -511,31 +507,26 @@ float AnimationNodeBlend3::process(float p_time, bool p_seek) {
|
|||
|
||||
void AnimationNodeBlend3::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_amount", "amount"), &AnimationNodeBlend3::set_amount);
|
||||
ClassDB::bind_method(D_METHOD("get_amount"), &AnimationNodeBlend3::get_amount);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlend3::set_use_sync);
|
||||
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlend3::is_using_sync);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "amount", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_amount", "get_amount");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync"), "set_use_sync", "is_using_sync");
|
||||
}
|
||||
AnimationNodeBlend3::AnimationNodeBlend3() {
|
||||
blend_amount = "blend_amount";
|
||||
add_input("-blend");
|
||||
add_input("in");
|
||||
add_input("+blend");
|
||||
sync = false;
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
void AnimationNodeTimeScale::set_scale(float p_scale) {
|
||||
scale = p_scale;
|
||||
void AnimationNodeTimeScale::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, scale, PROPERTY_HINT_RANGE, "0,32,0.01,or_greater"));
|
||||
}
|
||||
|
||||
float AnimationNodeTimeScale::get_scale() const {
|
||||
return scale;
|
||||
Variant AnimationNodeTimeScale::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return 1.0; //initial timescale
|
||||
}
|
||||
|
||||
String AnimationNodeTimeScale::get_caption() const {
|
||||
|
@ -544,6 +535,7 @@ String AnimationNodeTimeScale::get_caption() const {
|
|||
|
||||
float AnimationNodeTimeScale::process(float p_time, bool p_seek) {
|
||||
|
||||
float scale = get_parameter(this->scale);
|
||||
if (p_seek) {
|
||||
return blend_input(0, p_time, true, 1.0, FILTER_IGNORE, false);
|
||||
} else {
|
||||
|
@ -552,25 +544,19 @@ float AnimationNodeTimeScale::process(float p_time, bool p_seek) {
|
|||
}
|
||||
|
||||
void AnimationNodeTimeScale::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &AnimationNodeTimeScale::set_scale);
|
||||
ClassDB::bind_method(D_METHOD("get_scale"), &AnimationNodeTimeScale::get_scale);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "scale", PROPERTY_HINT_RANGE, "0,32,0.01,or_greater"), "set_scale", "get_scale");
|
||||
}
|
||||
AnimationNodeTimeScale::AnimationNodeTimeScale() {
|
||||
scale = "scale";
|
||||
add_input("in");
|
||||
scale = 1.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
void AnimationNodeTimeSeek::set_seek_pos(float p_seek_pos) {
|
||||
seek_pos = p_seek_pos;
|
||||
void AnimationNodeTimeSeek::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, seek_pos, PROPERTY_HINT_RANGE, "-1,3600,0.01,or_greater"));
|
||||
}
|
||||
|
||||
float AnimationNodeTimeSeek::get_seek_pos() const {
|
||||
return seek_pos;
|
||||
Variant AnimationNodeTimeSeek::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return 1.0; //initial timescale
|
||||
}
|
||||
|
||||
String AnimationNodeTimeSeek::get_caption() const {
|
||||
|
@ -579,11 +565,12 @@ String AnimationNodeTimeSeek::get_caption() const {
|
|||
|
||||
float AnimationNodeTimeSeek::process(float p_time, bool p_seek) {
|
||||
|
||||
float seek_pos = get_parameter(this->seek_pos);
|
||||
if (p_seek) {
|
||||
return blend_input(0, p_time, true, 1.0, FILTER_IGNORE, false);
|
||||
} else if (seek_pos >= 0) {
|
||||
float ret = blend_input(0, seek_pos, true, 1.0, FILTER_IGNORE, false);
|
||||
seek_pos = -1;
|
||||
set_parameter(this->seek_pos, -1.0); //reset
|
||||
_change_notify("seek_pos");
|
||||
return ret;
|
||||
} else {
|
||||
|
@ -592,19 +579,41 @@ float AnimationNodeTimeSeek::process(float p_time, bool p_seek) {
|
|||
}
|
||||
|
||||
void AnimationNodeTimeSeek::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_seek_pos", "seek_pos"), &AnimationNodeTimeSeek::set_seek_pos);
|
||||
ClassDB::bind_method(D_METHOD("get_seek_pos"), &AnimationNodeTimeSeek::get_seek_pos);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "seek_pos", PROPERTY_HINT_RANGE, "-1,3600,0.01,or_greater"), "set_seek_pos", "get_seek_pos");
|
||||
}
|
||||
|
||||
AnimationNodeTimeSeek::AnimationNodeTimeSeek() {
|
||||
add_input("in");
|
||||
seek_pos = -1;
|
||||
seek_pos = "seek_position";
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
void AnimationNodeTransition::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
|
||||
String anims;
|
||||
for (int i = 0; i < enabled_inputs; i++) {
|
||||
if (i > 0) {
|
||||
anims += ",";
|
||||
}
|
||||
anims += inputs[i].name;
|
||||
}
|
||||
|
||||
r_list->push_back(PropertyInfo(Variant::INT, current, PROPERTY_HINT_ENUM, anims));
|
||||
r_list->push_back(PropertyInfo(Variant::INT, prev_current, PROPERTY_HINT_NONE, "", 0));
|
||||
r_list->push_back(PropertyInfo(Variant::INT, prev, PROPERTY_HINT_NONE, "", 0));
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, time, PROPERTY_HINT_NONE, "", 0));
|
||||
r_list->push_back(PropertyInfo(Variant::REAL, prev_xfading, PROPERTY_HINT_NONE, "", 0));
|
||||
}
|
||||
Variant AnimationNodeTransition::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
if (p_parameter == time || p_parameter == prev_xfading) {
|
||||
return 0.0;
|
||||
} else if (p_parameter == prev || p_parameter == prev_current) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
String AnimationNodeTransition::get_caption() const {
|
||||
return "Transition";
|
||||
}
|
||||
|
@ -650,18 +659,12 @@ String AnimationNodeTransition::get_input_caption(int p_input) const {
|
|||
return inputs[p_input].name;
|
||||
}
|
||||
|
||||
void AnimationNodeTransition::set_current(int p_current) {
|
||||
|
||||
if (current == p_current)
|
||||
return;
|
||||
ERR_FAIL_INDEX(p_current, enabled_inputs);
|
||||
|
||||
#if 0
|
||||
Ref<AnimationNodeBlendTree> tree = get_parent();
|
||||
|
||||
if (tree.is_valid() && current >= 0) {
|
||||
prev = current;
|
||||
prev_xfading = xfade;
|
||||
prev_time = time;
|
||||
prev_xfading = xfade;
|
||||
time = 0;
|
||||
current = p_current;
|
||||
switched = true;
|
||||
|
@ -669,11 +672,8 @@ void AnimationNodeTransition::set_current(int p_current) {
|
|||
} else {
|
||||
current = p_current;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int AnimationNodeTransition::get_current() const {
|
||||
return current;
|
||||
}
|
||||
void AnimationNodeTransition::set_cross_fade_time(float p_fade) {
|
||||
xfade = p_fade;
|
||||
}
|
||||
|
@ -684,9 +684,34 @@ float AnimationNodeTransition::get_cross_fade_time() const {
|
|||
|
||||
float AnimationNodeTransition::process(float p_time, bool p_seek) {
|
||||
|
||||
int current = get_parameter(this->current);
|
||||
int prev = get_parameter(this->prev);
|
||||
int prev_current = get_parameter(this->prev_current);
|
||||
|
||||
float time = get_parameter(this->time);
|
||||
float prev_xfading = get_parameter(this->prev_xfading);
|
||||
|
||||
bool switched = current != prev_current;
|
||||
|
||||
if (switched) {
|
||||
set_parameter(this->prev_current, current);
|
||||
set_parameter(this->prev, prev_current);
|
||||
|
||||
prev = prev_current;
|
||||
prev_xfading = xfade;
|
||||
time = 0;
|
||||
switched = true;
|
||||
}
|
||||
|
||||
if (current < 0 || current >= enabled_inputs || prev >= enabled_inputs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float rem = 0;
|
||||
|
||||
if (prev < 0) { // process current animation, check for transition
|
||||
|
||||
float rem = blend_input(current, p_time, p_seek, 1.0, FILTER_IGNORE, false);
|
||||
rem = blend_input(current, p_time, p_seek, 1.0, FILTER_IGNORE, false);
|
||||
|
||||
if (p_seek)
|
||||
time = p_time;
|
||||
|
@ -695,16 +720,13 @@ float AnimationNodeTransition::process(float p_time, bool p_seek) {
|
|||
|
||||
if (inputs[current].auto_advance && rem <= xfade) {
|
||||
|
||||
set_current((current + 1) % enabled_inputs);
|
||||
set_parameter(this->current, (current + 1) % enabled_inputs);
|
||||
}
|
||||
|
||||
return rem;
|
||||
} else { // cross-fading from prev to current
|
||||
|
||||
float blend = xfade ? (prev_xfading / xfade) : 1;
|
||||
|
||||
float rem;
|
||||
|
||||
if (!p_seek && switched) { //just switched, seek to start of current
|
||||
|
||||
rem = blend_input(current, 0, true, 1.0 - blend, FILTER_IGNORE, false);
|
||||
|
@ -723,28 +745,19 @@ float AnimationNodeTransition::process(float p_time, bool p_seek) {
|
|||
time += p_time;
|
||||
prev_xfading -= p_time;
|
||||
if (prev_xfading < 0) {
|
||||
prev = -1;
|
||||
set_parameter(this->prev, -1);
|
||||
}
|
||||
}
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
set_parameter(this->time, time);
|
||||
set_parameter(this->prev_xfading, prev_xfading);
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
void AnimationNodeTransition::_validate_property(PropertyInfo &property) const {
|
||||
|
||||
if (property.name == "current" && enabled_inputs > 0) {
|
||||
property.hint = PROPERTY_HINT_ENUM;
|
||||
String anims;
|
||||
for (int i = 0; i < enabled_inputs; i++) {
|
||||
if (i > 0) {
|
||||
anims += ",";
|
||||
}
|
||||
anims += inputs[i].name;
|
||||
}
|
||||
property.hint_string = anims;
|
||||
}
|
||||
|
||||
if (property.name.begins_with("input_")) {
|
||||
String n = property.name.get_slicec('/', 0).get_slicec('_', 1);
|
||||
if (n != "count") {
|
||||
|
@ -769,14 +782,10 @@ void AnimationNodeTransition::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_input_caption", "input", "caption"), &AnimationNodeTransition::set_input_caption);
|
||||
ClassDB::bind_method(D_METHOD("get_input_caption", "input"), &AnimationNodeTransition::get_input_caption);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_current", "index"), &AnimationNodeTransition::set_current);
|
||||
ClassDB::bind_method(D_METHOD("get_current"), &AnimationNodeTransition::get_current);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cross_fade_time", "time"), &AnimationNodeTransition::set_cross_fade_time);
|
||||
ClassDB::bind_method(D_METHOD("get_cross_fade_time"), &AnimationNodeTransition::get_cross_fade_time);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "current", PROPERTY_HINT_RANGE, "0,64,1"), "set_current", "get_current");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01"), "set_cross_fade_time", "get_cross_fade_time");
|
||||
|
||||
for (int i = 0; i < MAX_INPUTS; i++) {
|
||||
|
@ -786,13 +795,15 @@ void AnimationNodeTransition::_bind_methods() {
|
|||
}
|
||||
|
||||
AnimationNodeTransition::AnimationNodeTransition() {
|
||||
|
||||
prev_xfading = "prev_xfading";
|
||||
prev = "prev";
|
||||
time = "time";
|
||||
current = "current";
|
||||
prev_current = "prev_current";
|
||||
;
|
||||
|
||||
enabled_inputs = 0;
|
||||
xfade = 0;
|
||||
current = -1;
|
||||
prev = -1;
|
||||
prev_time = 0;
|
||||
prev_xfading = 0;
|
||||
switched = false;
|
||||
for (int i = 0; i < MAX_INPUTS; i++) {
|
||||
inputs[i].auto_advance = false;
|
||||
inputs[i].name = itos(i + 1);
|
||||
|
@ -814,69 +825,102 @@ AnimationNodeOutput::AnimationNodeOutput() {
|
|||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNode> p_node) {
|
||||
void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNode> p_node, const Vector2 &p_position) {
|
||||
|
||||
ERR_FAIL_COND(nodes.has(p_name));
|
||||
ERR_FAIL_COND(p_node.is_null());
|
||||
ERR_FAIL_COND(p_node->get_parent().is_valid());
|
||||
ERR_FAIL_COND(p_node->get_tree() != NULL);
|
||||
ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output);
|
||||
ERR_FAIL_COND(String(p_name).find("/") != -1);
|
||||
nodes[p_name] = p_node;
|
||||
|
||||
p_node->set_parent(this);
|
||||
p_node->set_tree(get_tree());
|
||||
Node n;
|
||||
n.node = p_node;
|
||||
n.position = p_position;
|
||||
n.connections.resize(n.node->get_input_count());
|
||||
nodes[p_name] = n;
|
||||
|
||||
emit_changed();
|
||||
emit_signal("tree_changed");
|
||||
|
||||
p_node->connect("tree_changed", this, "_tree_changed", varray(), CONNECT_REFERENCE_COUNTED);
|
||||
p_node->connect("changed", this, "_node_changed", varray(p_name), CONNECT_REFERENCE_COUNTED);
|
||||
}
|
||||
|
||||
Ref<AnimationNode> AnimationNodeBlendTree::get_node(const StringName &p_name) const {
|
||||
|
||||
ERR_FAIL_COND_V(!nodes.has(p_name), Ref<AnimationNode>());
|
||||
|
||||
return nodes[p_name];
|
||||
return nodes[p_name].node;
|
||||
}
|
||||
|
||||
StringName AnimationNodeBlendTree::get_node_name(const Ref<AnimationNode> &p_node) const {
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
if (E->get() == p_node) {
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
if (E->get().node == p_node) {
|
||||
return E->key();
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_V(StringName());
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::set_node_position(const StringName &p_node, const Vector2 &p_position) {
|
||||
ERR_FAIL_COND(!nodes.has(p_node));
|
||||
nodes[p_node].position = p_position;
|
||||
}
|
||||
|
||||
Vector2 AnimationNodeBlendTree::get_node_position(const StringName &p_node) const {
|
||||
ERR_FAIL_COND_V(!nodes.has(p_node), Vector2());
|
||||
return nodes[p_node].position;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::get_child_nodes(List<ChildNode> *r_child_nodes) {
|
||||
Vector<StringName> ns;
|
||||
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
ns.push_back(E->key());
|
||||
}
|
||||
|
||||
ns.sort_custom<StringName::AlphCompare>();
|
||||
|
||||
for (int i = 0; i < ns.size(); i++) {
|
||||
ChildNode cn;
|
||||
cn.name = ns[i];
|
||||
cn.node = nodes[cn.name].node;
|
||||
r_child_nodes->push_back(cn);
|
||||
}
|
||||
}
|
||||
|
||||
bool AnimationNodeBlendTree::has_node(const StringName &p_name) const {
|
||||
return nodes.has(p_name);
|
||||
}
|
||||
Vector<StringName> AnimationNodeBlendTree::get_node_connection_array(const StringName &p_name) const {
|
||||
|
||||
ERR_FAIL_COND_V(!nodes.has(p_name), Vector<StringName>());
|
||||
return nodes[p_name].connections;
|
||||
}
|
||||
void AnimationNodeBlendTree::remove_node(const StringName &p_name) {
|
||||
|
||||
ERR_FAIL_COND(!nodes.has(p_name));
|
||||
ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output); //can't delete output
|
||||
|
||||
{
|
||||
//erase node connections
|
||||
Ref<AnimationNode> node = nodes[p_name];
|
||||
for (int i = 0; i < node->get_input_count(); i++) {
|
||||
node->set_input_connection(i, StringName());
|
||||
}
|
||||
node->set_parent(NULL);
|
||||
node->set_tree(NULL);
|
||||
Ref<AnimationNode> node = nodes[p_name].node;
|
||||
node->disconnect("tree_changed", this, "_tree_changed");
|
||||
node->disconnect("changed", this, "_node_changed");
|
||||
}
|
||||
|
||||
nodes.erase(p_name);
|
||||
|
||||
//erase connections to name
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
Ref<AnimationNode> node = E->get();
|
||||
for (int i = 0; i < node->get_input_count(); i++) {
|
||||
if (node->get_input_connection(i) == p_name) {
|
||||
node->set_input_connection(i, StringName());
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
for (int i = 0; i < E->get().connections.size(); i++) {
|
||||
if (E->get().connections[i] == p_name) {
|
||||
E->get().connections.write[i] = StringName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit_changed();
|
||||
emit_signal("tree_changed");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringName &p_new_name) {
|
||||
|
@ -886,18 +930,24 @@ void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringN
|
|||
ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output);
|
||||
ERR_FAIL_COND(p_new_name == SceneStringNames::get_singleton()->output);
|
||||
|
||||
nodes[p_name].node->disconnect("changed", this, "_node_changed");
|
||||
|
||||
nodes[p_new_name] = nodes[p_name];
|
||||
nodes.erase(p_name);
|
||||
|
||||
//rename connections
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
Ref<AnimationNode> node = E->get();
|
||||
for (int i = 0; i < node->get_input_count(); i++) {
|
||||
if (node->get_input_connection(i) == p_name) {
|
||||
node->set_input_connection(i, p_new_name);
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
|
||||
for (int i = 0; i < E->get().connections.size(); i++) {
|
||||
if (E->get().connections[i] == p_name) {
|
||||
E->get().connections.write[i] = p_new_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
//connection must be done with new name
|
||||
nodes[p_new_name].node->connect("changed", this, "_node_changed", varray(p_new_name), CONNECT_REFERENCE_COUNTED);
|
||||
|
||||
emit_signal("tree_changed");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) {
|
||||
|
@ -907,18 +957,18 @@ void AnimationNodeBlendTree::connect_node(const StringName &p_input_node, int p_
|
|||
ERR_FAIL_COND(p_output_node == SceneStringNames::get_singleton()->output);
|
||||
ERR_FAIL_COND(p_input_node == p_output_node);
|
||||
|
||||
Ref<AnimationNode> input = nodes[p_input_node];
|
||||
ERR_FAIL_INDEX(p_input_index, input->get_input_count());
|
||||
Ref<AnimationNode> input = nodes[p_input_node].node;
|
||||
ERR_FAIL_INDEX(p_input_index, nodes[p_input_node].connections.size());
|
||||
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
Ref<AnimationNode> node = E->get();
|
||||
for (int i = 0; i < node->get_input_count(); i++) {
|
||||
StringName output = node->get_input_connection(i);
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
for (int i = 0; i < E->get().connections.size(); i++) {
|
||||
StringName output = E->get().connections[i];
|
||||
ERR_FAIL_COND(output == p_output_node);
|
||||
}
|
||||
}
|
||||
|
||||
input->set_input_connection(p_input_index, p_output_node);
|
||||
nodes[p_input_node].connections.write[p_input_index] = p_output_node;
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
|
@ -926,20 +976,21 @@ void AnimationNodeBlendTree::disconnect_node(const StringName &p_node, int p_inp
|
|||
|
||||
ERR_FAIL_COND(!nodes.has(p_node));
|
||||
|
||||
Ref<AnimationNode> input = nodes[p_node];
|
||||
ERR_FAIL_INDEX(p_input_index, input->get_input_count());
|
||||
Ref<AnimationNode> input = nodes[p_node].node;
|
||||
ERR_FAIL_INDEX(p_input_index, nodes[p_node].connections.size());
|
||||
|
||||
input->set_input_connection(p_input_index, StringName());
|
||||
nodes[p_node].connections.write[p_input_index] = StringName();
|
||||
}
|
||||
|
||||
float AnimationNodeBlendTree::get_connection_activity(const StringName &p_input_node, int p_input_index) const {
|
||||
|
||||
ERR_FAIL_COND_V(!nodes.has(p_input_node), 0);
|
||||
|
||||
Ref<AnimationNode> input = nodes[p_input_node];
|
||||
ERR_FAIL_INDEX_V(p_input_index, input->get_input_count(), 0);
|
||||
Ref<AnimationNode> input = nodes[p_input_node].node;
|
||||
ERR_FAIL_INDEX_V(p_input_index, nodes[p_input_node].connections.size(), 0);
|
||||
|
||||
return input->get_input_activity(p_input_index);
|
||||
//return input->get_input_activity(p_input_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) const {
|
||||
|
@ -956,20 +1007,19 @@ AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node
|
|||
return CONNECTION_ERROR_SAME_NODE;
|
||||
}
|
||||
|
||||
Ref<AnimationNode> input = nodes[p_input_node];
|
||||
Ref<AnimationNode> input = nodes[p_input_node].node;
|
||||
|
||||
if (p_input_index < 0 || p_input_index >= input->get_input_count()) {
|
||||
if (p_input_index < 0 || p_input_index >= nodes[p_input_node].connections.size()) {
|
||||
return CONNECTION_ERROR_NO_INPUT_INDEX;
|
||||
}
|
||||
|
||||
if (input->get_input_connection(p_input_index) != StringName()) {
|
||||
if (nodes[p_input_node].connections[p_input_index] != StringName()) {
|
||||
return CONNECTION_ERROR_CONNECTION_EXISTS;
|
||||
}
|
||||
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
Ref<AnimationNode> node = E->get();
|
||||
for (int i = 0; i < node->get_input_count(); i++) {
|
||||
StringName output = node->get_input_connection(i);
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
for (int i = 0; i < E->get().connections.size(); i++) {
|
||||
StringName output = E->get().connections[i];
|
||||
if (output == p_output_node) {
|
||||
return CONNECTION_ERROR_CONNECTION_EXISTS;
|
||||
}
|
||||
|
@ -980,10 +1030,9 @@ AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node
|
|||
|
||||
void AnimationNodeBlendTree::get_node_connections(List<NodeConnection> *r_connections) const {
|
||||
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
Ref<AnimationNode> node = E->get();
|
||||
for (int i = 0; i < node->get_input_count(); i++) {
|
||||
StringName output = node->get_input_connection(i);
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
for (int i = 0; i < E->get().connections.size(); i++) {
|
||||
StringName output = E->get().connections[i];
|
||||
if (output != StringName()) {
|
||||
NodeConnection nc;
|
||||
nc.input_node = E->key();
|
||||
|
@ -1001,13 +1050,13 @@ String AnimationNodeBlendTree::get_caption() const {
|
|||
|
||||
float AnimationNodeBlendTree::process(float p_time, bool p_seek) {
|
||||
|
||||
Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output];
|
||||
return blend_node(output, p_time, p_seek, 1.0);
|
||||
Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output].node;
|
||||
return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, 1.0);
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::get_node_list(List<StringName> *r_list) {
|
||||
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
r_list->push_back(E->key());
|
||||
}
|
||||
}
|
||||
|
@ -1022,14 +1071,8 @@ Vector2 AnimationNodeBlendTree::get_graph_offset() const {
|
|||
return graph_offset;
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::set_tree(AnimationTree *p_player) {
|
||||
|
||||
AnimationNode::set_tree(p_player);
|
||||
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
Ref<AnimationNode> node = E->get();
|
||||
node->set_tree(p_player);
|
||||
}
|
||||
Ref<AnimationNode> AnimationNodeBlendTree::get_child_by_name(const StringName &p_name) {
|
||||
return get_node(p_name);
|
||||
}
|
||||
|
||||
bool AnimationNodeBlendTree::_set(const StringName &p_name, const Variant &p_value) {
|
||||
|
@ -1051,7 +1094,7 @@ bool AnimationNodeBlendTree::_set(const StringName &p_name, const Variant &p_val
|
|||
if (what == "position") {
|
||||
|
||||
if (nodes.has(node_name)) {
|
||||
nodes[node_name]->set_position(p_value);
|
||||
nodes[node_name].position = p_value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1078,7 +1121,7 @@ bool AnimationNodeBlendTree::_get(const StringName &p_name, Variant &r_ret) cons
|
|||
|
||||
if (what == "node") {
|
||||
if (nodes.has(node_name)) {
|
||||
r_ret = nodes[node_name];
|
||||
r_ret = nodes[node_name].node;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1086,7 +1129,7 @@ bool AnimationNodeBlendTree::_get(const StringName &p_name, Variant &r_ret) cons
|
|||
if (what == "position") {
|
||||
|
||||
if (nodes.has(node_name)) {
|
||||
r_ret = nodes[node_name]->get_position();
|
||||
r_ret = nodes[node_name].position;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1113,7 +1156,7 @@ bool AnimationNodeBlendTree::_get(const StringName &p_name, Variant &r_ret) cons
|
|||
void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
|
||||
List<StringName> names;
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
for (Map<StringName, Node>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
names.push_back(E->key());
|
||||
}
|
||||
names.sort_custom<StringName::AlphCompare>();
|
||||
|
@ -1121,7 +1164,7 @@ void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) cons
|
|||
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
|
||||
String name = E->get();
|
||||
if (name != "output") {
|
||||
p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
|
||||
p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR));
|
||||
}
|
||||
p_list->push_back(PropertyInfo(Variant::VECTOR2, "nodes/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
}
|
||||
|
@ -1129,9 +1172,19 @@ void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) cons
|
|||
p_list->push_back(PropertyInfo(Variant::ARRAY, "node_connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::_tree_changed() {
|
||||
emit_signal("tree_changed");
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::_node_changed(const StringName &p_node) {
|
||||
|
||||
ERR_FAIL_COND(!nodes.has(p_node));
|
||||
nodes[p_node].connections.resize(nodes[p_node].node->get_input_count());
|
||||
}
|
||||
|
||||
void AnimationNodeBlendTree::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_node", "name", "node"), &AnimationNodeBlendTree::add_node);
|
||||
ClassDB::bind_method(D_METHOD("add_node", "name", "node", "position"), &AnimationNodeBlendTree::add_node, DEFVAL(Vector2()));
|
||||
ClassDB::bind_method(D_METHOD("get_node", "name"), &AnimationNodeBlendTree::get_node);
|
||||
ClassDB::bind_method(D_METHOD("remove_node", "name"), &AnimationNodeBlendTree::remove_node);
|
||||
ClassDB::bind_method(D_METHOD("rename_node", "name", "new_name"), &AnimationNodeBlendTree::rename_node);
|
||||
|
@ -1139,9 +1192,15 @@ void AnimationNodeBlendTree::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("connect_node", "input_node", "input_index", "output_node"), &AnimationNodeBlendTree::connect_node);
|
||||
ClassDB::bind_method(D_METHOD("disconnect_node", "input_node", "input_index"), &AnimationNodeBlendTree::disconnect_node);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_node_position", "name", "position"), &AnimationNodeBlendTree::set_node_position);
|
||||
ClassDB::bind_method(D_METHOD("get_node_position", "name"), &AnimationNodeBlendTree::get_node_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &AnimationNodeBlendTree::set_graph_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_graph_offset"), &AnimationNodeBlendTree::get_graph_offset);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationNodeBlendTree::_tree_changed);
|
||||
ClassDB::bind_method(D_METHOD("_node_changed", "node"), &AnimationNodeBlendTree::_node_changed);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset");
|
||||
|
||||
BIND_CONSTANT(CONNECTION_OK);
|
||||
|
@ -1156,15 +1215,12 @@ AnimationNodeBlendTree::AnimationNodeBlendTree() {
|
|||
|
||||
Ref<AnimationNodeOutput> output;
|
||||
output.instance();
|
||||
output->set_position(Vector2(300, 150));
|
||||
output->set_parent(this);
|
||||
nodes["output"] = output;
|
||||
Node n;
|
||||
n.node = output;
|
||||
n.position = Vector2(300, 150);
|
||||
n.connections.resize(1);
|
||||
nodes["output"] = n;
|
||||
}
|
||||
|
||||
AnimationNodeBlendTree::~AnimationNodeBlendTree() {
|
||||
|
||||
for (Map<StringName, Ref<AnimationNode> >::Element *E = nodes.front(); E; E = E->next()) {
|
||||
E->get()->set_parent(NULL);
|
||||
E->get()->set_tree(NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static Vector<String> (*get_editable_animation_list)();
|
||||
|
||||
virtual String get_caption() const;
|
||||
virtual float process(float p_time, bool p_seek);
|
||||
|
||||
|
@ -41,8 +43,6 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
bool active;
|
||||
bool do_start;
|
||||
float fade_in;
|
||||
float fade_out;
|
||||
|
||||
|
@ -51,15 +51,25 @@ private:
|
|||
float autorestart_random_delay;
|
||||
MixMode mix;
|
||||
|
||||
float time;
|
||||
float remaining;
|
||||
float autorestart_remaining;
|
||||
bool sync;
|
||||
|
||||
/* bool active;
|
||||
bool do_start;
|
||||
float time;
|
||||
float remaining;*/
|
||||
|
||||
StringName active;
|
||||
StringName prev_active;
|
||||
StringName time;
|
||||
StringName remaining;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
virtual String get_caption() const;
|
||||
|
||||
void set_fadein_time(float p_time);
|
||||
|
@ -79,10 +89,6 @@ public:
|
|||
void set_mix_mode(MixMode p_mix);
|
||||
MixMode get_mix_mode() const;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
bool is_active() const;
|
||||
|
||||
void set_use_sync(bool p_sync);
|
||||
bool is_using_sync() const;
|
||||
|
||||
|
@ -97,17 +103,17 @@ VARIANT_ENUM_CAST(AnimationNodeOneShot::MixMode)
|
|||
class AnimationNodeAdd2 : public AnimationNode {
|
||||
GDCLASS(AnimationNodeAdd2, AnimationNode);
|
||||
|
||||
float amount;
|
||||
StringName add_amount;
|
||||
bool sync;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_caption() const;
|
||||
void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
void set_amount(float p_amount);
|
||||
float get_amount() const;
|
||||
virtual String get_caption() const;
|
||||
|
||||
void set_use_sync(bool p_sync);
|
||||
bool is_using_sync() const;
|
||||
|
@ -121,17 +127,17 @@ public:
|
|||
class AnimationNodeAdd3 : public AnimationNode {
|
||||
GDCLASS(AnimationNodeAdd3, AnimationNode);
|
||||
|
||||
float amount;
|
||||
StringName add_amount;
|
||||
bool sync;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_caption() const;
|
||||
void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
void set_amount(float p_amount);
|
||||
float get_amount() const;
|
||||
virtual String get_caption() const;
|
||||
|
||||
void set_use_sync(bool p_sync);
|
||||
bool is_using_sync() const;
|
||||
|
@ -145,19 +151,19 @@ public:
|
|||
class AnimationNodeBlend2 : public AnimationNode {
|
||||
GDCLASS(AnimationNodeBlend2, AnimationNode);
|
||||
|
||||
float amount;
|
||||
StringName blend_amount;
|
||||
bool sync;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
virtual String get_caption() const;
|
||||
virtual float process(float p_time, bool p_seek);
|
||||
|
||||
void set_amount(float p_amount);
|
||||
float get_amount() const;
|
||||
|
||||
void set_use_sync(bool p_sync);
|
||||
bool is_using_sync() const;
|
||||
|
||||
|
@ -168,17 +174,17 @@ public:
|
|||
class AnimationNodeBlend3 : public AnimationNode {
|
||||
GDCLASS(AnimationNodeBlend3, AnimationNode);
|
||||
|
||||
float amount;
|
||||
StringName blend_amount;
|
||||
bool sync;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_caption() const;
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
void set_amount(float p_amount);
|
||||
float get_amount() const;
|
||||
virtual String get_caption() const;
|
||||
|
||||
void set_use_sync(bool p_sync);
|
||||
bool is_using_sync() const;
|
||||
|
@ -190,16 +196,16 @@ public:
|
|||
class AnimationNodeTimeScale : public AnimationNode {
|
||||
GDCLASS(AnimationNodeTimeScale, AnimationNode);
|
||||
|
||||
float scale;
|
||||
StringName scale;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_caption() const;
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
void set_scale(float p_scale);
|
||||
float get_scale() const;
|
||||
virtual String get_caption() const;
|
||||
|
||||
float process(float p_time, bool p_seek);
|
||||
|
||||
|
@ -209,16 +215,16 @@ public:
|
|||
class AnimationNodeTimeSeek : public AnimationNode {
|
||||
GDCLASS(AnimationNodeTimeSeek, AnimationNode);
|
||||
|
||||
float seek_pos;
|
||||
StringName seek_pos;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_caption() const;
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
void set_seek_pos(float p_sec);
|
||||
float get_seek_pos() const;
|
||||
virtual String get_caption() const;
|
||||
|
||||
float process(float p_time, bool p_seek);
|
||||
|
||||
|
@ -241,13 +247,18 @@ class AnimationNodeTransition : public AnimationNode {
|
|||
InputData inputs[MAX_INPUTS];
|
||||
int enabled_inputs;
|
||||
|
||||
float prev_time;
|
||||
/*
|
||||
float prev_xfading;
|
||||
int prev;
|
||||
bool switched;
|
||||
|
||||
float time;
|
||||
int current;
|
||||
int prev_current; */
|
||||
|
||||
StringName prev_xfading;
|
||||
StringName prev;
|
||||
StringName time;
|
||||
StringName current;
|
||||
StringName prev_current;
|
||||
|
||||
float xfade;
|
||||
|
||||
|
@ -258,6 +269,9 @@ protected:
|
|||
void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
public:
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
virtual String get_caption() const;
|
||||
|
||||
void set_enabled_inputs(int p_inputs);
|
||||
|
@ -269,9 +283,6 @@ public:
|
|||
void set_input_caption(int p_input, const String &p_name);
|
||||
String get_input_caption(int p_input) const;
|
||||
|
||||
void set_current(int p_current);
|
||||
int get_current() const;
|
||||
|
||||
void set_cross_fade_time(float p_fade);
|
||||
float get_cross_fade_time() const;
|
||||
|
||||
|
@ -293,10 +304,19 @@ public:
|
|||
class AnimationNodeBlendTree : public AnimationRootNode {
|
||||
GDCLASS(AnimationNodeBlendTree, AnimationRootNode)
|
||||
|
||||
Map<StringName, Ref<AnimationNode> > nodes;
|
||||
struct Node {
|
||||
Ref<AnimationNode> node;
|
||||
Vector2 position;
|
||||
Vector<StringName> connections;
|
||||
};
|
||||
|
||||
Map<StringName, Node> nodes;
|
||||
|
||||
Vector2 graph_offset;
|
||||
|
||||
void _tree_changed();
|
||||
void _node_changed(const StringName &p_node);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
|
@ -314,12 +334,18 @@ public:
|
|||
//no need to check for cycles due to tree topology
|
||||
};
|
||||
|
||||
void add_node(const StringName &p_name, Ref<AnimationNode> p_node);
|
||||
void add_node(const StringName &p_name, Ref<AnimationNode> p_node, const Vector2 &p_position = Vector2());
|
||||
Ref<AnimationNode> get_node(const StringName &p_name) const;
|
||||
void remove_node(const StringName &p_name);
|
||||
void rename_node(const StringName &p_name, const StringName &p_new_name);
|
||||
bool has_node(const StringName &p_name) const;
|
||||
StringName get_node_name(const Ref<AnimationNode> &p_node) const;
|
||||
Vector<StringName> get_node_connection_array(const StringName &p_name) const;
|
||||
|
||||
void set_node_position(const StringName &p_node, const Vector2 &p_position);
|
||||
Vector2 get_node_position(const StringName &p_node) const;
|
||||
|
||||
virtual void get_child_nodes(List<ChildNode> *r_child_nodes);
|
||||
|
||||
void connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node);
|
||||
void disconnect_node(const StringName &p_node, int p_input_index);
|
||||
|
@ -342,7 +368,8 @@ public:
|
|||
void set_graph_offset(const Vector2 &p_graph_offset);
|
||||
Vector2 get_graph_offset() const;
|
||||
|
||||
virtual void set_tree(AnimationTree *p_player);
|
||||
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name);
|
||||
|
||||
AnimationNodeBlendTree();
|
||||
~AnimationNodeBlendTree();
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,6 +15,8 @@ public:
|
|||
private:
|
||||
SwitchMode switch_mode;
|
||||
bool auto_advance;
|
||||
StringName advance_condition;
|
||||
StringName advance_condition_name;
|
||||
float xfade;
|
||||
bool disabled;
|
||||
int priority;
|
||||
|
@ -29,6 +31,11 @@ public:
|
|||
void set_auto_advance(bool p_enable);
|
||||
bool has_auto_advance() const;
|
||||
|
||||
void set_advance_condition(const StringName &p_condition);
|
||||
StringName get_advance_condition() const;
|
||||
|
||||
StringName get_advance_condition_name() const;
|
||||
|
||||
void set_xfade_time(float p_xfade);
|
||||
float get_xfade_time() const;
|
||||
|
||||
|
@ -43,39 +50,24 @@ public:
|
|||
|
||||
VARIANT_ENUM_CAST(AnimationNodeStateMachineTransition::SwitchMode)
|
||||
|
||||
class AnimationNodeStateMachine : public AnimationRootNode {
|
||||
class AnimationNodeStateMachine;
|
||||
|
||||
GDCLASS(AnimationNodeStateMachine, AnimationRootNode);
|
||||
class AnimationNodeStateMachinePlayback : public Resource {
|
||||
GDCLASS(AnimationNodeStateMachinePlayback, Resource);
|
||||
|
||||
private:
|
||||
Map<StringName, Ref<AnimationRootNode> > states;
|
||||
|
||||
struct Transition {
|
||||
|
||||
StringName from;
|
||||
StringName to;
|
||||
Ref<AnimationNodeStateMachineTransition> transition;
|
||||
};
|
||||
friend class AnimationNodeStateMachine;
|
||||
|
||||
struct AStarCost {
|
||||
float distance;
|
||||
StringName prev;
|
||||
};
|
||||
|
||||
Vector<Transition> transitions;
|
||||
|
||||
float len_total;
|
||||
|
||||
float len_current;
|
||||
float pos_current;
|
||||
int loops_current;
|
||||
|
||||
bool play_start;
|
||||
StringName start_node;
|
||||
StringName end_node;
|
||||
|
||||
Vector2 graph_offset;
|
||||
|
||||
StringName current;
|
||||
|
||||
StringName fading_from;
|
||||
|
@ -85,6 +77,63 @@ private:
|
|||
Vector<StringName> path;
|
||||
bool playing;
|
||||
|
||||
StringName start_request;
|
||||
bool start_request_travel;
|
||||
bool stop_request;
|
||||
|
||||
bool _travel(AnimationNodeStateMachine *p_state_machine, const StringName &p_travel);
|
||||
|
||||
float process(AnimationNodeStateMachine *p_state_machine, float p_time, bool p_seek);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void travel(const StringName &p_state);
|
||||
void start(const StringName &p_state);
|
||||
void stop();
|
||||
bool is_playing() const;
|
||||
StringName get_current_node() const;
|
||||
StringName get_blend_from_node() const;
|
||||
Vector<StringName> get_travel_path() const;
|
||||
float get_current_play_pos() const;
|
||||
float get_current_length() const;
|
||||
|
||||
AnimationNodeStateMachinePlayback();
|
||||
};
|
||||
|
||||
class AnimationNodeStateMachine : public AnimationRootNode {
|
||||
|
||||
GDCLASS(AnimationNodeStateMachine, AnimationRootNode);
|
||||
|
||||
private:
|
||||
friend class AnimationNodeStateMachinePlayback;
|
||||
|
||||
struct State {
|
||||
Ref<AnimationRootNode> node;
|
||||
Vector2 position;
|
||||
};
|
||||
|
||||
Map<StringName, State> states;
|
||||
|
||||
struct Transition {
|
||||
|
||||
StringName from;
|
||||
StringName to;
|
||||
Ref<AnimationNodeStateMachineTransition> transition;
|
||||
};
|
||||
|
||||
Vector<Transition> transitions;
|
||||
|
||||
StringName playback;
|
||||
|
||||
StringName start_node;
|
||||
StringName end_node;
|
||||
|
||||
Vector2 graph_offset;
|
||||
|
||||
void _tree_changed();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
@ -94,7 +143,10 @@ protected:
|
|||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
void add_node(const StringName &p_name, Ref<AnimationNode> p_node);
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
void add_node(const StringName &p_name, Ref<AnimationNode> p_node, const Vector2 &p_position = Vector2());
|
||||
Ref<AnimationNode> get_node(const StringName &p_name) const;
|
||||
void remove_node(const StringName &p_name);
|
||||
void rename_node(const StringName &p_name, const StringName &p_new_name);
|
||||
|
@ -102,6 +154,11 @@ public:
|
|||
StringName get_node_name(const Ref<AnimationNode> &p_node) const;
|
||||
void get_node_list(List<StringName> *r_nodes) const;
|
||||
|
||||
void set_node_position(const StringName &p_name, const Vector2 &p_position);
|
||||
Vector2 get_node_position(const StringName &p_name) const;
|
||||
|
||||
virtual void get_child_nodes(List<ChildNode> *r_child_nodes);
|
||||
|
||||
bool has_transition(const StringName &p_from, const StringName &p_to) const;
|
||||
int find_transition(const StringName &p_from, const StringName &p_to) const;
|
||||
void add_transition(const StringName &p_from, const StringName &p_to, const Ref<AnimationNodeStateMachineTransition> &p_transition);
|
||||
|
@ -124,17 +181,7 @@ public:
|
|||
virtual float process(float p_time, bool p_seek);
|
||||
virtual String get_caption() const;
|
||||
|
||||
bool travel(const StringName &p_state);
|
||||
void start(const StringName &p_state);
|
||||
void stop();
|
||||
bool is_playing() const;
|
||||
StringName get_current_node() const;
|
||||
StringName get_blend_from_node() const;
|
||||
Vector<StringName> get_travel_path() const;
|
||||
float get_current_play_pos() const;
|
||||
float get_current_length() const;
|
||||
|
||||
virtual void set_tree(AnimationTree *p_player);
|
||||
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name);
|
||||
|
||||
AnimationNodeStateMachine();
|
||||
};
|
||||
|
|
|
@ -5,6 +5,38 @@
|
|||
#include "scene/scene_string_names.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
|
||||
|
||||
|
||||
void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
|
||||
}
|
||||
|
||||
Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter) const {
|
||||
return Variant();
|
||||
}
|
||||
|
||||
void AnimationNode::set_parameter(const StringName& p_name, const Variant& p_value) {
|
||||
ERR_FAIL_COND(!state);
|
||||
ERR_FAIL_COND(!state->tree->property_parent_map.has(base_path));
|
||||
ERR_FAIL_COND(!state->tree->property_parent_map[base_path].has(p_name));
|
||||
StringName path = state->tree->property_parent_map[base_path][p_name];
|
||||
|
||||
state->tree->property_map[path]=p_value;
|
||||
}
|
||||
|
||||
Variant AnimationNode::get_parameter(const StringName& p_name) const {
|
||||
ERR_FAIL_COND_V(!state,Variant());
|
||||
ERR_FAIL_COND_V(!state->tree->property_parent_map.has(base_path),Variant());
|
||||
ERR_FAIL_COND_V(!state->tree->property_parent_map[base_path].has(p_name),Variant());
|
||||
|
||||
StringName path = state->tree->property_parent_map[base_path][p_name];
|
||||
return state->tree->property_map[path];
|
||||
}
|
||||
|
||||
void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
|
||||
|
||||
}
|
||||
|
||||
void AnimationNode::blend_animation(const StringName &p_animation, float p_time, float p_delta, bool p_seeked, float p_blend) {
|
||||
|
||||
ERR_FAIL_COND(!state);
|
||||
|
@ -14,8 +46,8 @@ void AnimationNode::blend_animation(const StringName &p_animation, float p_time,
|
|||
|
||||
if (animation.is_null()) {
|
||||
|
||||
Ref<AnimationNodeBlendTree> btree = get_parent();
|
||||
if (btree.is_valid()) {
|
||||
AnimationNodeBlendTree* btree = Object::cast_to<AnimationNodeBlendTree>(parent);
|
||||
if (btree) {
|
||||
String name = btree->get_node_name(Ref<AnimationNodeAnimation>(this));
|
||||
make_invalid(vformat(RTR("In node '%s', invalid animation: '%s'."), name, p_animation));
|
||||
} else {
|
||||
|
@ -37,10 +69,20 @@ void AnimationNode::blend_animation(const StringName &p_animation, float p_time,
|
|||
state->animation_states.push_back(anim_state);
|
||||
}
|
||||
|
||||
float AnimationNode::_pre_process(State *p_state, float p_time, bool p_seek) {
|
||||
float AnimationNode::_pre_process(const StringName& p_base_path, AnimationNode *p_parent, State *p_state, float p_time, bool p_seek, const Vector<StringName>& p_connections) {
|
||||
|
||||
base_path = p_base_path;
|
||||
parent = p_parent;
|
||||
connections=p_connections;
|
||||
state = p_state;
|
||||
|
||||
float t = process(p_time, p_seek);
|
||||
|
||||
state = NULL;
|
||||
parent = NULL;
|
||||
base_path = StringName();
|
||||
connections.clear();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -56,39 +98,31 @@ void AnimationNode::make_invalid(const String &p_reason) {
|
|||
float AnimationNode::blend_input(int p_input, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
|
||||
ERR_FAIL_INDEX_V(p_input, inputs.size(), 0);
|
||||
ERR_FAIL_COND_V(!state, 0);
|
||||
ERR_FAIL_COND_V(!get_tree(), 0); //should not happen, but used to catch bugs
|
||||
|
||||
Ref<AnimationNodeBlendTree> tree = get_parent();
|
||||
AnimationNodeBlendTree* blend_tree = Object::cast_to<AnimationNodeBlendTree>(parent);
|
||||
ERR_FAIL_COND_V(!blend_tree,0);
|
||||
|
||||
if (!tree.is_valid() && get_tree()->get_tree_root().ptr() != this) {
|
||||
make_invalid(RTR("Can't blend input because node is not in a tree"));
|
||||
return 0;
|
||||
}
|
||||
StringName node_name = connections[p_input];
|
||||
|
||||
ERR_FAIL_COND_V(!tree.is_valid(), 0); //should not happen
|
||||
|
||||
StringName anim_name = inputs[p_input].connected_to;
|
||||
|
||||
Ref<AnimationNode> node = tree->get_node(anim_name);
|
||||
|
||||
if (node.is_null()) {
|
||||
|
||||
String name = tree->get_node_name(Ref<AnimationNodeAnimation>(this));
|
||||
if (!blend_tree->has_node(node_name)) {
|
||||
String name = blend_tree->get_node_name(Ref<AnimationNode>(this));
|
||||
make_invalid(vformat(RTR("Nothing connected to input '%s' of node '%s'."), get_input_name(p_input), name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
inputs.write[p_input].last_pass = state->last_pass;
|
||||
Ref<AnimationNode> node = blend_tree->get_node(node_name);
|
||||
|
||||
return _blend_node(node, p_time, p_seek, p_blend, p_filter, p_optimize, &inputs.write[p_input].activity);
|
||||
//inputs.write[p_input].last_pass = state->last_pass;
|
||||
float activity;
|
||||
return _blend_node(node_name,blend_tree->get_node_connection_array(node_name),NULL,node, p_time, p_seek, p_blend, p_filter, p_optimize, &activity);
|
||||
}
|
||||
|
||||
float AnimationNode::blend_node(Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
|
||||
float AnimationNode::blend_node(const StringName& p_sub_path,Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
|
||||
|
||||
return _blend_node(p_node, p_time, p_seek, p_blend, p_filter, p_optimize);
|
||||
return _blend_node(p_sub_path,Vector<StringName>(),this,p_node, p_time, p_seek, p_blend, p_filter, p_optimize);
|
||||
}
|
||||
|
||||
float AnimationNode::_blend_node(Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize, float *r_max) {
|
||||
float AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName>& p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize, float *r_max) {
|
||||
|
||||
ERR_FAIL_COND_V(!p_node.is_valid(), 0);
|
||||
ERR_FAIL_COND_V(!state, 0);
|
||||
|
@ -189,7 +223,19 @@ float AnimationNode::_blend_node(Ref<AnimationNode> p_node, float p_time, bool p
|
|||
if (!p_seek && p_optimize && !any_valid) //pointless to go on, all are zero
|
||||
return 0;
|
||||
|
||||
return p_node->_pre_process(state, p_time, p_seek);
|
||||
String new_path;
|
||||
AnimationNode *new_parent;
|
||||
|
||||
//this is the slowest part of processing, but as strings process in powers of 2, and the paths always exist, it will not result in that many allocations
|
||||
if (p_new_parent) {
|
||||
new_parent = p_new_parent;
|
||||
new_path = String(base_path)+String(p_subpath)+"/";
|
||||
} else {
|
||||
ERR_FAIL_COND_V(!parent,0);
|
||||
new_parent = parent;
|
||||
new_path = String(parent->base_path) + String(p_subpath)+"/";
|
||||
}
|
||||
return p_node->_pre_process(new_path,new_parent,state, p_time, p_seek, p_connections);
|
||||
}
|
||||
|
||||
int AnimationNode::get_input_count() const {
|
||||
|
@ -201,28 +247,6 @@ String AnimationNode::get_input_name(int p_input) {
|
|||
return inputs[p_input].name;
|
||||
}
|
||||
|
||||
float AnimationNode::get_input_activity(int p_input) const {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_input, inputs.size(), 0);
|
||||
if (!get_tree())
|
||||
return 0;
|
||||
|
||||
if (get_tree()->get_last_process_pass() != inputs[p_input].last_pass) {
|
||||
return 0;
|
||||
}
|
||||
return inputs[p_input].activity;
|
||||
}
|
||||
StringName AnimationNode::get_input_connection(int p_input) {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_input, inputs.size(), StringName());
|
||||
return inputs[p_input].connected_to;
|
||||
}
|
||||
|
||||
void AnimationNode::set_input_connection(int p_input, const StringName &p_connection) {
|
||||
|
||||
ERR_FAIL_INDEX(p_input, inputs.size());
|
||||
inputs.write[p_input].connected_to = p_connection;
|
||||
}
|
||||
|
||||
String AnimationNode::get_caption() const {
|
||||
|
||||
|
@ -239,8 +263,6 @@ void AnimationNode::add_input(const String &p_name) {
|
|||
Input input;
|
||||
ERR_FAIL_COND(p_name.find(".") != -1 || p_name.find("/") != -1);
|
||||
input.name = p_name;
|
||||
input.activity = 0;
|
||||
input.last_pass = 0;
|
||||
inputs.push_back(input);
|
||||
emit_changed();
|
||||
}
|
||||
|
@ -258,35 +280,6 @@ void AnimationNode::remove_input(int p_index) {
|
|||
emit_changed();
|
||||
}
|
||||
|
||||
void AnimationNode::_set_parent(Object *p_parent) {
|
||||
set_parent(Object::cast_to<AnimationNode>(p_parent));
|
||||
}
|
||||
|
||||
void AnimationNode::set_parent(AnimationNode *p_parent) {
|
||||
parent = p_parent; //do not use ref because parent contains children
|
||||
if (get_script_instance()) {
|
||||
get_script_instance()->call("_parent_set", p_parent);
|
||||
}
|
||||
}
|
||||
|
||||
Ref<AnimationNode> AnimationNode::get_parent() const {
|
||||
if (parent) {
|
||||
return Ref<AnimationNode>(parent);
|
||||
}
|
||||
|
||||
return Ref<AnimationNode>();
|
||||
}
|
||||
|
||||
AnimationTree *AnimationNode::get_tree() const {
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
AnimationPlayer *AnimationNode::get_player() const {
|
||||
ERR_FAIL_COND_V(!state, NULL);
|
||||
return state->player;
|
||||
}
|
||||
|
||||
float AnimationNode::process(float p_time, bool p_seek) {
|
||||
|
||||
if (get_script_instance()) {
|
||||
|
@ -320,21 +313,7 @@ bool AnimationNode::has_filter() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void AnimationNode::set_position(const Vector2 &p_position) {
|
||||
position = p_position;
|
||||
}
|
||||
|
||||
Vector2 AnimationNode::get_position() const {
|
||||
return position;
|
||||
}
|
||||
|
||||
void AnimationNode::set_tree(AnimationTree *p_player) {
|
||||
|
||||
if (player != NULL && p_player == NULL) {
|
||||
emit_signal("removed_from_graph");
|
||||
}
|
||||
player = p_player;
|
||||
}
|
||||
|
||||
Array AnimationNode::_get_filters() const {
|
||||
|
||||
|
@ -361,12 +340,14 @@ void AnimationNode::_validate_property(PropertyInfo &property) const {
|
|||
}
|
||||
}
|
||||
|
||||
Ref<AnimationNode> AnimationNode::get_child_by_name(const StringName &p_name) {
|
||||
return Ref<AnimationNode>();
|
||||
}
|
||||
|
||||
void AnimationNode::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_input_count"), &AnimationNode::get_input_count);
|
||||
ClassDB::bind_method(D_METHOD("get_input_name", "input"), &AnimationNode::get_input_name);
|
||||
ClassDB::bind_method(D_METHOD("get_input_connection", "input"), &AnimationNode::get_input_connection);
|
||||
ClassDB::bind_method(D_METHOD("get_input_activity", "input"), &AnimationNode::get_input_activity);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_input", "name"), &AnimationNode::add_input);
|
||||
ClassDB::bind_method(D_METHOD("remove_input", "index"), &AnimationNode::remove_input);
|
||||
|
@ -377,19 +358,16 @@ void AnimationNode::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_filter_enabled", "enable"), &AnimationNode::set_filter_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_filter_enabled"), &AnimationNode::is_filter_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_position", "position"), &AnimationNode::set_position);
|
||||
ClassDB::bind_method(D_METHOD("get_position"), &AnimationNode::get_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_set_filters", "filters"), &AnimationNode::_set_filters);
|
||||
ClassDB::bind_method(D_METHOD("_get_filters"), &AnimationNode::_get_filters);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "blend"), &AnimationNode::blend_animation);
|
||||
ClassDB::bind_method(D_METHOD("blend_node", "node", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("blend_node", "name","node", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_parent", "parent"), &AnimationNode::_set_parent);
|
||||
ClassDB::bind_method(D_METHOD("get_parent"), &AnimationNode::get_parent);
|
||||
ClassDB::bind_method(D_METHOD("get_tree"), &AnimationNode::get_tree);
|
||||
ClassDB::bind_method(D_METHOD("set_parameter","name","value"), &AnimationNode::set_parameter);
|
||||
ClassDB::bind_method(D_METHOD("get_parameter","name"), &AnimationNode::get_parameter);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_filter_enabled", "is_filter_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "filters", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_filters", "_get_filters");
|
||||
|
@ -397,9 +375,11 @@ void AnimationNode::_bind_methods() {
|
|||
BIND_VMETHOD(MethodInfo("process", PropertyInfo(Variant::REAL, "time"), PropertyInfo(Variant::BOOL, "seek")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::STRING, "get_caption"));
|
||||
BIND_VMETHOD(MethodInfo(Variant::STRING, "has_filter"));
|
||||
BIND_VMETHOD(MethodInfo("_parent_set", PropertyInfo(Variant::OBJECT, "parent")));
|
||||
|
||||
ADD_SIGNAL(MethodInfo("removed_from_graph"));
|
||||
|
||||
ADD_SIGNAL(MethodInfo("tree_changed"));
|
||||
|
||||
BIND_ENUM_CONSTANT(FILTER_IGNORE);
|
||||
BIND_ENUM_CONSTANT(FILTER_PASS);
|
||||
BIND_ENUM_CONSTANT(FILTER_STOP);
|
||||
|
@ -410,8 +390,6 @@ AnimationNode::AnimationNode() {
|
|||
|
||||
state = NULL;
|
||||
parent = NULL;
|
||||
player = NULL;
|
||||
set_local_to_scene(true);
|
||||
filter_enabled = false;
|
||||
}
|
||||
|
||||
|
@ -420,18 +398,17 @@ AnimationNode::AnimationNode() {
|
|||
void AnimationTree::set_tree_root(const Ref<AnimationNode> &p_root) {
|
||||
|
||||
if (root.is_valid()) {
|
||||
root->set_tree(NULL);
|
||||
}
|
||||
if (p_root.is_valid()) {
|
||||
ERR_EXPLAIN("root node already set to another player");
|
||||
ERR_FAIL_COND(p_root->player);
|
||||
root->disconnect("tree_changed",this,"_tree_changed");
|
||||
}
|
||||
|
||||
root = p_root;
|
||||
|
||||
if (root.is_valid()) {
|
||||
root->set_tree(this);
|
||||
root->connect("tree_changed",this,"_tree_changed");
|
||||
}
|
||||
|
||||
properties_dirty=true;
|
||||
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
|
@ -699,7 +676,10 @@ void AnimationTree::_clear_caches() {
|
|||
|
||||
void AnimationTree::_process_graph(float p_delta) {
|
||||
|
||||
_update_properties(); //if properties need updating, update them
|
||||
|
||||
//check all tracks, see if they need modification
|
||||
|
||||
root_motion_transform = Transform();
|
||||
|
||||
if (!root.is_valid()) {
|
||||
|
@ -741,6 +721,7 @@ void AnimationTree::_process_graph(float p_delta) {
|
|||
state.valid = true;
|
||||
state.player = player;
|
||||
state.last_pass = process_pass;
|
||||
state.tree = this;
|
||||
|
||||
// root source blends
|
||||
|
||||
|
@ -757,11 +738,11 @@ void AnimationTree::_process_graph(float p_delta) {
|
|||
|
||||
if (started) {
|
||||
//if started, seek
|
||||
root->_pre_process(&state, 0, true);
|
||||
root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path,NULL,&state, 0, true,Vector<StringName>());
|
||||
started = false;
|
||||
}
|
||||
|
||||
root->_pre_process(&state, p_delta, false);
|
||||
root->_pre_process(SceneStringNames::get_singleton()->parameters_base_path,NULL,&state, p_delta, false,Vector<StringName>());
|
||||
}
|
||||
|
||||
if (!state.valid) {
|
||||
|
@ -1297,6 +1278,117 @@ Transform AnimationTree::get_root_motion_transform() const {
|
|||
return root_motion_transform;
|
||||
}
|
||||
|
||||
void AnimationTree::_tree_changed() {
|
||||
if (properties_dirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
call_deferred("_update_properties");
|
||||
properties_dirty=true;
|
||||
}
|
||||
|
||||
void AnimationTree::_update_properties_for_node(const String& p_base_path,Ref<AnimationNode> node) {
|
||||
|
||||
if (!property_parent_map.has(p_base_path)) {
|
||||
property_parent_map[p_base_path]=HashMap<StringName, StringName>();
|
||||
}
|
||||
|
||||
List<PropertyInfo> plist;
|
||||
node->get_parameter_list(&plist);
|
||||
for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
|
||||
PropertyInfo pinfo = E->get();
|
||||
|
||||
StringName key = pinfo.name;
|
||||
|
||||
if (!property_map.has(p_base_path +key)) {
|
||||
property_map[p_base_path + key] = node->get_parameter_default_value(key);
|
||||
}
|
||||
|
||||
property_parent_map[p_base_path][key]=p_base_path+key;
|
||||
|
||||
pinfo.name = p_base_path + key;
|
||||
properties.push_back(pinfo);
|
||||
}
|
||||
|
||||
List<AnimationNode::ChildNode> children;
|
||||
node->get_child_nodes(&children);
|
||||
|
||||
for (List<AnimationNode::ChildNode>::Element *E=children.front();E;E=E->next()) {
|
||||
_update_properties_for_node(p_base_path+E->get().name+"/",E->get().node);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationTree::_update_properties() {
|
||||
if (!properties_dirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
properties.clear();
|
||||
property_parent_map.clear();
|
||||
|
||||
if (root.is_valid()) {
|
||||
_update_properties_for_node(SceneStringNames::get_singleton()->parameters_base_path,root);
|
||||
}
|
||||
|
||||
properties_dirty = false;
|
||||
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
bool AnimationTree::_set(const StringName &p_name, const Variant &p_value) {
|
||||
if (properties_dirty) {
|
||||
_update_properties();
|
||||
}
|
||||
|
||||
if (property_map.has(p_name)) {
|
||||
property_map[p_name]=p_value;
|
||||
#ifdef TOOLS_ENABLED
|
||||
_change_notify(p_name.operator String().utf8().get_data());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AnimationTree::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
if (properties_dirty) {
|
||||
const_cast<AnimationTree*>(this)->_update_properties();
|
||||
}
|
||||
|
||||
if (property_map.has(p_name)) {
|
||||
r_ret=property_map[p_name];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
void AnimationTree::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
if (properties_dirty) {
|
||||
const_cast<AnimationTree*>(this)->_update_properties();
|
||||
}
|
||||
|
||||
for (const List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
|
||||
p_list->push_back(E->get());
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationTree::rename_parameter(const String& p_base,const String& p_new_base) {
|
||||
|
||||
//rename values first
|
||||
for (const List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
|
||||
if (E->get().name.begins_with(p_base)) {
|
||||
String new_name = E->get().name.replace_first(p_base,p_new_base);
|
||||
property_map[new_name]=property_map[E->get().name];
|
||||
}
|
||||
}
|
||||
|
||||
//update tree second
|
||||
properties_dirty=true;
|
||||
_update_properties();
|
||||
}
|
||||
|
||||
void AnimationTree::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_active", "active"), &AnimationTree::set_active);
|
||||
ClassDB::bind_method(D_METHOD("is_active"), &AnimationTree::is_active);
|
||||
|
@ -1315,11 +1407,17 @@ void AnimationTree::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("get_root_motion_transform"), &AnimationTree::get_root_motion_transform);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationTree::_tree_changed);
|
||||
ClassDB::bind_method(D_METHOD("_update_properties"), &AnimationTree::_update_properties);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("rename_parameter","old_name","new_name"), &AnimationTree::rename_parameter);
|
||||
|
||||
|
||||
ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationTree::advance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_node_removed"), &AnimationTree::_node_removed);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tree_root", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_tree_root", "get_tree_root");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tree_root", PROPERTY_HINT_RESOURCE_TYPE, "AnimationRootNode"), "set_tree_root", "get_tree_root");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "anim_player", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationPlayer"), "set_animation_player", "get_animation_player");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_process_mode", "get_process_mode");
|
||||
|
@ -1338,10 +1436,9 @@ AnimationTree::AnimationTree() {
|
|||
cache_valid = false;
|
||||
setup_pass = 1;
|
||||
started = true;
|
||||
properties_dirty = true;
|
||||
}
|
||||
|
||||
AnimationTree::~AnimationTree() {
|
||||
if (root.is_valid()) {
|
||||
root->player = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,9 +23,6 @@ public:
|
|||
struct Input {
|
||||
|
||||
String name;
|
||||
StringName connected_to;
|
||||
float activity;
|
||||
uint64_t last_pass;
|
||||
};
|
||||
|
||||
Vector<Input> inputs;
|
||||
|
@ -51,30 +48,33 @@ public:
|
|||
List<AnimationState> animation_states;
|
||||
bool valid;
|
||||
AnimationPlayer *player;
|
||||
AnimationTree *tree;
|
||||
String invalid_reasons;
|
||||
uint64_t last_pass;
|
||||
};
|
||||
|
||||
Vector<float> blends;
|
||||
State *state;
|
||||
float _pre_process(State *p_state, float p_time, bool p_seek);
|
||||
String path;
|
||||
float _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, float p_time, bool p_seek, const Vector<StringName> &p_connections);
|
||||
void _pre_update_animations(HashMap<NodePath, int> *track_map);
|
||||
Vector2 position;
|
||||
|
||||
//all this is temporary
|
||||
StringName base_path;
|
||||
Vector<StringName> connections;
|
||||
AnimationNode *parent;
|
||||
AnimationTree *player;
|
||||
|
||||
float _blend_node(Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, float *r_max = NULL);
|
||||
|
||||
HashMap<NodePath, bool> filter;
|
||||
bool filter_enabled;
|
||||
|
||||
Array _get_filters() const;
|
||||
void _set_filters(const Array &p_filters);
|
||||
friend class AnimationNodeBlendTree;
|
||||
float _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, float *r_max = NULL);
|
||||
|
||||
protected:
|
||||
void blend_animation(const StringName &p_animation, float p_time, float p_delta, bool p_seeked, float p_blend);
|
||||
float blend_node(Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
|
||||
float blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
|
||||
float blend_input(int p_input, float p_time, bool p_seek, float p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
|
||||
void make_invalid(const String &p_reason);
|
||||
|
||||
|
@ -85,20 +85,24 @@ protected:
|
|||
void _set_parent(Object *p_parent);
|
||||
|
||||
public:
|
||||
void set_parent(AnimationNode *p_parent);
|
||||
Ref<AnimationNode> get_parent() const;
|
||||
virtual void set_tree(AnimationTree *p_player);
|
||||
AnimationTree *get_tree() const;
|
||||
AnimationPlayer *get_player() const;
|
||||
virtual void get_parameter_list(List<PropertyInfo> *r_list) const;
|
||||
virtual Variant get_parameter_default_value(const StringName &p_parameter) const;
|
||||
|
||||
void set_parameter(const StringName &p_name, const Variant &p_value);
|
||||
Variant get_parameter(const StringName &p_name) const;
|
||||
|
||||
struct ChildNode {
|
||||
StringName name;
|
||||
Ref<AnimationNode> node;
|
||||
};
|
||||
|
||||
virtual void get_child_nodes(List<ChildNode> *r_child_nodes);
|
||||
|
||||
virtual float process(float p_time, bool p_seek);
|
||||
virtual String get_caption() const;
|
||||
|
||||
int get_input_count() const;
|
||||
String get_input_name(int p_input);
|
||||
StringName get_input_connection(int p_input);
|
||||
void set_input_connection(int p_input, const StringName &p_connection);
|
||||
float get_input_activity(int p_input) const;
|
||||
|
||||
void add_input(const String &p_name);
|
||||
void set_input_name(int p_input, const String &p_name);
|
||||
|
@ -112,8 +116,7 @@ public:
|
|||
|
||||
virtual bool has_filter() const;
|
||||
|
||||
void set_position(const Vector2 &p_position);
|
||||
Vector2 get_position() const;
|
||||
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name);
|
||||
|
||||
AnimationNode();
|
||||
};
|
||||
|
@ -245,7 +248,21 @@ private:
|
|||
NodePath root_motion_track;
|
||||
Transform root_motion_transform;
|
||||
|
||||
friend class AnimationNode;
|
||||
bool properties_dirty;
|
||||
void _tree_changed();
|
||||
void _update_properties();
|
||||
List<PropertyInfo> properties;
|
||||
HashMap<StringName, HashMap<StringName, StringName> > property_parent_map;
|
||||
HashMap<StringName, Variant> property_map;
|
||||
|
||||
void _update_properties_for_node(const String &p_base_path, Ref<AnimationNode> node);
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -274,6 +291,8 @@ public:
|
|||
|
||||
void advance(float p_time);
|
||||
|
||||
void rename_parameter(const String &p_base, const String &p_new_base);
|
||||
|
||||
uint64_t get_last_process_pass() const;
|
||||
AnimationTree();
|
||||
~AnimationTree();
|
||||
|
|
|
@ -356,14 +356,14 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
|
|||
for (int j = 0; j < gn->get_connection_output_count(); j++) {
|
||||
|
||||
Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
|
||||
if (create_hot_zone(pos).has_point(p_point))
|
||||
if (is_in_hot_zone(pos, p_point))
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int j = 0; j < gn->get_connection_input_count(); j++) {
|
||||
|
||||
Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
|
||||
if (create_hot_zone(pos).has_point(p_point)) {
|
||||
if (is_in_hot_zone(pos, p_point)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
for (int j = 0; j < gn->get_connection_output_count(); j++) {
|
||||
|
||||
Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
|
||||
if (create_hot_zone(pos).has_point(mpos)) {
|
||||
if (is_in_hot_zone(pos, mpos)) {
|
||||
|
||||
if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) {
|
||||
//check disconnect
|
||||
|
@ -435,7 +435,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
for (int j = 0; j < gn->get_connection_input_count(); j++) {
|
||||
|
||||
Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
|
||||
if (create_hot_zone(pos).has_point(mpos)) {
|
||||
if (is_in_hot_zone(pos, mpos)) {
|
||||
|
||||
if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) {
|
||||
//check disconnect
|
||||
|
@ -502,7 +502,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
|
||||
Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
|
||||
int type = gn->get_connection_output_type(j);
|
||||
if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && create_hot_zone(pos).has_point(mpos)) {
|
||||
if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_hot_zone(pos, mpos)) {
|
||||
|
||||
connecting_target = true;
|
||||
connecting_to = pos;
|
||||
|
@ -517,7 +517,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
|
||||
Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
|
||||
int type = gn->get_connection_input_type(j);
|
||||
if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && create_hot_zone(pos).has_point(mpos)) {
|
||||
if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_hot_zone(pos, mpos)) {
|
||||
connecting_target = true;
|
||||
connecting_to = pos;
|
||||
connecting_target_to = gn->get_name();
|
||||
|
@ -557,8 +557,55 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
|||
}
|
||||
}
|
||||
|
||||
Rect2 GraphEdit::create_hot_zone(const Vector2 &pos) {
|
||||
return Rect2(pos.x - port_grab_distance_horizontal, pos.y - port_grab_distance_vertical, port_grab_distance_horizontal * 2, port_grab_distance_vertical * 2);
|
||||
bool GraphEdit::_check_clickable_control(Control *p_control, const Vector2 &pos) {
|
||||
|
||||
if (p_control->is_set_as_toplevel() || !p_control->is_visible())
|
||||
return false;
|
||||
|
||||
if (!p_control->has_point(pos) || p_control->get_mouse_filter() == MOUSE_FILTER_IGNORE) {
|
||||
//test children
|
||||
for (int i = 0; i < p_control->get_child_count(); i++) {
|
||||
Control *subchild = Object::cast_to<Control>(p_control->get_child(i));
|
||||
if (!subchild)
|
||||
continue;
|
||||
if (_check_clickable_control(subchild, pos - subchild->get_position())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphEdit::is_in_hot_zone(const Vector2 &pos, const Vector2 &p_mouse_pos) {
|
||||
if (!Rect2(pos.x - port_grab_distance_horizontal, pos.y - port_grab_distance_vertical, port_grab_distance_horizontal * 2, port_grab_distance_vertical * 2).has_point(p_mouse_pos))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *child = Object::cast_to<Control>(get_child(i));
|
||||
if (!child)
|
||||
continue;
|
||||
Rect2 rect = child->get_rect();
|
||||
if (rect.has_point(p_mouse_pos)) {
|
||||
|
||||
//check sub-controls
|
||||
Vector2 subpos = p_mouse_pos - rect.position;
|
||||
|
||||
for (int j = 0; j < child->get_child_count(); j++) {
|
||||
Control *subchild = Object::cast_to<Control>(child->get_child(j));
|
||||
if (!subchild)
|
||||
continue;
|
||||
|
||||
if (_check_clickable_control(subchild, subpos - subchild->get_position())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Vector2>
|
||||
|
|
|
@ -131,7 +131,7 @@ private:
|
|||
GraphEditFilter *top_layer;
|
||||
void _top_layer_input(const Ref<InputEvent> &p_ev);
|
||||
|
||||
Rect2 create_hot_zone(const Vector2 &pos);
|
||||
bool is_in_hot_zone(const Vector2 &pos, const Vector2 &p_mouse_pos);
|
||||
|
||||
void _top_layer_draw();
|
||||
void _connections_layer_draw();
|
||||
|
@ -172,6 +172,8 @@ private:
|
|||
void _snap_toggled();
|
||||
void _snap_value_changed(double);
|
||||
|
||||
bool _check_clickable_control(Control *p_control, const Vector2 &pos);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
virtual void add_child_notify(Node *p_child);
|
||||
|
|
|
@ -412,6 +412,8 @@ void register_scene_types() {
|
|||
ClassDB::register_class<AnimationNodeBlendSpace1D>();
|
||||
ClassDB::register_class<AnimationNodeBlendSpace2D>();
|
||||
ClassDB::register_class<AnimationNodeStateMachine>();
|
||||
ClassDB::register_class<AnimationNodeStateMachinePlayback>();
|
||||
|
||||
ClassDB::register_class<AnimationNodeStateMachineTransition>();
|
||||
ClassDB::register_class<AnimationNodeOutput>();
|
||||
ClassDB::register_class<AnimationNodeOneShot>();
|
||||
|
|
|
@ -201,4 +201,6 @@ SceneStringNames::SceneStringNames() {
|
|||
}
|
||||
|
||||
_mesh_changed = StaticCString::create("_mesh_changed");
|
||||
|
||||
parameters_base_path = "parameters/";
|
||||
}
|
||||
|
|
|
@ -203,6 +203,8 @@ public:
|
|||
|
||||
StringName output;
|
||||
|
||||
StringName parameters_base_path;
|
||||
|
||||
enum {
|
||||
MAX_MATERIALS = 32
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue