Beispiel #1
0
/* drivers support/hacks 
 *  - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render
 *	- these are always run since the depsgraph can't handle non-object data
 *	- these happen after objects are all done so that we can read in their final transform values,
 *	  though this means that objects can't refer to scene info for guidance...
 */
static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
{
	float ctime = BKE_scene_frame_get(scene);
	
	/* scene itself */
	if (scene->adt && scene->adt->drivers.first) {
		BKE_animsys_evaluate_animdata(scene, &scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
	}

	/* world */
	/* TODO: what about world textures? but then those have nodes too... */
	if (scene->world) {
		ID *wid = (ID *)scene->world;
		AnimData *adt = BKE_animdata_from_id(wid);
		
		if (adt && adt->drivers.first)
			BKE_animsys_evaluate_animdata(scene, wid, adt, ctime, ADT_RECALC_DRIVERS);
	}
	
	/* nodes */
	if (scene->nodetree) {
		ID *nid = (ID *)scene->nodetree;
		AnimData *adt = BKE_animdata_from_id(nid);
		
		if (adt && adt->drivers.first)
			BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
	}
}
Beispiel #2
0
/* drivers support/hacks 
 *  - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render
 *	- these are always run since the depsgraph can't handle non-object data
 *	- these happen after objects are all done so that we can read in their final transform values,
 *	  though this means that objects can't refer to scene info for guidance...
 */
static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
{
	SceneRenderLayer *srl;
	float ctime = BKE_scene_frame_get(scene);
	
	/* scene itself */
	if (scene->adt && scene->adt->drivers.first) {
		BKE_animsys_evaluate_animdata(scene, &scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
	}

	/* world */
	/* TODO: what about world textures? but then those have nodes too... */
	if (scene->world) {
		ID *wid = (ID *)scene->world;
		AnimData *adt = BKE_animdata_from_id(wid);
		
		if (adt && adt->drivers.first)
			BKE_animsys_evaluate_animdata(scene, wid, adt, ctime, ADT_RECALC_DRIVERS);
	}
	
	/* nodes */
	if (scene->nodetree) {
		ID *nid = (ID *)scene->nodetree;
		AnimData *adt = BKE_animdata_from_id(nid);
		
		if (adt && adt->drivers.first)
			BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
	}

	/* world nodes */
	if (scene->world && scene->world->nodetree) {
		ID *nid = (ID *)scene->world->nodetree;
		AnimData *adt = BKE_animdata_from_id(nid);
		
		if (adt && adt->drivers.first)
			BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
	}

	/* freestyle */
	for (srl = scene->r.layers.first; srl; srl = srl->next) {
		FreestyleConfig *config = &srl->freestyleConfig;
		FreestyleLineSet *lineset;

		for (lineset = config->linesets.first; lineset; lineset = lineset->next) {
			if (lineset->linestyle) {
				ID *lid = &lineset->linestyle->id;
				AnimData *adt = BKE_animdata_from_id(lid);

				if (adt && adt->drivers.first)
					BKE_animsys_evaluate_animdata(scene, lid, adt, ctime, ADT_RECALC_DRIVERS);
			}
		}
	}
}
void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4])
{
	ListBase *conlist = get_active_constraints(ob);
	bConstraint *con;
	for (con = (bConstraint *)conlist->first; con; con = con->next) {
		ListBase targets = {NULL, NULL};
		
		bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
		
		if (cti && cti->get_constraint_targets) {
			bConstraintTarget *ct;
			Object *obtar;
			cti->get_constraint_targets(con, &targets);
			for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
				obtar = ct->tar;

				if (obtar) {
					BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
					BKE_object_where_is_calc_time(scene, obtar, ctime);
				}
			}

			if (cti->flush_constraint_targets)
				cti->flush_constraint_targets(con, &targets, 1);
		}
	}
	BKE_object_where_is_calc_time(scene, ob, ctime);
	copy_m4_m4(mat, ob->obmat);
}
Beispiel #4
0
/* For the calculation of the effects of an Action at the given frame on an object 
 * This is currently only used for the Action Constraint 
 */
