diff options
-rw-r--r-- | doc/base/classes.xml | 43 | ||||
-rw-r--r-- | scene/animation/animation_tree_player.cpp | 90 | ||||
-rw-r--r-- | scene/animation/animation_tree_player.h | 8 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 54 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 3 | ||||
-rw-r--r-- | tools/editor/plugins/animation_tree_editor_plugin.cpp | 52 |
6 files changed, 195 insertions, 55 deletions
diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 7bc8c42592..68d5b3e071 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -3029,6 +3029,16 @@ <description> </description> </method> + <method name="animation_node_set_filter_path"> + <argument index="0" name="id" type="String"> + </argument> + <argument index="1" name="path" type="NodePath"> + </argument> + <argument index="2" name="enable" type="bool"> + </argument> + <description> + </description> + </method> <method name="oneshot_node_set_fadein_time"> <argument index="0" name="id" type="String"> </argument> @@ -27184,80 +27194,94 @@ This method controls whether the position between two cached points is interpola </class> <class name="Polygon2D" inherits="Node2D" category="Core"> <brief_description> + 2D polygon representation </brief_description> <description> + A Polygon2D is defined by a set of n points connected together by line segments, meaning that the point 1 will be connected with point 2, point 2 with point 3 ..., point n-1 with point n and point n with point 1 in order to close the loop and define a plane. </description> <methods> <method name="set_polygon"> <argument index="0" name="polygon" type="Vector2Array"> </argument> <description> + Defines the set of points that will represent the polygon. </description> </method> <method name="get_polygon" qualifiers="const"> <return type="Vector2Array"> </return> <description> + Returns the set of points that defines this polygon </description> </method> <method name="set_uv"> <argument index="0" name="uv" type="Vector2Array"> </argument> <description> + Sets the uv value for every point of the polygon </description> </method> <method name="get_uv" qualifiers="const"> <return type="Vector2Array"> </return> <description> + Returns the uv value associated with every point of the polygon </description> </method> <method name="set_color"> <argument index="0" name="color" type="Color"> </argument> <description> + Sets the polygon fill color, if the polygon has a texture defined, the defined texture will be tinted to the polygon fill color. </description> </method> <method name="get_color" qualifiers="const"> <return type="Color"> </return> <description> + Returns the polygon fill color </description> </method> <method name="set_texture"> <argument index="0" name="texture" type="Object"> </argument> <description> + Sets the polygon texture. </description> </method> <method name="get_texture" qualifiers="const"> <return type="Object"> </return> <description> + Returns the polygon texture </description> </method> <method name="set_texture_offset"> <argument index="0" name="texture_offset" type="Vector2"> </argument> <description> + Sets the offset of the polygon texture. Initially the texture will appear anchored to the polygon position, the offset is used to move the texture location away from that point (notice that the texture origin is set to its top left corner, so when offset is 0,0 the top left corner of the texture is at the polygon position), for example setting the offset to 10, 10 will move the texture 10 units to the left and 10 units to the top. </description> </method> <method name="get_texture_offset" qualifiers="const"> <return type="Vector2"> </return> <description> + Returns the polygon texture offset </description> </method> <method name="set_texture_rotation"> <argument index="0" name="texture_rotation" type="float"> </argument> <description> + Sets the amount of rotation of the polygon texture, [code]texture_rotation[/code] is specified in degrees and clockwise rotation, meaning that if the texture rotation is set to 45 degrees, the texture will be rotated 45 degrees clockwise along the polygon position plus the texture offset. </description> </method> <method name="get_texture_rotation" qualifiers="const"> <return type="float"> </return> <description> + Returns the rotation in degrees of the texture polygon </description> </method> <method name="set_texture_scale"> @@ -27276,12 +27300,14 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="invert" type="bool"> </argument> <description> + Sets the polygon as the defined polygon bounding box minus the defined polygon (the defined polygon will appear as a hole on square that contains the defined polygon). </description> </method> <method name="get_invert" qualifiers="const"> <return type="bool"> </return> <description> + Returns whether this polygon is inverted or not </description> </method> <method name="set_invert_border"> @@ -27300,12 +27326,14 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="offset" type="Vector2"> </argument> <description> + Sets the amount of distance from the polygon points from the polygon position, for example if the offset is set to 10,10 then all the polygon points will move 10 units to the right and 10 units to the bottom. </description> </method> <method name="get_offset" qualifiers="const"> <return type="Vector2"> </return> <description> + Returns the polygon points offset to the polygon position. </description> </method> </methods> @@ -28531,39 +28559,45 @@ This method controls whether the position between two cached points is interpola </class> <class name="RayCast2D" inherits="Node2D" category="Core"> <brief_description> + Query the closest object intersecting a ray </brief_description> <description> + A RayCast2D represents a line from its origin to its destination position [code]cast_to[/code], it is used to query the 2D space in order to find the closest object intersecting with the ray. </description> <methods> <method name="set_enabled"> <argument index="0" name="enabled" type="bool"> </argument> <description> + Enables the RayCast2D. Only enabled raycasts will be able to query the space and report collisions. </description> </method> <method name="is_enabled" qualifiers="const"> <return type="bool"> </return> <description> + Returns whether this raycast is enabled or not </description> </method> <method name="set_cast_to"> <argument index="0" name="local_point" type="Vector2"> </argument> <description> + Sets the ray destination point, so that the ray will test from the ray's origin to [code]local_point[/code] </description> </method> <method name="get_cast_to" qualifiers="const"> <return type="Vector2"> </return> <description> + Return the destination point of this ray object </description> </method> <method name="is_colliding" qualifiers="const"> <return type="bool"> </return> <description> - Return whether the closest object the ray is pointing to is colliding with the vector, with the vector length considered. + Return whether the closest object the ray is pointing to is colliding with the vector (considering the vector length). </description> </method> <method name="get_collider" qualifiers="const"> @@ -28577,18 +28611,21 @@ This method controls whether the position between two cached points is interpola <return type="int"> </return> <description> + Returns the collision shape of the closest object the ray is pointing to. </description> </method> <method name="get_collision_point" qualifiers="const"> <return type="Vector2"> </return> <description> + Returns the collision point in which the ray intersects the closest object. </description> </method> <method name="get_collision_normal" qualifiers="const"> <return type="Vector2"> </return> <description> + Returns the normal of the intersecting object shape face containing the collision point. </description> </method> <method name="add_exception_rid"> @@ -28601,6 +28638,7 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="node" type="Object"> </argument> <description> + Adds a collision exception so the ray does not report collisions with the specified [code]node[/code]. </description> </method> <method name="remove_exception_rid"> @@ -28613,10 +28651,12 @@ This method controls whether the position between two cached points is interpola <argument index="0" name="node" type="Object"> </argument> <description> + Removes a collision exception so the ray does report collisions with the specified [code]node[/code]. </description> </method> <method name="clear_exceptions"> <description> + Removes all collision exception for this ray. </description> </method> <method name="set_layer_mask"> @@ -28629,6 +28669,7 @@ This method controls whether the position between two cached points is interpola <return type="int"> </return> <description> + Returns the layer mask for this ray. </description> </method> <method name="set_type_mask"> diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index c732dd54cf..211c5961b0 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -139,6 +139,11 @@ bool AnimationTreePlayer::_set(const StringName& p_name, const Variant& p_value) animation_node_set_master_animation(id,node.get_valid("from")); else animation_node_set_animation(id,node.get_valid("animation")); + Array filters= node.get_valid("filter"); + for(int i=0;i<filters.size();i++) { + + animation_node_set_filter_path(id,filters[i],true); + } } break; case NODE_ONESHOT: { @@ -276,6 +281,15 @@ bool AnimationTreePlayer::_get(const StringName& p_name,Variant &r_ret) const { } else { node["animation"]=an->animation; } + Array k; + List<NodePath> keys; + an->filter.get_key_list(&keys); + k.resize(keys.size()); + int i=0; + for(List<NodePath>::Element *E=keys.front();E;E=E->next()) { + k[i++]=E->get(); + } + node["filter"]=k; } break; case NODE_ONESHOT: { OneShotNode *osn = static_cast<OneShotNode*>(n); @@ -439,7 +453,6 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode //transform to seconds... - switch(nb->type) { case NODE_OUTPUT: { @@ -464,7 +477,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode an->time=p_time; an->step=0; } else { - an->time+=p_time; + an->time=MAX(0,an->time+p_time); an->step=p_time; } @@ -482,14 +495,12 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode an->skip=true; for (List<AnimationNode::TrackRef>::Element *E=an->tref.front();E;E=E->next()) { - - if (p_filter && p_filter->has(an->animation->track_get_path(E->get().local_track))) { - - if (p_reverse_weight<0) - E->get().weight=0; - else - E->get().weight=p_reverse_weight; - + NodePath track_path = an->animation->track_get_path(E->get().local_track); + if (p_filter && p_filter->has(track_path)) { + E->get().weight = MAX(0, p_reverse_weight); + } else if(an->filter.has(track_path)) { + E->get().weight = 0; + E->get().track->skip = true; } else { E->get().weight=p_weight; } @@ -552,18 +563,17 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode float main_rem; float os_rem; + float os_reverse_weight = p_reverse_weight; if (!osn->filter.empty()) { - - main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek,&osn->filter,p_weight); - os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,os_seek,&osn->filter,-1); - - } else { - - main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek); - os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,os_seek); + p_filter = &osn->filter; + p_reverse_weight = p_weight; + os_reverse_weight = -1; } + main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek,p_filter,p_reverse_weight); + os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,os_seek,p_filter,os_reverse_weight); + if (osn->start) { osn->remaining=os_rem; osn->start=false; @@ -768,6 +778,8 @@ void AnimationTreePlayer::_process_animation(float p_delta) { t.value = t.object->get(t.property); t.value.zero(); + + t.skip = false; } @@ -816,16 +828,9 @@ void AnimationTreePlayer::_process_animation(float p_delta) { if (a->value_track_is_continuous(tr.local_track)) { Variant value = a->value_track_interpolate(tr.local_track,anim_list->time); Variant::blend(tr.track->value,value,blend,tr.track->value); - tr.track->object->set(tr.track->property,tr.track->value); } else { - - List<int> indices; - a->value_track_get_key_indices(tr.local_track,anim_list->time,anim_list->step,&indices); - for(List<int>::Element *E=indices.front();E;E=E->next()) { - - Variant value = a->track_get_key_value(tr.local_track,E->get()); - tr.track->object->set(tr.track->property,value); - } + int index = a->track_find_key(tr.local_track,anim_list->time); + tr.track->value = a->track_get_key_value(tr.local_track, index); } } break; case Animation::TYPE_METHOD: { ///< Call any method on a specific node. @@ -854,11 +859,13 @@ void AnimationTreePlayer::_process_animation(float p_delta) { Track &t = E->get(); - if (!t.object) + if (t.skip || !t.object) continue; - if(t.property) // value track; was applied in step 2 + if(t.property) { // value track + t.object->set(t.property,t.value); continue; + } Transform xform; xform.basis=t.rot; @@ -983,6 +990,24 @@ void AnimationTreePlayer::animation_node_set_master_animation(const StringName& } +void AnimationTreePlayer::animation_node_set_filter_path(const StringName& p_node,const NodePath& p_track_path,bool p_filter) { + + GET_NODE( NODE_ANIMATION, AnimationNode ); + + if (p_filter) + n->filter[p_track_path]=true; + else + n->filter.erase(p_track_path); + +} + +void AnimationTreePlayer::animation_node_set_get_filtered_paths(const StringName& p_node,List<NodePath> *r_paths) const{ + + GET_NODE( NODE_ANIMATION, AnimationNode ); + + n->filter.get_key_list(r_paths); +} + void AnimationTreePlayer::oneshot_node_set_fadein_time(const StringName& p_node,float p_time) { GET_NODE( NODE_ONESHOT, OneShotNode ); @@ -1210,6 +1235,12 @@ String AnimationTreePlayer::animation_node_get_master_animation(const StringName } +bool AnimationTreePlayer::animation_node_is_path_filtered(const StringName& p_node,const NodePath& p_path) const { + + GET_NODE_V(NODE_ANIMATION, AnimationNode, 0 ); + return n->filter.has(p_path); +} + float AnimationTreePlayer::oneshot_node_get_fadein_time(const StringName& p_node) const { @@ -1750,6 +1781,7 @@ void AnimationTreePlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("animation_node_set_master_animation","id","source"),&AnimationTreePlayer::animation_node_set_master_animation); ObjectTypeDB::bind_method(_MD("animation_node_get_master_animation","id"),&AnimationTreePlayer::animation_node_get_master_animation); + ObjectTypeDB::bind_method(_MD("animation_node_set_filter_path","id","path","enable"),&AnimationTreePlayer::animation_node_set_filter_path); ObjectTypeDB::bind_method(_MD("oneshot_node_set_fadein_time","id","time_sec"),&AnimationTreePlayer::oneshot_node_set_fadein_time); ObjectTypeDB::bind_method(_MD("oneshot_node_get_fadein_time","id"),&AnimationTreePlayer::oneshot_node_get_fadein_time); diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h index 2e44d69aa1..0e78281e4c 100644 --- a/scene/animation/animation_tree_player.h +++ b/scene/animation/animation_tree_player.h @@ -111,6 +111,7 @@ private: Variant value; + bool skip; }; @@ -162,6 +163,9 @@ private: float step; String from; bool skip; + + HashMap<NodePath,bool> filter; + AnimationNode() { type=NODE_ANIMATION; next=NULL; last_version=0; skip=false; } }; @@ -310,6 +314,10 @@ public: void animation_node_set_master_animation(const StringName& p_node,const String& p_master_animation); String animation_node_get_master_animation(const StringName& p_node) const; + void animation_node_set_filter_path(const StringName& p_node,const NodePath& p_filter,bool p_enable); + void animation_node_set_get_filtered_paths(const StringName& p_node,List<NodePath> *r_paths) const; + bool animation_node_is_path_filtered(const StringName& p_node,const NodePath& p_path) const; + /* ONE SHOT NODE */ void oneshot_node_set_fadein_time(const StringName& p_node,float p_time); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index f7461a736c..41d546c6f7 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2057,7 +2057,17 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { scancode_handled=false; break; } -#ifdef APPLE_STYLE_KEYS +#ifndef APPLE_STYLE_KEYS + if (k.mod.command) { + _scroll_lines_up(); + break; + } +#else + if (k.mod.command && k.mod.alt) { + _scroll_lines_up(); + break; + } + if (k.mod.command) cursor_set_line(0); else @@ -2084,7 +2094,17 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { scancode_handled=false; break; } -#ifdef APPLE_STYLE_KEYS +#ifndef APPLE_STYLE_KEYS + if (k.mod.command) { + _scroll_lines_down(); + break; + } +#else + if (k.mod.command && k.mod.alt) { + _scroll_lines_down(); + break; + } + if (k.mod.command) cursor_set_line(text.size()-1); else @@ -2498,6 +2518,36 @@ void TextEdit::_post_shift_selection() { selection.selecting_text=true; } +void TextEdit::_scroll_lines_up() { + // adjust the vertical scroll + if (get_v_scroll() > 0) { + set_v_scroll(get_v_scroll() - 1); + } + + // adjust the cursor + if (cursor_get_line() >= (get_visible_rows() + get_v_scroll()) && !selection.active) { + cursor_set_line((get_visible_rows() + get_v_scroll()) - 1, false); + } +} + +void TextEdit::_scroll_lines_down() { + // calculate the maximum vertical scroll position + int max_v_scroll = get_line_count() - 1; + if (!scroll_past_end_of_file_enabled) { + max_v_scroll -= get_visible_rows() - 1; + } + + // adjust the vertical scroll + if (get_v_scroll() < max_v_scroll) { + set_v_scroll(get_v_scroll() + 1); + } + + // adjust the cursor + if ((cursor_get_line()) <= get_v_scroll() - 1 && !selection.active) { + cursor_set_line(get_v_scroll(), false); + } +} + /**** TEXT EDIT CORE API ****/ void TextEdit::_base_insert_text(int p_line, int p_char,const String& p_text,int &r_end_line,int &r_end_column) { diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 09c2a4d729..193dd236d1 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -259,6 +259,9 @@ class TextEdit : public Control { void _pre_shift_selection(); void _post_shift_selection(); + void _scroll_lines_up(); + void _scroll_lines_down(); + // void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask); Size2 get_minimum_size(); diff --git a/tools/editor/plugins/animation_tree_editor_plugin.cpp b/tools/editor/plugins/animation_tree_editor_plugin.cpp index 08c2a1c3ae..7e1214ec83 100644 --- a/tools/editor/plugins/animation_tree_editor_plugin.cpp +++ b/tools/editor/plugins/animation_tree_editor_plugin.cpp @@ -239,8 +239,12 @@ void AnimationTreeEditor::_play_toggled() { void AnimationTreeEditor::_master_anim_menu_item(int p_item) { - String str = master_anim_popup->get_item_text(p_item); - anim_tree->animation_node_set_master_animation(edited_node,str); + if(p_item == 0) _edit_filters(); + else { + + String str = master_anim_popup->get_item_text(p_item); + anim_tree->animation_node_set_master_animation(edited_node,str); + } update(); } @@ -291,6 +295,8 @@ void AnimationTreeEditor::_popup_edit_dialog() { AnimationPlayer *ap = anim_tree->get_node(anim_tree->get_master_player())->cast_to<AnimationPlayer>(); master_anim_popup->clear(); + master_anim_popup->add_item("Edit Filters"); + master_anim_popup->add_separator(); List<StringName> sn; ap->get_animation_list(&sn); sn.sort_custom<StringName::AlphCompare>(); @@ -652,39 +658,35 @@ AnimationTreeEditor::ClickType AnimationTreeEditor::_locate_click(const Point2& float y = pos.y-style->get_offset().height; - if (y<h) - return CLICK_NODE; - y-=h; - - if (y<h) + if (y<2*h) return CLICK_NODE; + y-=2*h; - y-=h; - - int count=0; // title and name int inputs = anim_tree->node_get_input_count(node); - count += inputs?inputs:1; + int count = MAX(inputs,1); - for(int i=0;i<count;i++) { + if (inputs==0 || (pos.x > size.width/2 && type != AnimationTreePlayer::NODE_OUTPUT)) { - if (y<h) { + if (y<count*h) { - if (inputs==0 || ( type!=AnimationTreePlayer::NODE_OUTPUT && pos.x > size.width/2)) { + if (p_slot_index) + *p_slot_index=0; + return CLICK_OUTPUT_SLOT; + } + } - if (p_slot_index) - *p_slot_index=0; - return CLICK_OUTPUT_SLOT; - } else { + for(int i=0;i<count;i++) { - if (p_slot_index) - *p_slot_index=i; - return CLICK_INPUT_SLOT; - } + if (y<h) { + if (p_slot_index) + *p_slot_index=i; + return CLICK_INPUT_SLOT; } y-=h; } - return (type!=AnimationTreePlayer::NODE_OUTPUT && type!=AnimationTreePlayer::NODE_TIMESEEK)?CLICK_PARAMETER:CLICK_NODE; + bool has_parameters = type!=AnimationTreePlayer::NODE_OUTPUT && type!=AnimationTreePlayer::NODE_TIMESEEK; + return has_parameters ? CLICK_PARAMETER : CLICK_NODE; } return CLICK_NONE; @@ -1243,6 +1245,8 @@ void AnimationTreeEditor::_filter_edited() { anim_tree->oneshot_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0)); } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_BLEND2) { anim_tree->blend2_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0)); + } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ANIMATION) { + anim_tree->animation_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0)); } } @@ -1310,6 +1314,8 @@ void AnimationTreeEditor::_edit_filters() { it->set_checked(0, anim_tree->oneshot_node_is_path_filtered(edited_node,E->get())); } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_BLEND2) { it->set_checked(0, anim_tree->blend2_node_is_path_filtered(edited_node,E->get())); + } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ANIMATION) { + it->set_checked(0, anim_tree->animation_node_is_path_filtered(edited_node,E->get())); } pm[E->get()]=it; } |