Exemplo n.º 1
0
void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_allow_discrete) {

	if (p_anim->node_cache.size() != p_anim->animation->get_track_count()) {
		// animation hasn't been "node-cached"
		_generate_node_caches(p_anim);
	}

	ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());

	Animation *a = p_anim->animation.operator->();
	bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint();

	for (int i = 0; i < a->get_track_count(); i++) {

		TrackNodeCache *nc = p_anim->node_cache[i];

		if (!nc) // no node cache for this track, skip it
			continue;

		if (a->track_get_key_count(i) == 0)
			continue; // do nothing if track is empty

		switch (a->track_get_type(i)) {

			case Animation::TYPE_TRANSFORM: {

				if (!nc->spatial)
					continue;

				Vector3 loc;
				Quat rot;
				Vector3 scale;

				Error err = a->transform_track_interpolate(i, p_time, &loc, &rot, &scale);
				//ERR_CONTINUE(err!=OK); //used for testing, should be removed

				if (err != OK)
					continue;

				if (nc->accum_pass != accum_pass) {
					ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
					cache_update[cache_update_size++] = nc;
					nc->accum_pass = accum_pass;
					nc->loc_accum = loc;
					nc->rot_accum = rot;
					nc->scale_accum = scale;

				} else {

					nc->loc_accum = nc->loc_accum.linear_interpolate(loc, p_interp);
					nc->rot_accum = nc->rot_accum.slerp(rot, p_interp);
					nc->scale_accum = nc->scale_accum.linear_interpolate(scale, p_interp);
				}

			} break;
			case Animation::TYPE_VALUE: {

				if (!nc->node)
					continue;

				//StringName property=a->track_get_path(i).get_property();

				Map<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.find(a->track_get_path(i).get_property());
				ERR_CONTINUE(!E); //should it continue, or create a new one?

				TrackNodeCache::PropertyAnim *pa = &E->get();

				if (a->value_track_get_update_mode(i) == Animation::UPDATE_CONTINUOUS || (p_delta == 0 && a->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE)) { //delta == 0 means seek

					Variant value = a->value_track_interpolate(i, p_time);

					if (value == Variant())
						continue;

					//thanks to trigger mode, this should be solved now..
					/*
					if (p_delta==0 && value.get_type()==Variant::STRING)
						continue; // doing this with strings is messy, should find another way
					*/
					if (pa->accum_pass != accum_pass) {
						ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX);
						cache_update_prop[cache_update_prop_size++] = pa;
						pa->value_accum = value;
						pa->accum_pass = accum_pass;
					} else {
						Variant::interpolate(pa->value_accum, value, p_interp, pa->value_accum);
					}

				} else if (p_allow_discrete && p_delta != 0) {

					List<int> indices;
					a->value_track_get_key_indices(i, p_time, p_delta, &indices);

					for (List<int>::Element *F = indices.front(); F; F = F->next()) {

						Variant value = a->track_get_key_value(i, F->get());
						switch (pa->special) {

							case SP_NONE: {
								bool valid;
								pa->object->set(pa->prop, value, &valid); //you are not speshul
#ifdef DEBUG_ENABLED
								if (!valid) {
									ERR_PRINTS("Failed setting track value '" + String(pa->owner->path) + "'. Check if property exists or the type of key is valid. Animation '" + a->get_name() + "' at node '" + get_path() + "'.");
								}
#endif

							} break;
							case SP_NODE2D_POS: {
#ifdef DEBUG_ENABLED
								if (value.get_type() != Variant::VECTOR2) {
									ERR_PRINTS("Position key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2(). Animation '" + a->get_name() + "' at node '" + get_path() + "'.");
								}
#endif
								static_cast<Node2D *>(pa->object)->set_position(value);
							} break;
							case SP_NODE2D_ROT: {
#ifdef DEBUG_ENABLED
								if (value.is_num()) {
									ERR_PRINTS("Rotation key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not numerical. Animation '" + a->get_name() + "' at node '" + get_path() + "'.");
								}
#endif

								static_cast<Node2D *>(pa->object)->set_rotation(Math::deg2rad((double)value));
							} break;
							case SP_NODE2D_SCALE: {
#ifdef DEBUG_ENABLED
								if (value.get_type() != Variant::VECTOR2) {
									ERR_PRINTS("Scale key at time " + rtos(p_time) + " in Animation Track '" + String(pa->owner->path) + "' not of type Vector2()." + a->get_name() + "' at node '" + get_path() + "'.");
								}
#endif

								static_cast<Node2D *>(pa->object)->set_scale(value);
							} break;
						}
					}
				}

			} break;
			case Animation::TYPE_METHOD: {

				if (!nc->node)
					continue;
				if (p_delta == 0)
					continue;
				if (!p_allow_discrete)
					break;

				List<int> indices;

				a->method_track_get_key_indices(i, p_time, p_delta, &indices);

				for (List<int>::Element *E = indices.front(); E; E = E->next()) {

					StringName method = a->method_track_get_name(i, E->get());
					Vector<Variant> params = a->method_track_get_params(i, E->get());

					int s = params.size();

					ERR_CONTINUE(s > VARIANT_ARG_MAX);
					if (can_call) {
						MessageQueue::get_singleton()->push_call(
								nc->node,
								method,
								s >= 1 ? params[0] : Variant(),
								s >= 2 ? params[1] : Variant(),
								s >= 3 ? params[2] : Variant(),
								s >= 4 ? params[3] : Variant(),
								s >= 5 ? params[4] : Variant());
					}
				}

			} break;
		}
	}
}
Exemplo n.º 2
0
void AnimationPlayer::_animation_process_animation(AnimationData* p_anim,float p_time, float p_delta,float p_interp, bool p_allow_discrete) {

	if (p_anim->node_cache.size() != p_anim->animation->get_track_count()) {
		// animation hasn't been "node-cached"
		_generate_node_caches(p_anim);
	}


	ERR_FAIL_COND( p_anim->node_cache.size() != p_anim->animation->get_track_count() );
	

	Animation *a=p_anim->animation.operator->();
	bool can_call = is_inside_tree() && !get_tree()->is_editor_hint();
	
	for (int i=0;i<a->get_track_count();i++) {
	
		TrackNodeCache *nc=p_anim->node_cache[i];
		
		if (!nc) // no node cache for this track, skip it
			continue;
			
		if (a->track_get_key_count(i)==0)
			continue; // do nothing if track is empty

		switch(a->track_get_type(i)) {
			
			case Animation::TYPE_TRANSFORM: {
			
				if (!nc->spatial)
					continue;
			
				
				Vector3 loc;
				Quat rot;
				Vector3 scale;


				Error err = a->transform_track_interpolate(i,p_time,&loc,&rot,&scale);
				//ERR_CONTINUE(err!=OK); //used for testing, should be removed


				if (err!=OK)
					continue;

				if (nc->accum_pass!=accum_pass) {
					ERR_CONTINUE( cache_update_size >= NODE_CACHE_UPDATE_MAX );
					cache_update[cache_update_size++]=nc;
					nc->accum_pass=accum_pass;
					nc->loc_accum=loc;
					nc->rot_accum=rot;
					nc->scale_accum=scale;

				} else {

					nc->loc_accum=nc->loc_accum.linear_interpolate(loc,p_interp);
					nc->rot_accum=nc->rot_accum.slerp(rot,p_interp);
					nc->scale_accum=nc->scale_accum.linear_interpolate(scale,p_interp);

				}
				
			} break;
			case Animation::TYPE_VALUE: {
			
				if (!nc->node)
					continue;

				//StringName property=a->track_get_path(i).get_property();

				Map<StringName,TrackNodeCache::PropertyAnim>::Element *E=nc->property_anim.find(a->track_get_path(i).get_property());
				ERR_CONTINUE(!E); //should it continue, or create a new one?

				TrackNodeCache::PropertyAnim *pa = &E->get();


				if (a->value_track_is_continuous(i) || p_delta==0) {


					Variant value=a->value_track_interpolate(i,p_time);
					if (p_delta==0 && value.get_type()==Variant::STRING)
						continue; // doing this with strings is messy, should find another way
					if (pa->accum_pass!=accum_pass) {
						ERR_CONTINUE( cache_update_prop_size >= NODE_CACHE_UPDATE_MAX );
						cache_update_prop[cache_update_prop_size++]=pa;
						pa->value_accum=value;
						pa->accum_pass=accum_pass;
					} else {
						Variant::interpolate(pa->value_accum,value,p_interp,pa->value_accum);
					}


				} else if (p_allow_discrete) {

					List<int> indices;
					a->value_track_get_key_indices(i,p_time,p_delta,&indices);

					for(List<int>::Element *F=indices.front();F;F=F->next()) {

						Variant value=a->track_get_key_value(i,F->get());
						switch(pa->special) {

							case SP_NONE: pa->object->set(pa->prop,value); break; //you are not speshul
							case SP_NODE2D_POS: static_cast<Node2D*>(pa->object)->set_pos(value); break;
							case SP_NODE2D_ROT: static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(value)); break;
							case SP_NODE2D_SCALE: static_cast<Node2D*>(pa->object)->set_scale(value); break;
						}

					}

				}
				
			} break;
			case Animation::TYPE_METHOD: {
			
				if (!nc->node)
					continue;
				if (p_delta==0)
					continue;
				if (!p_allow_discrete)
					break;
					
				List<int> indices;

				a->method_track_get_key_indices(i,p_time,p_delta,&indices);
							
				for(List<int>::Element *E=indices.front();E;E=E->next()) {

					StringName method=a->method_track_get_name(i,E->get());
					Vector<Variant> params=a->method_track_get_params(i,E->get());

					int s=params.size();

					ERR_CONTINUE( s > VARIANT_ARG_MAX );
					if (can_call) {
						MessageQueue::get_singleton()->push_call(
									nc->node,
									method,
									s>=1 ? params[0] : Variant(),
									s>=2 ? params[1] : Variant(),
									s>=3 ? params[2] : Variant(),
									s>=4 ? params[3] : Variant(),
									s>=5 ? params[4] : Variant()
									       );
					}
				}
					
			
			} break;
		}
	}
}