瀏覽代碼

AnimationTree: add filters to Animation nodes.

Josh Grams 9 年之前
父節點
當前提交
bd95e18ae4

+ 60 - 0
doc/base/classes.xml

@@ -2900,6 +2900,12 @@
 		</method>
 	</methods>
 	<signals>
+		<signal name="animation_started">
+			<argument index="0" name="name" type="String">
+			</argument>
+			<description>
+			</description>
+		</signal>
 		<signal name="animation_changed">
 			<argument index="0" name="old_name" type="String">
 			</argument>
@@ -3023,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>
@@ -13887,6 +13903,12 @@ Returns an empty String "" at the end of the list.
 			<description>
 			</description>
 		</method>
+		<method name="get_connection" qualifiers="const">
+			<return type="StreamPeer">
+			</return>
+			<description>
+			</description>
+		</method>
 		<method name="request">
 			<return type="int">
 			</return>
@@ -19118,6 +19140,14 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
 			Set the mesh of the item.
 			</description>
 		</method>
+		<method name="set_item_navmesh">
+			<argument index="0" name="id" type="int">
+			</argument>
+			<argument index="1" name="navmesh" type="NavigationMesh">
+			</argument>
+			<description>
+			</description>
+		</method>
 		<method name="set_item_shape">
 			<argument index="0" name="id" type="int">
 			</argument>
@@ -19144,6 +19174,14 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
 			Return the mesh of the item.
 			</description>
 		</method>
+		<method name="get_item_navmesh" qualifiers="const">
+			<return type="NavigationMesh">
+			</return>
+			<argument index="0" name="id" type="int">
+			</argument>
+			<description>
+			</description>
+		</method>
 		<method name="get_item_shape" qualifiers="const">
 			<return type="Shape">
 			</return>
@@ -36069,6 +36107,22 @@ This method controls whether the position between two cached points is interpola
 			<description>
 			</description>
 		</method>
+		<method name="add_triangle_fan">
+			<argument index="0" name="vertexes" type="Vector3Array">
+			</argument>
+			<argument index="1" name="uvs" type="Vector2Array" default="[Vector2Array]">
+			</argument>
+			<argument index="2" name="colors" type="ColorArray" default="ColorArray([ColorArray])">
+			</argument>
+			<argument index="3" name="uv2s" type="Vector2Array" default="[Vector2Array]">
+			</argument>
+			<argument index="4" name="normals" type="Vector3Array" default="Vector3Array()">
+			</argument>
+			<argument index="5" name="tangents" type="Array" default="Array()">
+			</argument>
+			<description>
+			</description>
+		</method>
 		<method name="set_material">
 			<argument index="0" name="material" type="Material">
 			</argument>
@@ -37311,6 +37365,12 @@ This method controls whether the position between two cached points is interpola
 			<description>
 			</description>
 		</method>
+		<method name="get_stylebox_types" qualifiers="const">
+			<return type="StringArray">
+			</return>
+			<description>
+			</description>
+		</method>
 		<method name="set_font">
 			<argument index="0" name="name" type="String">
 			</argument>

+ 57 - 20
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;
 	}
 
 
@@ -817,7 +829,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
 							Variant value = a->value_track_interpolate(tr.local_track,anim_list->time);
 							Variant::blend(tr.track->value,value,blend,tr.track->value);
 						} else {
-							int index = a->track_find_key(tr.local_track,anim_list->time+anim_list->step);
+							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;
@@ -847,7 +859,7 @@ 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
@@ -978,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 );
@@ -1205,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 {
 
 
@@ -1745,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);

+ 8 - 0
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);

+ 29 - 23
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;
 	}