void what_does_obaction (Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe)
{
	bActionGroup *agrp= action_groups_find_named(act, groupname);
	
	/* clear workob */
	clear_workob(workob);
	
	/* init workob */
	copy_m4_m4(workob->obmat, ob->obmat);
	copy_m4_m4(workob->parentinv, ob->parentinv);
	copy_m4_m4(workob->constinv, ob->constinv);
	workob->parent= ob->parent;
	
	workob->rotmode= ob->rotmode;
	
	workob->trackflag= ob->trackflag;
	workob->upflag= ob->upflag;
	
	workob->partype= ob->partype;
	workob->par1= ob->par1;
	workob->par2= ob->par2;
	workob->par3= ob->par3;

	workob->constraints.first = ob->constraints.first;
	workob->constraints.last = ob->constraints.last;
	
	workob->pose= pose;	/* need to set pose too, since this is used for both types of Action Constraint */

	BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr));
	BLI_strncpy(workob->id.name, "OB<ConstrWorkOb>", sizeof(workob->id.name)); /* we don't use real object name, otherwise RNA screws with the real thing */
	
	/* if we're given a group to use, it's likely to be more efficient (though a bit more dangerous) */
	if (agrp) {
		/* specifically evaluate this group only */
		PointerRNA id_ptr;
		
		/* get RNA-pointer for the workob's ID */
		RNA_id_pointer_create(&workob->id, &id_ptr);
		
		/* execute action for this group only */
		animsys_evaluate_action_group(&id_ptr, act, agrp, NULL, cframe);
	}
	else {
		AnimData adt= {NULL};
		
		/* init animdata, and attach to workob */
		workob->adt= &adt;
		
		adt.recalc= ADT_RECALC_ANIM;
		adt.action= act;
		
		/* execute effects of Action on to workob (or it's PoseChannels) */
		BKE_animsys_evaluate_animdata(NULL, &workob->id, &adt, cframe, ADT_RECALC_ANIM);
	}
}
Beispiel #5
0
static void lamp_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
{
	bNode *node;

	/* nodetree itself */
	if (ntree->adt && ntree->adt->drivers.first)
		BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
	
	/* nodes */
	for (node = ntree->nodes.first; node; node = node->next)
		if (node->id && node->type == NODE_GROUP)
			lamp_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
}
void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
{
	bPoseChannel *parchan = NULL;
	bPose *pose = ob_arm->pose;

	pchan = BKE_pose_channel_find_name(pose, bone->name);

	if (!pchan)
		return;

	parchan = pchan->parent;

	enable_fcurves(ob_arm->adt->action, bone->name);

	std::vector<float>::iterator it;
	for (it = frames.begin(); it != frames.end(); it++) {
		float mat[4][4], ipar[4][4];

		float ctime = BKE_scene_frame_get_from_ctime(scene, *it);


		BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
		BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);

		// compute bone local mat
		if (bone->parent) {
			invert_m4_m4(ipar, parchan->pose_mat);
			mult_m4_m4m4(mat, ipar, pchan->pose_mat);
		}
		else
			copy_m4_m4(mat, pchan->pose_mat);

		switch (type) {
			case 0:
				mat4_to_eul(v, mat);
				break;
			case 1:
				mat4_to_size(v, mat);
				break;
			case 2:
				copy_v3_v3(v, mat[3]);
				break;
		}

		v += 3;
	}

	enable_fcurves(ob_arm->adt->action, NULL);
}
Beispiel #7
0
bool BL_ShapeDeformer::ExecuteShapeDrivers(void)
{
	if (m_useShapeDrivers && PoseUpdated()) {
		// the shape drivers use the bone matrix as input. Must 
		// update the matrix now
		m_armobj->ApplyPose();

		// We don't need an actual time, just use 0
		BKE_animsys_evaluate_animdata(NULL, &GetKey()->id, GetKey()->adt, 0.f, ADT_RECALC_DRIVERS);

		ForceUpdate();
		m_armobj->RestorePose();
		m_bDynamic = true;
		return true;
	}
	return false;
}
Beispiel #8
0
/* this is called in main loop, doing tagged updates before redraw */
void BKE_scene_update_tagged(Main *bmain, Scene *scene)
{
	Scene *sce_iter;
	
	/* keep this first */
	BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE);

	/* (re-)build dependency graph if needed */
	for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
		DAG_scene_relations_update(bmain, sce_iter);

	/* flush recalc flags to dependencies */
	DAG_ids_flush_tagged(bmain);

	/* removed calls to quick_cache, see pointcache.c */
	
	/* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later 
	 * when trying to find materials with drivers that need evaluating [#32017] 
	 */
	tag_main_idcode(bmain, ID_MA, FALSE);
	tag_main_idcode(bmain, ID_LA, FALSE);

	/* update all objects: drivers, matrices, displists, etc. flags set
	 * by depgraph or manual, no layer check here, gets correct flushed
	 *
	 * in the future this should handle updates for all datablocks, not
	 * only objects and scenes. - brecht */
	scene_update_tagged_recursive(bmain, scene, scene);

	/* extra call here to recalc scene animation (for sequencer) */
	{
		AnimData *adt = BKE_animdata_from_id(&scene->id);
		float ctime = BKE_scene_frame_get(scene);
		
		if (adt && (adt->recalc & ADT_RECALC_ANIM))
			BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0);
	}
	
	/* notify editors and python about recalc */
	BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST);
	DAG_ids_check_recalc(bmain, scene, FALSE);

	/* clear recalc flags */
	DAG_ids_clear_recalc(bmain);
}
Beispiel #9
0
void lamp_drivers_update(Scene *scene, Lamp *la, float ctime)
{
	/* Prevent infinite recursion by checking (and tagging the lamp) as having been visited already
	 * (see BKE_scene_update_tagged()). This assumes la->id.flag & LIB_DOIT isn't set by anything else
	 * in the meantime... [#32017] */
	if (la->id.flag & LIB_DOIT)
		return;
	else
		la->id.flag |= LIB_DOIT;
	
	/* lamp itself */
	if (la->adt && la->adt->drivers.first)
		BKE_animsys_evaluate_animdata(scene, &la->id, la->adt, ctime, ADT_RECALC_DRIVERS);
	
	/* nodes */
	if (la->nodetree)
		lamp_node_drivers_update(scene, la->nodetree, ctime);
}
Beispiel #10
0
/* this is called in main loop, doing tagged updates before redraw */
void BKE_scene_update_tagged(Main *bmain, Scene *scene)
{
	/* keep this first */
	BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE);

	/* flush recalc flags to dependencies */
	DAG_ids_flush_tagged(bmain);

	scene->physics_settings.quick_cache_step = 0;

	/* update all objects: drivers, matrices, displists, etc. flags set
	 * by depgraph or manual, no layer check here, gets correct flushed
	 *
	 * in the future this should handle updates for all datablocks, not
	 * only objects and scenes. - brecht */
	scene_update_tagged_recursive(bmain, scene, scene);

	/* extra call here to recalc scene animation (for sequencer) */
	{
		AnimData *adt = BKE_animdata_from_id(&scene->id);
		float ctime = BKE_scene_frame_get(scene);
		
		if (adt && (adt->recalc & ADT_RECALC_ANIM))
			BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0);
	}
	
	/* quick point cache updates */
	if (scene->physics_settings.quick_cache_step)
		BKE_ptcache_quick_cache_all(bmain, scene);

	/* notify editors and python about recalc */
	BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST);
	DAG_ids_check_recalc(bmain, scene, FALSE);

	/* clear recalc flags */
	DAG_ids_clear_recalc(bmain);
}
Beispiel #11
0
void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, const float fps)
{
	CacheFile *cache_file;
	char filename[FILE_MAX];

	for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) {
		/* Execute drivers only, as animation has already been done. */
		BKE_animsys_evaluate_animdata(scene, &cache_file->id, cache_file->adt, ctime, ADT_RECALC_DRIVERS);

		if (!cache_file->is_sequence) {
			continue;
		}

		const float time = BKE_cachefile_time_offset(cache_file, ctime, fps);

		if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) {
			BKE_cachefile_clean(scene, cache_file);
#ifdef WITH_ALEMBIC
			ABC_free_handle(cache_file->handle);
			cache_file->handle = ABC_create_handle(filename, NULL);
#endif
		}
	}
}
Beispiel #12
0
static int ocean_bake_exec(bContext *C, wmOperator *op)
{
	Object *ob = ED_object_active_context(C);
	OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
	Scene *scene = CTX_data_scene(C);
	OceanCache *och;
	struct Ocean *ocean;
	int f, cfra, i=0;
	int free= RNA_boolean_get(op->ptr, "free");
	
	wmJob *steve;
	OceanBakeJob *oj;
	
	if (!omd)
		return OPERATOR_CANCELLED;
	
	if (free) {
		omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
		DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
		WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
		return OPERATOR_FINISHED;
	}

	och = BKE_init_ocean_cache(omd->cachepath, modifier_path_relbase(ob),
	                           omd->bakestart, omd->bakeend, omd->wave_scale,
	                           omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
	
	och->time = MEM_mallocN(och->duration*sizeof(float), "foam bake time");
	
	cfra = scene->r.cfra;
	
	/* precalculate time variable before baking */
	for (f=omd->bakestart; f<=omd->bakeend; f++) {
		/* from physics_fluid.c:
		 
		 * XXX: This can't be used due to an anim sys optimisation that ignores recalc object animation,
		 * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
		 * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
		 * This doesn't work with drivers:
		 * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
		 */
		
		/* Modifying the global scene isn't nice, but we can do it in 
		 * this part of the process before a threaded job is created */
		
		//scene->r.cfra = f;
		//ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
		
		/* ok, this doesn't work with drivers, but is way faster. 
		 * let's use this for now and hope nobody wants to drive the time value... */
		BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
		
		och->time[i] = omd->time;
		i++;
	}
	
	/* make a copy of ocean to use for baking - threadsafety */
	ocean = BKE_add_ocean();
	init_ocean_modifier_bake(ocean, omd);
	
	/*
	 BKE_bake_ocean(ocean, och);
	
	omd->oceancache = och;
	omd->cached = TRUE;
	
	scene->r.cfra = cfra;
	
	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
	*/
	
	/* job stuff */
	
	scene->r.cfra = cfra;
	
	/* setup job */
	steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation", WM_JOB_PROGRESS);
	oj= MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
	oj->ocean = ocean;
	oj->och = och;
	oj->omd = omd;
	
	WM_jobs_customdata(steve, oj, oceanbake_free);
	WM_jobs_timer(steve, 0.1, NC_OBJECT|ND_MODIFIER, NC_OBJECT|ND_MODIFIER);
	WM_jobs_callbacks(steve, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
	
	WM_jobs_start(CTX_wm_manager(C), steve);
	
	
	
	return OPERATOR_FINISHED;
}
Beispiel #13
0
void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
                                   Scene *scene,
                                   Object *ob)
{
	ID *data_id = (ID *)ob->data;
	AnimData *adt = BKE_animdata_from_id(data_id);
	Key *key;
	float ctime = BKE_scene_frame_get(scene);

	if (G.debug & G_DEBUG_DEPSGRAPH)
		printf("recalcdata %s\n", ob->id.name + 2);

	/* TODO(sergey): Only used by legacy depsgraph. */
	if (adt) {
		/* evaluate drivers - datalevel */
		/* XXX: for mesh types, should we push this to derivedmesh instead? */
		BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS);
	}

	/* TODO(sergey): Only used by legacy depsgraph. */
	key = BKE_key_from_object(ob);
	if (key && key->block.first) {
		if (!(ob->shapeflag & OB_SHAPE_LOCK))
			BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
	}

	/* includes all keys and modifiers */
	switch (ob->type) {
		case OB_MESH:
		{
			BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL;
			uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH;
#ifdef WITH_FREESTYLE
			/* make sure Freestyle edge/face marks appear in DM for render (see T40315) */
			if (eval_ctx->mode != DAG_EVAL_VIEWPORT) {
				data_mask |= CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
			}
#endif
			if (em) {
				makeDerivedMesh(scene, ob, em,  data_mask, false); /* was CD_MASK_BAREMESH */
			}
			else {
				makeDerivedMesh(scene, ob, NULL, data_mask, false);
			}
			break;
		}
		case OB_ARMATURE:
			if (ob->id.lib && ob->proxy_from) {
				if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
					printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
					       ob->id.name + 2, ob->proxy_from->id.name + 2);
				}
			}
			else {
				BKE_pose_where_is(scene, ob);
			}
			break;

		case OB_MBALL:
			BKE_displist_make_mball(eval_ctx, scene, ob);
			break;

		case OB_CURVE:
		case OB_SURF:
		case OB_FONT:
			BKE_displist_make_curveTypes(scene, ob, 0);
			break;

		case OB_LATTICE:
			BKE_lattice_modifiers_calc(scene, ob);
			break;

		case OB_EMPTY:
			if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data)
				if (BKE_image_is_animated(ob->data))
					BKE_image_user_check_frame_calc(ob->iuser, (int)ctime, 0);
			break;
	}

	/* related materials */
	/* XXX: without depsgraph tagging, this will always need to be run, which will be slow!
	 * However, not doing anything (or trying to hack around this lack) is not an option
	 * anymore, especially due to Cycles [#31834]
	 */
	if (ob->totcol) {
		int a;
		if (ob->totcol != 0) {
			BLI_mutex_lock(&material_lock);
			for (a = 1; a <= ob->totcol; a++) {
				Material *ma = give_current_material(ob, a);
				if (ma) {
					/* recursively update drivers for this material */
					material_drivers_update(scene, ma, ctime);
				}
			}
			BLI_mutex_unlock(&material_lock);
		}
	}
	else if (ob->type == OB_LAMP)
		lamp_drivers_update(scene, ob->data, ctime);

	/* particles */
	if (ob != scene->obedit && ob->particlesystem.first) {
		ParticleSystem *tpsys, *psys;
		DerivedMesh *dm;
		ob->transflag &= ~OB_DUPLIPARTS;
		psys = ob->particlesystem.first;
		while (psys) {
			/* ensure this update always happens even if psys is disabled */
			if (psys->recalc & PSYS_RECALC_TYPE) {
				psys_changed_type(ob, psys);
			}

			if (psys_check_enabled(ob, psys)) {
				/* check use of dupli objects here */
				if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) &&
				    ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ||
				     (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
				{
					ob->transflag |= OB_DUPLIPARTS;
				}

				particle_system_update(scene, ob, psys);
				psys = psys->next;
			}
			else if (psys->flag & PSYS_DELETE) {
				tpsys = psys->next;
				BLI_remlink(&ob->particlesystem, psys);
				psys_free(ob, psys);
				psys = tpsys;
			}
			else
				psys = psys->next;
		}

		if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) {
			/* this is to make sure we get render level duplis in groups:
			 * the derivedmesh must be created before init_render_mesh,
			 * since object_duplilist does dupliparticles before that */
			CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL;
			dm = mesh_create_derived_render(scene, ob, data_mask);
			dm->release(dm);

			for (psys = ob->particlesystem.first; psys; psys = psys->next)
				psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
		}
	}

	/* quick cache removed */
}
Beispiel #14
0
static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated)
{
	extern int enable_cu_speed;	/* object.c */
	Object copyob;
	int cfrao = scene->r.cfra;
	int dupend = ob->dupend;
	
	/* simple prevention of too deep nested groups */
	if (level > MAX_DUPLI_RECUR) return;
	
	/* if we don't have any data/settings which will lead to object movement,
	 * don't waste time trying, as it will all look the same...
	 */
	if (ob->parent==NULL && ob->constraints.first==NULL && ob->adt==NULL) 
		return;
	
	/* make a copy of the object's original data (before any dupli-data overwrites it) 
	 * as we'll need this to keep track of unkeyed data
	 *	- this doesn't take into account other data that can be reached from the object,
	 *	  for example it's shapekeys or bones, hence the need for an update flush at the end
	 */
	copyob = *ob;
	
	/* duplicate over the required range */
	if (ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0;
	
	for (scene->r.cfra= ob->dupsta; scene->r.cfra<=dupend; scene->r.cfra++) {
		short ok= 1;
		
		/* - dupoff = how often a frames within the range shouldn't be made into duplis
		 * - dupon = the length of each "skipping" block in frames
		 */
		if (ob->dupoff) {
			ok= scene->r.cfra - ob->dupsta;
			ok= ok % (ob->dupon+ob->dupoff);
			ok= (ok < ob->dupon);
		}
		
		if (ok) {	
			DupliObject *dob;
			
			/* WARNING: doing animation updates in this way is not terribly accurate, as the dependencies
			 * and/or other objects which may affect this object's transforms are not updated either.
			 * However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine!
			 */
			BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
			where_is_object_time(scene, ob, (float)scene->r.cfra);
			
			dob= new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, OB_DUPLIFRAMES, animated);
			copy_m4_m4(dob->omat, copyob.obmat);
		}
	}

	enable_cu_speed= 1;
	
	/* reset frame to original frame, then re-evaluate animation as above 
	 * as 2.5 animation data may have far-reaching consequences
	 */
	scene->r.cfra= cfrao;
	
	BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
	where_is_object_time(scene, ob, (float)scene->r.cfra);
	
	/* but, to make sure unkeyed object transforms are still sane, 
	 * let's copy object's original data back over
	 */
	*ob = copyob;
}
Beispiel #15
0
bool BL_ShapeActionActuator::Update(double curtime, bool frame)
{
	bool bNegativeEvent = false;
	bool bPositiveEvent = false;
	bool keepgoing = true;
	bool wrap = false;
	bool apply=true;
	int	priority;
	float newweight;

	curtime -= KX_KetsjiEngine::GetSuspendedDelta();
	
	// result = true if animation has to be continued, false if animation stops
	// maybe there are events for us in the queue !
	if (frame)
	{
		bNegativeEvent = m_negevent;
		bPositiveEvent = m_posevent;
		RemoveAllEvents();
		
		if (bPositiveEvent)
			m_flag |= ACT_FLAG_ACTIVE;
		
		if (bNegativeEvent)
		{
			if (!(m_flag & ACT_FLAG_ACTIVE))
				return false;
			m_flag &= ~ACT_FLAG_ACTIVE;
		}
	}
	
	/*	This action can only be attached to a deform object */
	BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent();
	float length = m_endframe - m_startframe;
	
	priority = m_priority;
	
	/* Determine pre-incrementation behaviour and set appropriate flags */
	switch (m_playtype){
	case ACT_ACTION_MOTION:
		if (bNegativeEvent){
			keepgoing=false;
			apply=false;
		};
		break;
	case ACT_ACTION_FROM_PROP:
		if (bNegativeEvent){
			apply=false;
			keepgoing=false;
		}
		break;
	case ACT_ACTION_LOOP_END:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_KEYUP;
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag |= ACT_FLAG_LOCKINPUT;
				m_localtime = m_startframe;
				m_starttime = curtime;
			}
		}
		if (bNegativeEvent){
			m_flag |= ACT_FLAG_KEYUP;
		}
		break;
	case ACT_ACTION_LOOP_STOP:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag &= ~ACT_FLAG_KEYUP;
				m_flag |= ACT_FLAG_LOCKINPUT;
				SetStartTime(curtime);
			}
		}
		if (bNegativeEvent){
			m_flag |= ACT_FLAG_KEYUP;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
			keepgoing=false;
			apply=false;
		}
		break;
	case ACT_ACTION_FLIPPER:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_flag |= ACT_FLAG_LOCKINPUT;
				SetStartTime(curtime);
			}
		}
		else if (bNegativeEvent){
			m_flag |= ACT_FLAG_REVERSE;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
			SetStartTime(curtime);
		}
		break;
	case ACT_ACTION_PLAY:
		if (bPositiveEvent){
			if (!(m_flag & ACT_FLAG_LOCKINPUT)){
				m_flag &= ~ACT_FLAG_REVERSE;
				m_localtime = m_starttime;
				m_starttime = curtime;
				m_flag |= ACT_FLAG_LOCKINPUT;
			}
		}
		break;
	default:
		break;
	}
	
	/* Perform increment */
	if (keepgoing){
		if (m_playtype == ACT_ACTION_MOTION){
			MT_Point3	newpos;
			MT_Point3	deltapos;
			
			newpos = obj->NodeGetWorldPosition();
			
			/* Find displacement */
			deltapos = newpos-m_lastpos;
			m_localtime += (length/m_stridelength) * deltapos.length();
			m_lastpos = newpos;
		}
		else{
			SetLocalTime(curtime);
		}
	}
	
	/* Check if a wrapping response is needed */
	if (length){
		if (m_localtime < m_startframe || m_localtime > m_endframe)
		{
			m_localtime = m_startframe + fmod(m_localtime, length);
			wrap = true;
		}
	}
	else
		m_localtime = m_startframe;
	
	/* Perform post-increment tasks */
	switch (m_playtype){
	case ACT_ACTION_FROM_PROP:
		{
			CValue* propval = GetParent()->GetProperty(m_propname);
			if (propval)
				m_localtime = propval->GetNumber();
			
			if (bNegativeEvent){
				keepgoing=false;
			}
		}
		break;
	case ACT_ACTION_MOTION:
		break;
	case ACT_ACTION_LOOP_STOP:
		break;
	case ACT_ACTION_FLIPPER:
		if (wrap){
			if (!(m_flag & ACT_FLAG_REVERSE)){
				m_localtime=m_endframe;
				//keepgoing = false;
			}
			else {
				m_localtime=m_startframe;
				keepgoing = false;
			}
		}
		break;
	case ACT_ACTION_LOOP_END:
		if (wrap){
			if (m_flag & ACT_FLAG_KEYUP){
				keepgoing = false;
				m_localtime = m_endframe;
				m_flag &= ~ACT_FLAG_LOCKINPUT;
			}
			SetStartTime(curtime);
		}
		break;
	case ACT_ACTION_PLAY:
		if (wrap){
			m_localtime = m_endframe;
			keepgoing = false;
			m_flag &= ~ACT_FLAG_LOCKINPUT;
		}
		break;
	default:
		keepgoing = false;
		break;
	}
	
	/* Set the property if its defined */
	if (m_framepropname[0] != '\0') {
		CValue* propowner = GetParent();
		CValue* oldprop = propowner->GetProperty(m_framepropname);
		CValue* newval = new CFloatValue(m_localtime);
		if (oldprop) {
			oldprop->SetValue(newval);
		} else {
			propowner->SetProperty(m_framepropname, newval);
		}
		newval->Release();
	}
	
	if (bNegativeEvent)
		m_blendframe=0.0f;
	
	/* Apply the pose if necessary*/
	if (apply) {

		/* Priority test */
		if (obj->SetActiveAction(this, priority, curtime)){
			Key *key = obj->GetKey();

			if (!key) {
				// this could happen if the mesh was changed in the middle of an action
				// and the new mesh has no key, stop the action
				keepgoing = false;
			}
			else {
				ListBase tchanbase= {NULL, NULL};
			
				if (m_blendin && m_blendframe==0.0f){
					// this is the start of the blending, remember the startup shape
					obj->GetShape(m_blendshape);
					m_blendstart = curtime;
				}
				// only interested in shape channel

				// in 2.4x was // extract_ipochannels_from_action(&tchanbase, &key->id, m_action, "Shape", m_localtime);
				BKE_animsys_evaluate_animdata(&key->id, key->adt, m_localtime, ADT_RECALC_ANIM);

				// XXX - in 2.5 theres no way to do this. possibly not that important to support - Campbell
				if (0) { // XXX !execute_ipochannels(&tchanbase)) {
					// no update, this is possible if action does not match the keys, stop the action
					keepgoing = false;
				} 
				else {
					// the key have changed, apply blending if needed
					if (m_blendin && (m_blendframe<m_blendin)){
						newweight = (m_blendframe/(float)m_blendin);

						BlendShape(key, 1.0f - newweight);

						/* Increment current blending percentage */
						m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
						if (m_blendframe>m_blendin)
							m_blendframe = m_blendin;
					}
					m_lastUpdate = m_localtime;
				}
				BLI_freelistN(&tchanbase);
			}
		}
		else{
			m_blendframe = 0.0f;
		}
	}
	
	if (!keepgoing){
		m_blendframe = 0.0f;
	}
	return keepgoing;
};
Beispiel #16
0
/* For the calculation of the effects of an Action at the given frame on an object 
 * This is currently only used for the Action Constraint 
 */
void what_does_obaction(Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe)
{
	bActionGroup *agrp = BKE_action_group_find_name(act, groupname);
	
	/* clear workob */
	BKE_object_workob_clear(workob);
	
	/* init workob */
	copy_m4_m4(workob->obmat, ob->obmat);
	copy_m4_m4(workob->parentinv, ob->parentinv);
	copy_m4_m4(workob->constinv, ob->constinv);
	workob->parent = ob->parent;
	
	workob->rotmode = ob->rotmode;
	
	workob->trackflag = ob->trackflag;
	workob->upflag = ob->upflag;
	
	workob->partype = ob->partype;
	workob->par1 = ob->par1;
	workob->par2 = ob->par2;
	workob->par3 = ob->par3;

	workob->constraints.first = ob->constraints.first;
	workob->constraints.last = ob->constraints.last;
	
	workob->pose = pose; /* need to set pose too, since this is used for both types of Action Constraint */
	if (pose) {
		/* This function is most likely to be used with a temporary pose with a single bone in there.
		 * For such cases it makes no sense to create hash since it'll only waste CPU ticks on memory
		 * allocation and also will make lookup slower.
		 */
		if (pose->chanbase.first != pose->chanbase.last) {
			BKE_pose_channels_hash_make(pose);
		}
		if (pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
			BKE_pose_update_constraint_flags(pose);
		}
	}

	BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr));
	BLI_strncpy(workob->id.name, "OB<ConstrWorkOb>", sizeof(workob->id.name)); /* we don't use real object name, otherwise RNA screws with the real thing */
	
	/* if we're given a group to use, it's likely to be more efficient (though a bit more dangerous) */
	if (agrp) {
		/* specifically evaluate this group only */
		PointerRNA id_ptr;
		
		/* get RNA-pointer for the workob's ID */
		RNA_id_pointer_create(&workob->id, &id_ptr);
		
		/* execute action for this group only */
		animsys_evaluate_action_group(&id_ptr, act, agrp, NULL, cframe);
	}
	else {
		AnimData adt = {NULL};
		
		/* init animdata, and attach to workob */
		workob->adt = &adt;
		
		adt.recalc = ADT_RECALC_ANIM;
		adt.action = act;
		
		/* execute effects of Action on to workob (or it's PoseChannels) */
		BKE_animsys_evaluate_animdata(NULL, &workob->id, &adt, cframe, ADT_RECALC_ANIM);
	}
}
Beispiel #17
0
std::string AnimationExporter::create_4x4_source(std::vector<float> &frames , Object * ob_arm, Bone *bone , const std::string& anim_id)
{
	COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
	std::string source_id = anim_id + get_semantic_suffix(semantic);

	COLLADASW::Float4x4Source source(mSW);
	source.setId(source_id);
	source.setArrayId(source_id + ARRAY_ID_SUFFIX);
	source.setAccessorCount(frames.size());
	source.setAccessorStride(16);

	COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
	add_source_parameters(param, semantic, false, NULL, true);

	source.prepareToAppendValues();

	bPoseChannel *parchan = NULL;
	bPoseChannel *pchan = NULL;
	bPose *pose = ob_arm->pose;

	pchan = get_pose_channel(pose, bone->name);

	if (!pchan)
		return "";

	parchan = pchan->parent;

	enable_fcurves(ob_arm->adt->action, bone->name);

	std::vector<float>::iterator it;
	int j = 0;
	for (it = frames.begin(); it != frames.end(); it++) {
		float mat[4][4], ipar[4][4];

		float ctime = BKE_frame_to_ctime(scene, *it);

		BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
		where_is_pose_bone(scene, ob_arm, pchan, ctime, 1);

		// compute bone local mat
		if (bone->parent) {
			invert_m4_m4(ipar, parchan->pose_mat);
			mult_m4_m4m4(mat, ipar, pchan->pose_mat);
		}
		else
			copy_m4_m4(mat, pchan->pose_mat);
		UnitConverter converter;

		float outmat[4][4];
		converter.mat4_to_dae(outmat,mat);


		source.appendValues(outmat);


		j++;
	}

	enable_fcurves(ob_arm->adt->action, NULL);

	source.finish();

	return source_id;
}
Beispiel #18
0
/* OB_DUPLIFRAMES */
static void make_duplis_frames(const DupliContext *ctx)
{
	Scene *scene = ctx->scene;
	Object *ob = ctx->object;
	extern int enable_cu_speed; /* object.c */
	Object copyob;
	int cfrao = scene->r.cfra;
	int dupend = ob->dupend;

	/* dupliframes not supported inside groups */
	if (ctx->group)
		return;
	/* if we don't have any data/settings which will lead to object movement,
	 * don't waste time trying, as it will all look the same...
	 */
	if (ob->parent == NULL && BLI_listbase_is_empty(&ob->constraints) && ob->adt == NULL)
		return;

	/* make a copy of the object's original data (before any dupli-data overwrites it)
	 * as we'll need this to keep track of unkeyed data
	 *	- this doesn't take into account other data that can be reached from the object,
	 *	  for example it's shapekeys or bones, hence the need for an update flush at the end
	 */
	copyob = *ob;

	/* duplicate over the required range */
	if (ob->transflag & OB_DUPLINOSPEED) enable_cu_speed = 0;

	/* special flag to avoid setting recalc flags to notify the depsgraph of
	 * updates, as this is not a permanent change to the object */
	ob->id.tag |= LIB_TAG_ANIM_NO_RECALC;

	for (scene->r.cfra = ob->dupsta; scene->r.cfra <= dupend; scene->r.cfra++) {
		int ok = 1;

		/* - dupoff = how often a frames within the range shouldn't be made into duplis
		 * - dupon = the length of each "skipping" block in frames
		 */
		if (ob->dupoff) {
			ok = scene->r.cfra - ob->dupsta;
			ok = ok % (ob->dupon + ob->dupoff);
			ok = (ok < ob->dupon);
		}

		if (ok) {
			/* WARNING: doing animation updates in this way is not terribly accurate, as the dependencies
			 * and/or other objects which may affect this object's transforms are not updated either.
			 * However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine!
			 */
			BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
			BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);

			make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false);
		}
	}

	enable_cu_speed = 1;

	/* reset frame to original frame, then re-evaluate animation as above
	 * as 2.5 animation data may have far-reaching consequences
	 */
	scene->r.cfra = cfrao;

	BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
	BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);

	/* but, to make sure unkeyed object transforms are still sane,
	 * let's copy object's original data back over
	 */
	*ob = copyob;
}
std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob_arm, Bone *bone, const std::string& anim_id)
{
	COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
	std::string source_id = anim_id + get_semantic_suffix(semantic);

	COLLADASW::Float4x4Source source(mSW);
	source.setId(source_id);
	source.setArrayId(source_id + ARRAY_ID_SUFFIX);
	source.setAccessorCount(frames.size());
	source.setAccessorStride(16);

	COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
	add_source_parameters(param, semantic, false, NULL, true);

	source.prepareToAppendValues();

	bPoseChannel *parchan = NULL;
	bPoseChannel *pchan = NULL;
	bPose *pose = ob_arm->pose;

	pchan = BKE_pose_channel_find_name(pose, bone->name);

	if (!pchan)
		return "";

	parchan = pchan->parent;

	enable_fcurves(ob_arm->adt->action, bone->name);

	std::vector<float>::iterator it;
	int j = 0;
	for (it = frames.begin(); it != frames.end(); it++) {
		float mat[4][4], ipar[4][4];

		float ctime = BKE_scene_frame_get_from_ctime(scene, *it);

		BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
		BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);

		// compute bone local mat
		if (bone->parent) {
			invert_m4_m4(ipar, parchan->pose_mat);
			mult_m4_m4m4(mat, ipar, pchan->pose_mat);
		}
		else
			copy_m4_m4(mat, pchan->pose_mat);
		UnitConverter converter;

		// SECOND_LIFE_COMPATIBILITY
		// AFAIK animation to second life is via BVH, but no
		// reason to not have the collada-animation be correct
		if (export_settings->second_life) {
			float temp[4][4];
			copy_m4_m4(temp, bone->arm_mat);
			temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
			invert_m4(temp);

			mult_m4_m4m4(mat, mat, temp);

			if (bone->parent) {
				copy_m4_m4(temp, bone->parent->arm_mat);
				temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;

				mult_m4_m4m4(mat, temp, mat);
			}
		}

		float outmat[4][4];
		converter.mat4_to_dae(outmat, mat);


		source.appendValues(outmat);


		j++;
	}

	enable_fcurves(ob_arm->adt->action, NULL);

	source.finish();

	return source_id;
}