bool AnimationExporter::hasAnimations(Scene *sce)
{
	LinkNode *node;

	for (node=this->export_settings->export_set; node; node=node->next) {
		Object *ob = (Object *)node->link;

		FCurve *fcu = 0;
		//Check for object transform animations
		if (ob->adt && ob->adt->action)
			fcu = (FCurve *)ob->adt->action->curves.first;
		//Check for Lamp parameter animations
		else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
			fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
		//Check for Camera parameter animations
		else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
			fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);

		//Check Material Effect parameter animations.
		for (int a = 0; a < ob->totcol; a++) {
			Material *ma = give_current_material(ob, a + 1);
			if (!ma) continue;
			if (ma->adt && ma->adt->action) {
				fcu = (FCurve *)ma->adt->action->curves.first;
			}
		}

		//check shape key animation
		if (!fcu) {
			Key *key = BKE_key_from_object(ob);
			if (key && key->adt && key->adt->action)
				fcu = (FCurve *)key->adt->action->curves.first;
		}
		if (fcu)
			return true;
	}
	return false;
}
예제 #2
0
bool ImagesExporter::hasImages(Scene *sce)
{
	Base *base = (Base *)sce->base.first;
	
	while (base) {
		Object *ob= base->object;
		int a;
		for (a = 0; a < ob->totcol; a++) {
			Material *ma = give_current_material(ob, a+1);

			// no material, but check all of the slots
			if (!ma) continue;
			int b;
			for (b = 0; b < MAX_MTEX; b++) {
				MTex *mtex = ma->mtex[b];
				if (mtex && mtex->tex && mtex->tex->ima) return true;
			}

		}
		base= base->next;
	}
	return false;
}
static int buttons_context_path_material(ButsContextPath *path, bool for_texture, bool new_shading)
{
	Object *ob;
	PointerRNA *ptr = &path->ptr[path->len - 1];
	Material *ma;

	/* if we already have a (pinned) material, we're done */
	if (RNA_struct_is_a(ptr->type, &RNA_Material)) {
		return 1;
	}
	/* if we have an object, use the object material slot */
	else if (buttons_context_path_object(path)) {
		ob = path->ptr[path->len - 1].data;

		if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
			ma = give_current_material(ob, ob->actcol);
			RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
			path->len++;

			if (for_texture && give_current_material_texture_node(ma))
				return 1;

			if (!new_shading) {
				/* Only try to get mat from node in case of old shading system (see T40331). */
				ma = give_node_material(ma);
				if (ma) {
					RNA_id_pointer_create(&ma->id, &path->ptr[path->len]);
					path->len++;
				}
			}
			return 1;
		}
	}

	/* no path to a material possible */
	return 0;
}
예제 #4
0
bool ImagesExporter::hasImages(Scene *sce)
{
	LinkNode *node;
	
	for (node = this->export_settings->export_set; node; node = node->next) {
		Object *ob = (Object *)node->link;
		int a;
		for (a = 0; a < ob->totcol; a++) {
			Material *ma = give_current_material(ob, a + 1);

			// no material, but check all of the slots
			if (!ma) continue;
			int b;
			for (b = 0; b < MAX_MTEX; b++) {
				MTex *mtex = ma->mtex[b];
				if (mtex && mtex->tex && mtex->tex->ima) return true;
			}

		}
		if (ob->type == OB_MESH) {
			Mesh *me     = (Mesh *) ob->data;
			BKE_mesh_tessface_ensure(me);
			bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
			if (has_uvs) {
				int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
				for (int a = 0; a < num_layers; a++) {
					MTFace *tface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, a);
					Image *img = tface->tpage;
					if (img) return true;
				}
			}
		}

	}
	return false;
}
예제 #5
0
static void update_tface_color_layer(DerivedMesh *dm)
{
	MTFace *tface = DM_get_tessface_data_layer(dm, CD_MTFACE);
	MFace *mface = dm->getTessFaceArray(dm);
	MCol *finalCol;
	int i, j;
	MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
	if (!mcol)
		mcol = dm->getTessFaceDataArray(dm, CD_MCOL);

	if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) {
		finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL);
	}
	else {
		finalCol = MEM_mallocN(sizeof(MCol) * 4 * dm->getNumTessFaces(dm), "add_tface_color_layer");

		CustomData_add_layer(&dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData);
	}

	for (i = 0; i < dm->getNumTessFaces(dm); i++) {
		Material *ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1);

		if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
			if (mcol)
				memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4);
			else
				for (j = 0; j < 4; j++) {
					finalCol[i * 4 + j].b = 255;
					finalCol[i * 4 + j].g = 255;
					finalCol[i * 4 + j].r = 255;
				}
		}
		else if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].b = 255;
				finalCol[i * 4 + j].g = 0;
				finalCol[i * 4 + j].r = 255;
			}
		}
		else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].b = Gtexdraw.obcol[0];
				finalCol[i * 4 + j].g = Gtexdraw.obcol[1];
				finalCol[i * 4 + j].r = Gtexdraw.obcol[2];
			}
		}
		else if (!mcol) {
			if (tface) {
				for (j = 0; j < 4; j++) {
					finalCol[i * 4 + j].b = 255;
					finalCol[i * 4 + j].g = 255;
					finalCol[i * 4 + j].r = 255;
				}
			}
			else {
				float col[3];

				if (ma) {
					if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
					else copy_v3_v3(col, &ma->r);
					
					for (j = 0; j < 4; j++) {
						finalCol[i * 4 + j].b = FTOCHAR(col[0]);
						finalCol[i * 4 + j].g = FTOCHAR(col[1]);
						finalCol[i * 4 + j].r = FTOCHAR(col[2]);
					}
				}
				else
					for (j = 0; j < 4; j++) {
						finalCol[i * 4 + j].b = 255;
						finalCol[i * 4 + j].g = 255;
						finalCol[i * 4 + j].r = 255;
					}
			}
		}
		else {
			for (j = 0; j < 4; j++) {
				finalCol[i * 4 + j].r = mcol[i * 4 + j].r;
				finalCol[i * 4 + j].g = mcol[i * 4 + j].g;
				finalCol[i * 4 + j].b = mcol[i * 4 + j].b;
			}
		}
	}
}
static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol)
{
	const MPoly *mp = dm->getPolyArray(dm);
	const int mpoly_num = dm->getNumPolys(dm);
	MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
	MLoopCol *finalCol;
	int i, j;
	MLoopCol *mloopcol = NULL;

	/* cache material values to avoid a lot of lookups */
	Material *ma = NULL;
	short mat_nr_prev = -1;
	enum {
		COPY_CALC,
		COPY_ORIG,
		COPY_PREV,
	} copy_mode = COPY_CALC;

	if (use_mcol) {
		mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
		if (!mloopcol)
			mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
	}

	if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) {
		finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL);
	}
	else {
		finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer");
		CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData);
	}

	for (i = mpoly_num; i--; mp++) {
		const short mat_nr = mp->mat_nr;

		if (UNLIKELY(mat_nr_prev != mat_nr)) {
			ma = give_current_material(Gtexdraw.ob, mat_nr + 1);
			copy_mode = COPY_CALC;
			mat_nr_prev = mat_nr;
		}

		/* avoid lookups  */
		if (copy_mode == COPY_ORIG) {
			memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
		}
		else if (copy_mode == COPY_PREV) {
			int loop_index = mp->loopstart;
			const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart];
			for (j = 0; j < mp->totloop; j++, loop_index++) {
				finalCol[loop_index] = *lcol_prev;
			}
		}

		/* (copy_mode == COPY_CALC) */
		else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
			if (mloopcol) {
				memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
				copy_mode = COPY_ORIG;
			}
			else {
				memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
				copy_mode = COPY_PREV;
			}
		}
		else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw)) {
			int loop_index = mp->loopstart;
			for (j = 0; j < mp->totloop; j++, loop_index++) {
				finalCol[loop_index].r = 255;
				finalCol[loop_index].g = 0;
				finalCol[loop_index].b = 255;
			}
			copy_mode = COPY_PREV;
		}
		else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
			int loop_index = mp->loopstart;
			for (j = 0; j < mp->totloop; j++, loop_index++) {
				copy_v3_v3_char((char *)&finalCol[loop_index].r, (char *)Gtexdraw.obcol);
			}
			copy_mode = COPY_PREV;
		}
		else {
			if (mloopcol) {
				memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
				copy_mode = COPY_ORIG;
			}
			else if (mtexpoly) {
				memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
				copy_mode = COPY_PREV;
			}
			else {
				float col[3];

				if (ma) {
					int loop_index = mp->loopstart;
					MLoopCol lcol;

					if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
					else copy_v3_v3(col, &ma->r);
					rgb_float_to_uchar((unsigned char *)&lcol.r, col);
					lcol.a = 255;
					
					for (j = 0; j < mp->totloop; j++, loop_index++) {
						finalCol[loop_index] = lcol;
					}
				}
				else {
					memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
				}
				copy_mode = COPY_PREV;
			}
		}
	}
}
예제 #7
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 */
}
// called for each exported object
void AnimationExporter::operator()(Object *ob)
{
	FCurve *fcu;
	char *transformName;
	/* bool isMatAnim = false; */ /* UNUSED */

	//Export transform animations
	if (ob->adt && ob->adt->action) {
		fcu = (FCurve *)ob->adt->action->curves.first;

		//transform matrix export for bones are temporarily disabled here.
		if (ob->type == OB_ARMATURE) {
			bArmature *arm = (bArmature *)ob->data;
			for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
				write_bone_animation_matrix(ob, bone);
		}

		while (fcu) {
			//for armature animations as objects
			if (ob->type == OB_ARMATURE)
				transformName =  fcu->rna_path;
			else 
				transformName = extract_transform_name(fcu->rna_path);

			if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
			    (!strcmp(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
			    (!strcmp(transformName, "rotation_quaternion")))
			{
				dae_animation(ob, fcu, transformName, false);
			}
			fcu = fcu->next;
		}

	}

	//Export Lamp parameter animations
	if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
		fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
		while (fcu) {
			transformName = extract_transform_name(fcu->rna_path);

			if ((!strcmp(transformName, "color")) || (!strcmp(transformName, "spot_size")) ||
			    (!strcmp(transformName, "spot_blend")) || (!strcmp(transformName, "distance")))
			{
				dae_animation(ob, fcu, transformName, true);
			}
			fcu = fcu->next;
		}
	}

	//Export Camera parameter animations
	if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
		fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
		while (fcu) {
			transformName = extract_transform_name(fcu->rna_path);

			if ((!strcmp(transformName, "lens")) ||
			    (!strcmp(transformName, "ortho_scale")) ||
			    (!strcmp(transformName, "clip_end")) || (!strcmp(transformName, "clip_start")))
			{
				dae_animation(ob, fcu, transformName, true);
			}
			fcu = fcu->next;
		}
	}

	//Export Material parameter animations.
	for (int a = 0; a < ob->totcol; a++) {
		Material *ma = give_current_material(ob, a + 1);
		if (!ma) continue;
		if (ma->adt && ma->adt->action) {
			/* isMatAnim = true; */
			fcu = (FCurve *)ma->adt->action->curves.first;
			while (fcu) {
				transformName = extract_transform_name(fcu->rna_path);

				if ((!strcmp(transformName, "specular_hardness")) || (!strcmp(transformName, "specular_color")) ||
				    (!strcmp(transformName, "diffuse_color")) || (!strcmp(transformName, "alpha")) ||
				    (!strcmp(transformName, "ior")))
				{
					dae_animation(ob, fcu, transformName, true, ma);
				}
				fcu = fcu->next;
			}
		}

	}
}
예제 #9
0
// powerful because it handles both cases when there is material and when there's not
void GeometryExporter::createPolylist(short material_index,
					bool has_uvs,
					bool has_color,
					Object *ob,
					std::string& geom_id,
					std::vector<Face>& norind)
{
	Mesh *me = (Mesh*)ob->data;
	MFace *mfaces = me->mface;
	int totfaces = me->totface;

	// <vcount>
	int i;
	int faces_in_polylist = 0;
	std::vector<unsigned long> vcount_list;

	// count faces with this material
	for (i = 0; i < totfaces; i++) {
		MFace *f = &mfaces[i];
		
		if (f->mat_nr == material_index) {
			faces_in_polylist++;
			if (f->v4 == 0) {
				vcount_list.push_back(3);
			}
			else {
				vcount_list.push_back(4);
			}
		}
	}

	// no faces using this material
	if (faces_in_polylist == 0) {
		fprintf(stderr, "%s: no faces use material %d\n", id_name(ob).c_str(), material_index);
		return;
	}
		
	Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
	COLLADASW::Polylist polylist(mSW);
		
	// sets count attribute in <polylist>
	polylist.setCount(faces_in_polylist);
		
	// sets material name
	if (ma) {
		std::ostringstream ostr;
		ostr << translate_id(id_name(ma)) << material_index+1;
		polylist.setMaterial(ostr.str());
	}
			
	COLLADASW::InputList &til = polylist.getInputList();
		
	// creates <input> in <polylist> for vertices 
	COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
		
	// creates <input> in <polylist> for normals
	COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
		
	til.push_back(input1);
	til.push_back(input2);
		
	// if mesh has uv coords writes <input> for TEXCOORD
	int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);

	for (i = 0; i < num_layers; i++) {
		// char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
		COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
								makeUrl(makeTexcoordSourceId(geom_id, i)),
								2, // offset always 2, this is only until we have optimized UV sets
								i  // set number equals UV map index
								);
		til.push_back(input3);
	}

	if (has_color) {
		COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::COLOR), has_uvs ? 3 : 2);
		til.push_back(input4);
	}
		
	// sets <vcount>
	polylist.setVCountList(vcount_list);
		
	// performs the actual writing
	polylist.prepareToAppendValues();
		
	// <p>
	int texindex = 0;
	for (i = 0; i < totfaces; i++) {
		MFace *f = &mfaces[i];

		if (f->mat_nr == material_index) {

			unsigned int *v = &f->v1;
			unsigned int *n = &norind[i].v1;
			for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
				polylist.appendValues(v[j]);
				polylist.appendValues(n[j]);

				if (has_uvs)
					polylist.appendValues(texindex + j);

				if (has_color)
					polylist.appendValues(texindex + j);
			}
		}

		texindex += 3;
		if (f->v4 != 0)
			texindex++;
	}
		
	polylist.finish();
}
예제 #10
0
// powerful because it handles both cases when there is material and when there's not
void GeometryExporter::createPolylist(short material_index,
                                      bool has_uvs,
                                      bool has_color,
                                      Object *ob,
                                      Mesh *me,
                                      std::string& geom_id,
                                      std::vector<BCPolygonNormalsIndices>& norind)
{

	MPoly *mpolys = me->mpoly;
	MLoop *mloops = me->mloop;
	int totpolys  = me->totpoly;

	// <vcount>
	int i;
	int faces_in_polylist = 0;
	std::vector<unsigned long> vcount_list;

	// count faces with this material
	for (i = 0; i < totpolys; i++) {
		MPoly *p = &mpolys[i];
		
		if (p->mat_nr == material_index) {
			faces_in_polylist++;
			vcount_list.push_back(p->totloop);
		}
	}

	// no faces using this material
	if (faces_in_polylist == 0) {
		fprintf(stderr, "%s: material with index %d is not used.\n", id_name(ob).c_str(), material_index);
		return;
	}
		
	Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
	COLLADASW::Polylist polylist(mSW);
		
	// sets count attribute in <polylist>
	polylist.setCount(faces_in_polylist);
		
	// sets material name
	if (ma) {
		std::string material_id = get_material_id(ma);
		std::ostringstream ostr;
		ostr << translate_id(material_id);
		polylist.setMaterial(ostr.str());
	}
			
	COLLADASW::InputList &til = polylist.getInputList();
		
	// creates <input> in <polylist> for vertices 
	COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
		
	// creates <input> in <polylist> for normals
	COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
		
	til.push_back(input1);
	til.push_back(input2);
		
	// if mesh has uv coords writes <input> for TEXCOORD
	int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
	int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
	for (i = 0; i < num_layers; i++) {
		if (!this->export_settings->active_uv_only || i == active_uv_index) {

			// char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
			COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
									makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
									2, // this is only until we have optimized UV sets
									(this->export_settings->active_uv_only) ? 0 : i  // only_active_uv exported -> we have only one set
									);
			til.push_back(input3);
		}
	}

	int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
	if (totlayer_mcol > 0) {
		int map_index = 0;

		for (int a = 0; a < totlayer_mcol; a++) {
			char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
			COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
			                        makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
			                        (has_uvs) ? 3 : 2,  // all color layers have same index order
			                        map_index           // set number equals color map index
			                        );
			til.push_back(input4);
			map_index++;
		}
	}
		
	// sets <vcount>
	polylist.setVCountList(vcount_list);
		
	// performs the actual writing
	polylist.prepareToAppendValues();
	
	// <p>
	int texindex = 0;
	for (i = 0; i < totpolys; i++) {
		MPoly *p = &mpolys[i];
		int loop_count = p->totloop;

		if (p->mat_nr == material_index) {
			MLoop *l = &mloops[p->loopstart];
			BCPolygonNormalsIndices normal_indices = norind[i];

			for (int j = 0; j < loop_count; j++) {
				polylist.appendValues(l[j].v);
				polylist.appendValues(normal_indices[j]);
				if (has_uvs)
					polylist.appendValues(texindex + j);

				if (has_color)
					polylist.appendValues(texindex + j);
			}
		}

		texindex += loop_count;
	}
		
	polylist.finish();
}
예제 #11
0
static void buttons_texture_users_from_context(ListBase *users, const bContext *C, SpaceButs *sbuts)
{
    Scene *scene = NULL;
    Object *ob = NULL;
    Material *ma = NULL;
    Lamp *la = NULL;
    World *wrld = NULL;
    Brush *brush = NULL;
    ID *pinid = sbuts->pinid;
    bool limited_mode = (sbuts->flag & SB_TEX_USER_LIMITED) != 0;

    /* get data from context */
    if (pinid) {
        if (GS(pinid->name) == ID_SCE)
            scene = (Scene *)pinid;
        else if (GS(pinid->name) == ID_OB)
            ob = (Object *)pinid;
        else if (GS(pinid->name) == ID_LA)
            la = (Lamp *)pinid;
        else if (GS(pinid->name) == ID_WO)
            wrld = (World *)pinid;
        else if (GS(pinid->name) == ID_MA)
            ma = (Material *)pinid;
        else if (GS(pinid->name) == ID_BR)
            brush = (Brush *)pinid;
    }

    if (!scene)
        scene = CTX_data_scene(C);

    if (!(pinid || pinid == &scene->id)) {
        ob = (scene->basact) ? scene->basact->object : NULL;
        wrld = scene->world;
        brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
    }

    if (ob && ob->type == OB_LAMP && !la)
        la = ob->data;
    if (ob && !ma)
        ma = give_current_material(ob, ob->actcol);

    /* fill users */
    users->first = users->last = NULL;

    if (ma && !limited_mode)
        buttons_texture_users_find_nodetree(users, &ma->id, ma->nodetree, "Material");
    if (la && !limited_mode)
        buttons_texture_users_find_nodetree(users, &la->id, la->nodetree, "Lamp");
    if (wrld && !limited_mode)
        buttons_texture_users_find_nodetree(users, &wrld->id, wrld->nodetree, "World");

    if (ob) {
        ParticleSystem *psys = psys_get_current(ob);
        MTex *mtex;
        int a;

        /* modifiers */
        modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users);

        /* particle systems */
        if (psys && !limited_mode) {
            for (a = 0; a < MAX_MTEX; a++) {
                mtex = psys->part->mtex[a];

                if (mtex) {
                    PointerRNA ptr;
                    PropertyRNA *prop;

                    RNA_pointer_create(&psys->part->id, &RNA_ParticleSettingsTextureSlot, mtex, &ptr);
                    prop = RNA_struct_find_property(&ptr, "texture");

                    buttons_texture_user_property_add(users, &psys->part->id, ptr, prop,
                                                      "Particles", RNA_struct_ui_icon(&RNA_ParticleSettings), psys->name);
                }
            }
        }

        /* field */
        if (ob->pd && ob->pd->forcefield == PFIELD_TEXTURE) {
            PointerRNA ptr;
            PropertyRNA *prop;

            RNA_pointer_create(&ob->id, &RNA_FieldSettings, ob->pd, &ptr);
            prop = RNA_struct_find_property(&ptr, "texture");

            buttons_texture_user_property_add(users, &ob->id, ptr, prop,
                                              "Fields", ICON_FORCE_TEXTURE, "Texture Field");
        }
    }

    /* brush */
    if (brush) {
        PointerRNA ptr;
        PropertyRNA *prop;

        /* texture */
        RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mtex, &ptr);
        prop = RNA_struct_find_property(&ptr, "texture");

        buttons_texture_user_property_add(users, &brush->id, ptr, prop,
                                          "Brush", ICON_BRUSH_DATA, "Brush");

        /* mask texture */
        RNA_pointer_create(&brush->id, &RNA_BrushTextureSlot, &brush->mask_mtex, &ptr);
        prop = RNA_struct_find_property(&ptr, "texture");

        buttons_texture_user_property_add(users, &brush->id, ptr, prop,
                                          "Brush", ICON_BRUSH_DATA, "Brush Mask");
    }
}
예제 #12
0
void EffectsExporter::operator()(Material *ma, Object *ob)
{
	// create a list of indices to textures of type TEX_IMAGE
	std::vector<int> tex_indices;
	if (this->export_settings->include_material_textures)
		createTextureIndices(ma, tex_indices);

	openEffect(translate_id(id_name(ma)) + "-effect");
	
	COLLADASW::EffectProfile ep(mSW);
	ep.setProfileType(COLLADASW::EffectProfile::COMMON);
	ep.openProfile();
	// set shader type - one of three blinn, phong or lambert
	if (ma->spec > 0.0f) {
		if (ma->spec_shader == MA_SPEC_BLINN) {
			writeBlinn(ep, ma);
		}
		else {
			// \todo figure out handling of all spec+diff shader combos blender has, for now write phong
			// for now set phong in case spec shader is not blinn
			writePhong(ep, ma);
		}
	}
	else {
		if (ma->diff_shader == MA_DIFF_LAMBERT) {
			writeLambert(ep, ma);
		}
		else {
			// \todo figure out handling of all spec+diff shader combos blender has, for now write phong
			writePhong(ep, ma);
		}
	}
	
	// index of refraction
	if (ma->mode & MA_RAYTRANSP) {
		ep.setIndexOfRefraction(ma->ang, false, "index_of_refraction");
	}
	else {
		ep.setIndexOfRefraction(1.0f, false, "index_of_refraction");
	}

	COLLADASW::ColorOrTexture cot;

	// transparency
	if (ma->mode & MA_TRANSP) {
		// Tod: because we are in A_ONE mode transparency is calculated like this:
		ep.setTransparency(ma->alpha, false, "transparency");
		// cot = getcol(1.0f, 1.0f, 1.0f, 1.0f);
		// ep.setTransparent(cot);
	}

	// emission
	cot = getcol(ma->emit, ma->emit, ma->emit, 1.0f);
	ep.setEmission(cot, false, "emission");

	// diffuse multiplied by diffuse intensity
	cot = getcol(ma->r * ma->ref, ma->g * ma->ref, ma->b * ma->ref, 1.0f);
	ep.setDiffuse(cot, false, "diffuse");

	// ambient
	/* ma->ambX is calculated only on render, so lets do it here manually and not rely on ma->ambX. */
	if (this->scene->world)
		cot = getcol(this->scene->world->ambr * ma->amb, this->scene->world->ambg * ma->amb, this->scene->world->ambb * ma->amb, 1.0f);
	else
		cot = getcol(ma->amb, ma->amb, ma->amb, 1.0f);

	ep.setAmbient(cot, false, "ambient");

	// reflective, reflectivity
	if (ma->mode & MA_RAYMIRROR) {
		cot = getcol(ma->mirr, ma->mirg, ma->mirb, 1.0f);
		ep.setReflective(cot);
		ep.setReflectivity(ma->ray_mirror);
	}
	// else {
	//  cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
	//  ep.setReflective(cot);
	//  ep.setReflectivity(ma->spec);
	// }

	// specular
	if (ep.getShaderType() != COLLADASW::EffectProfile::LAMBERT) {
		cot = getcol(ma->specr * ma->spec, ma->specg * ma->spec, ma->specb * ma->spec, 1.0f);
		ep.setSpecular(cot, false, "specular");
	}

	// XXX make this more readable if possible

	// create <sampler> and <surface> for each image
	COLLADASW::Sampler samplers[MAX_MTEX];
	//COLLADASW::Surface surfaces[MAX_MTEX];
	//void *samp_surf[MAX_MTEX][2];
	void *samp_surf[MAX_MTEX][1];
	
	// image to index to samp_surf map
	// samp_surf[index] stores 2 pointers, sampler and surface
	std::map<std::string, int> im_samp_map;

	unsigned int a, b;
	for (a = 0, b = 0; a < tex_indices.size(); a++) {
		MTex *t = ma->mtex[tex_indices[a]];
		Image *ima = t->tex->ima;
		
		// Image not set for texture
		if (!ima) continue;
		
		std::string key(id_name(ima));
		key = translate_id(key);

		// create only one <sampler>/<surface> pair for each unique image
		if (im_samp_map.find(key) == im_samp_map.end()) {
			// //<newparam> <surface> <init_from>
			// COLLADASW::Surface surface(COLLADASW::Surface::SURFACE_TYPE_2D,
			//                         key + COLLADASW::Surface::SURFACE_SID_SUFFIX);
			// COLLADASW::SurfaceInitOption sio(COLLADASW::SurfaceInitOption::INIT_FROM);
			// sio.setImageReference(key);
			// surface.setInitOption(sio);

			// COLLADASW::NewParamSurface surface(mSW);
			// surface->setParamType(COLLADASW::CSW_SURFACE_TYPE_2D);
			
			//<newparam> <sampler> <source>
			COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
			                           key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
			                           key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
			sampler.setImageId(key);
			// copy values to arrays since they will live longer
			samplers[a] = sampler;
			//surfaces[a] = surface;
			
			// store pointers so they can be used later when we create <texture>s
			samp_surf[b][0] = &samplers[a];
			//samp_surf[b][1] = &surfaces[a];
			
			im_samp_map[key] = b;
			b++;
		}
	}


	std::set<Image *> uv_textures;
	if (ob->type == OB_MESH && ob->totcol && this->export_settings->include_uv_textures) {
		bool active_uv_only = this->export_settings->active_uv_only;
		Mesh *me     = (Mesh *) ob->data;
		int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);

		BKE_mesh_tessface_ensure(me);
		for (int i = 0; i < me->pdata.totlayer; i++) {
			if (!active_uv_only || active_uv_layer == i)
			{
				if (me->pdata.layers[i].type == CD_MTEXPOLY) {
					MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
					MFace *mface = me->mface;
					for (int j = 0; j < me->totpoly; j++, mface++, txface++) {

						Material *mat = give_current_material(ob, mface->mat_nr + 1);
						if (mat != ma) 
							continue;

						Image *ima = txface->tpage;
						if (ima == NULL)
							continue;


						bool not_in_list = uv_textures.find(ima)==uv_textures.end();
						if (not_in_list) {
							std::string name = id_name(ima);
							std::string key(name);
							key = translate_id(key);

							// create only one <sampler>/<surface> pair for each unique image
							if (im_samp_map.find(key) == im_samp_map.end()) {
								//<newparam> <sampler> <source>
								COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
														   key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
														   key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
								sampler.setImageId(key);
								samplers[a] = sampler;
								samp_surf[b][0] = &samplers[a];
								im_samp_map[key] = b;
								b++;
								a++;
								uv_textures.insert(ima);
							}
						}
					}
				}
			}
		}
	}

	// used as fallback when MTex->uvname is "" (this is pretty common)
	// it is indeed the correct value to use in that case
	std::string active_uv(getActiveUVLayerName(ob));

	// write textures
	// XXX very slow
	for (a = 0; a < tex_indices.size(); a++) {
		MTex *t = ma->mtex[tex_indices[a]];
		Image *ima = t->tex->ima;

		std::string key(id_name(ima));
		key = translate_id(key);
		int i = im_samp_map[key];
		std::string uvname = strlen(t->uvname) ? t->uvname : active_uv;
		COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i][0];
		writeTextures(ep, key, sampler, t, ima, uvname);
	}

	std::set<Image *>::iterator uv_t_iter;
	for (uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++ ) {
		Image *ima = *uv_t_iter;
		std::string key(id_name(ima));
		key = translate_id(key);
		int i = im_samp_map[key];
		COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i][0];
		ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse");
	}

	// performs the actual writing
	ep.addProfileElements();
	bool twoSided = false;
	if (ob->type == OB_MESH && ob->data) {
		Mesh *me = (Mesh *)ob->data;
		if (me->flag & ME_TWOSIDED)
			twoSided = true;
	}
	if (twoSided)
		ep.addExtraTechniqueParameter("GOOGLEEARTH", "double_sided", 1);
	ep.addExtraTechniques(mSW);

	ep.closeProfile();
	if (twoSided)
		mSW->appendTextBlock("<extra><technique profile=\"MAX3D\"><double_sided>1</double_sided></technique></extra>");
	closeEffect();
}
예제 #13
0
/* call this with NULL to restore assigned ID pointers in preview scene */
static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
	Scene *sce;
	Base *base;
	Main *pr_main = sp->pr_main;
	
	sce = preview_get_scene(pr_main);
	if (sce) {
		
		/* this flag tells render to not execute depsgraph or ipos etc */
		sce->r.scemode |= R_PREVIEWBUTS;
		/* set world always back, is used now */
		sce->world = pr_main->world.first;
		/* now: exposure copy */
		if (scene->world) {
			sce->world->exp = scene->world->exp;
			sce->world->range = scene->world->range;
		}
		
		sce->r.color_mgt_flag = scene->r.color_mgt_flag;
		BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);

		BKE_color_managed_view_settings_free(&sce->view_settings);
		BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
		
		/* prevent overhead for small renders and icons (32) */
		if (id && sp->sizex < 40) {
			sce->r.tilex = sce->r.tiley = 64;
		}
		else {
			sce->r.tilex = sce->r.xsch / 4;
			sce->r.tiley = sce->r.ysch / 4;
		}
		
		if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
			sce->r.alphamode = R_ALPHAPREMUL;
		else
			sce->r.alphamode = R_ADDSKY;

		sce->r.cfra = scene->r.cfra;

		if (id_type == ID_TE && sp->pr_method == PR_ICON_RENDER) {
			/* force blender internal for texture icons render,
			 * seems commonly used render engines does not support
			 * such kind of rendering
			 */
			BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
		}
		else {
			BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
		}
		
		if (id_type == ID_MA) {
			Material *mat = NULL, *origmat = (Material *)id;
			
			if (origmat) {
				/* work on a copy */
				mat = localize_material(origmat);
				sp->matcopy = mat;
				BLI_addtail(&pr_main->mat, mat);
				
				if (!BKE_scene_use_new_shading_nodes(scene)) {
					init_render_material(mat, 0, NULL);     /* call that retrieves mode_l */
					end_render_material(mat);
					
					/* un-useful option */
					if (sp->pr_method == PR_ICON_RENDER)
						mat->shade_flag &= ~MA_OBCOLOR;

					/* turn on raytracing if needed */
					if (mat->mode_l & MA_RAYMIRROR)
						sce->r.mode |= R_RAYTRACE;
					if (mat->material_type == MA_TYPE_VOLUME)
						sce->r.mode |= R_RAYTRACE;
					if ((mat->mode_l & MA_RAYTRANSP) && (mat->mode_l & MA_TRANSP))
						sce->r.mode |= R_RAYTRACE;
					if (preview_mat_has_sss(mat, NULL))
						sce->r.mode |= R_SSS;
					
					/* turn off fake shadows if needed */
					/* this only works in a specific case where the preview.blend contains
					 * an object starting with 'c' which has a material linked to it (not the obdata)
					 * and that material has a fake shadow texture in the active texture slot */
					for (base = sce->base.first; base; base = base->next) {
						if (base->object->id.name[2] == 'c') {
							Material *shadmat = give_current_material(base->object, base->object->actcol);
							if (shadmat) {
								if (mat->mode & MA_SHADBUF) shadmat->septex = 0;
								else shadmat->septex |= 1;
							}
						}
					}
					
					/* turn off bounce lights for volume, 
					 * doesn't make much visual difference and slows it down too */
					if (mat->material_type == MA_TYPE_VOLUME) {
						for (base = sce->base.first; base; base = base->next) {
							if (base->object->type == OB_LAMP) {
								/* if doesn't match 'Lamp.002' --> main key light */
								if (strcmp(base->object->id.name + 2, "Lamp.002") != 0) {
									base->object->restrictflag |= OB_RESTRICT_RENDER;
								}
							}
						}
					}
				}
				else {
					/* use current scene world to light sphere */
					if (mat->pr_type == MA_SPHERE_A)
						sce->world = scene->world;
				}
				
				if (sp->pr_method == PR_ICON_RENDER) {
					if (mat->material_type == MA_TYPE_HALO) {
						sce->lay = 1 << MA_FLAT;
					}
					else {
						sce->lay = 1 << MA_SPHERE_A;

						/* same as above, use current scene world to light sphere */
						if (BKE_scene_use_new_shading_nodes(scene))
							sce->world = scene->world;
					}
				}
				else {
					sce->lay = 1 << mat->pr_type;
					if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
						/* two previews, they get copied by wmJob */
						BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, TRUE);
						BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, TRUE);
					}
				}
			}
			else {
				sce->r.mode &= ~(R_OSA | R_RAYTRACE | R_SSS);
				
			}
			
			for (base = sce->base.first; base; base = base->next) {
				if (base->object->id.name[2] == 'p') {
					/* copy over object color, in case material uses it */
					copy_v4_v4(base->object->col, sp->col);
					
					if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) {
						/* don't use assign_material, it changed mat->id.us, which shows in the UI */
						Material ***matar = give_matarar(base->object);
						int actcol = max_ii(base->object->actcol - 1, 0);

						if (matar && actcol < base->object->totcol)
							(*matar)[actcol] = mat;
					}
					else if (base->object->type == OB_LAMP) {
						base->object->restrictflag &= ~OB_RESTRICT_RENDER;
					}
				}
			}
		}
		else if (id_type == ID_TE) {
			Tex *tex = NULL, *origtex = (Tex *)id;
			
			if (origtex) {
				tex = localize_texture(origtex);
				sp->texcopy = tex;
				BLI_addtail(&pr_main->tex, tex);
			}
			sce->lay = 1 << MA_TEXTURE;
			
			for (base = sce->base.first; base; base = base->next) {
				if (base->object->id.name[2] == 't') {
					Material *mat = give_current_material(base->object, base->object->actcol);
					if (mat && mat->mtex[0]) {
						mat->mtex[0]->tex = tex;
						
						if (tex && sp->slot)
							mat->mtex[0]->which_output = sp->slot->which_output;

						mat->mtex[0]->mapto &= ~MAP_ALPHA;
						mat->alpha = 1.0f;

						/* show alpha in this case */
						if (tex == NULL || (tex->flag & TEX_PRV_ALPHA)) {
							if (!(tex && tex->type == TEX_IMAGE && (tex->imaflag & (TEX_USEALPHA | TEX_CALCALPHA)) == 0)) {
								mat->mtex[0]->mapto |= MAP_ALPHA;
								mat->alpha = 0.0f;
							}
						}
					}
				}
			}

			if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
				/* two previews, they get copied by wmJob */
				BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, TRUE);
				BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, TRUE);
			}
		}
		else if (id_type == ID_LA) {
			Lamp *la = NULL, *origla = (Lamp *)id;

			/* work on a copy */
			if (origla) {
				la = localize_lamp(origla);
				sp->lampcopy = la;
				BLI_addtail(&pr_main->lamp, la);
			}

			sce->lay = 1 << MA_LAMP;

			if (!BKE_scene_use_new_shading_nodes(scene)) {
				if (la && la->type == LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
					sce->lay = 1 << MA_ATMOS;
					sce->world = scene->world;
					sce->camera = (Object *)BLI_findstring(&pr_main->object, "CameraAtmo", offsetof(ID, name) + 2);
				}
				else {
					sce->world = NULL;
					sce->camera = (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name) + 2);
				}
			}
				
			for (base = sce->base.first; base; base = base->next) {
				if (base->object->id.name[2] == 'p') {
					if (base->object->type == OB_LAMP)
						base->object->data = la;
				}
			}

			if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
				/* two previews, they get copied by wmJob */
				BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, TRUE);
				BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, TRUE);
			}
		}
		else if (id_type == ID_WO) {
			World *wrld = NULL, *origwrld = (World *)id;

			if (origwrld) {
				wrld = localize_world(origwrld);
				sp->worldcopy = wrld;
				BLI_addtail(&pr_main->world, wrld);
			}

			sce->lay = 1 << MA_SKY;
			sce->world = wrld;

			if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
				/* two previews, they get copied by wmJob */
				BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, TRUE);
				BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, TRUE);
			}
		}
		
		return sce;
	}
	
	return NULL;
}
예제 #14
0
bool BL_Action::Play(const char* name,
					float start,
					float end,
					short priority,
					float blendin,
					short play_mode,
					float layer_weight,
					short ipo_flags,
					float playback_speed)
{

	// Only start playing a new action if we're done, or if
	// the new action has a higher priority
	if (!IsDone() && priority > m_priority)
		return false;
	m_priority = priority;
	bAction* prev_action = m_action;

	KX_Scene* kxscene = m_obj->GetScene();

	// First try to load the action
	m_action = (bAction*)kxscene->GetLogicManager()->GetActionByName(name);
	if (!m_action)
	{
		printf("Failed to load action: %s\n", name);
		m_done = true;
		return false;
	}

	// If we have the same settings, don't play again
	// This is to resolve potential issues with pulses on sensors such as the ones
	// reported in bug #29412. The fix is here so it works for both logic bricks and Python.
	// However, this may eventually lead to issues where a user wants to override an already
	// playing action with the same action and settings. If this becomes an issue,
	// then this fix may have to be re-evaluated.
	if (!IsDone() && m_action == prev_action && m_startframe == start && m_endframe == end
			&& m_priority == priority && m_speed == playback_speed)
		return false;

	// First get rid of any old controllers
	ClearControllerList();

	// Create an SG_Controller
	SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, kxscene->GetSceneConverter());
	m_sg_contr_list.push_back(sg_contr);
	m_obj->GetSGNode()->AddSGController(sg_contr);
	sg_contr->SetObject(m_obj->GetSGNode());

	// Try obcolor
	sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter());
	if (sg_contr) {
		m_sg_contr_list.push_back(sg_contr);
		m_obj->GetSGNode()->AddSGController(sg_contr);
		sg_contr->SetObject(m_obj->GetSGNode());
	}

	// Now try materials
	if (m_obj->GetBlenderObject()->totcol==1) {
		Material *mat = give_current_material(m_obj->GetBlenderObject(), 1);
		if (mat) {
			sg_contr = BL_CreateMaterialIpo(m_action, mat, 0, m_obj, kxscene->GetSceneConverter());
			if (sg_contr) {
				m_sg_contr_list.push_back(sg_contr);
				m_obj->GetSGNode()->AddSGController(sg_contr);
				sg_contr->SetObject(m_obj->GetSGNode());
			}
		}
	} else {
		Material *mat;
		STR_HashedString matname;

		for (int matidx = 1; matidx <= m_obj->GetBlenderObject()->totcol; ++matidx) {
			mat = give_current_material(m_obj->GetBlenderObject(), matidx);
			if (mat) {
				matname = mat->id.name;
				sg_contr = BL_CreateMaterialIpo(m_action, mat, matname.hash(), m_obj, kxscene->GetSceneConverter());
				if (sg_contr) {
					m_sg_contr_list.push_back(sg_contr);
					m_obj->GetSGNode()->AddSGController(sg_contr);
					sg_contr->SetObject(m_obj->GetSGNode());
				}
			}
		}
	}

	// Extra controllers
	if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
	{
		sg_contr = BL_CreateLampIPO(m_action, m_obj, kxscene->GetSceneConverter());
		m_sg_contr_list.push_back(sg_contr);
		m_obj->GetSGNode()->AddSGController(sg_contr);
		sg_contr->SetObject(m_obj->GetSGNode());
	}
	else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
	{
		sg_contr = BL_CreateCameraIPO(m_action, m_obj, kxscene->GetSceneConverter());
		m_sg_contr_list.push_back(sg_contr);
		m_obj->GetSGNode()->AddSGController(sg_contr);
		sg_contr->SetObject(m_obj->GetSGNode());
	}
	
	m_ipo_flags = ipo_flags;
	InitIPO();

	// Setup blendin shapes/poses
	if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
	{
		BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
		obj->GetMRDPose(&m_blendinpose);
	}
	else
	{
		BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
		BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
		
		if (shape_deformer && shape_deformer->GetKey())
		{
			obj->GetShape(m_blendinshape);

			// Now that we have the previous blend shape saved, we can clear out the key to avoid any
			// further interference.
			KeyBlock *kb;
			for (kb=(KeyBlock *)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock *)kb->next)
				kb->curval = 0.f;
		}
	}

	// Now that we have an action, we have something we can play
	m_starttime = -1.f; // We get the start time on our first update
	m_startframe = m_localtime = start;
	m_endframe = end;
	m_blendin = blendin;
	m_playmode = play_mode;
	m_endtime = 0.f;
	m_blendframe = 0.f;
	m_blendstart = 0.f;
	m_speed = playback_speed;
	m_layer_weight = layer_weight;
	
	m_done = false;

	return true;
}
static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
	SpaceNode *snode = CTX_wm_space_node(C);
	Scene *scene = CTX_data_scene(C);
	Object *ob = OBACT;
	Tex *tx = NULL;

	if (snode->texfrom == SNODE_TEX_OBJECT) {
		if (ob) {
			tx = give_current_object_texture(ob);
			if (tx) {
				if (ob->type == OB_LAMP)
					*r_from = (ID *)ob->data;
				else
					*r_from = (ID *)give_current_material(ob, ob->actcol);
				
				/* from is not set fully for material nodes, should be ID + Node then */
				*r_id = &tx->id;
				*r_ntree = tx->nodetree;
			}
		}
	}
	else if (snode->texfrom == SNODE_TEX_WORLD) {
		if (scene->world) {
			*r_from = (ID *)scene->world;
			tx = give_current_world_texture(scene->world);
			if (tx) {
				*r_id = &tx->id;
				*r_ntree = tx->nodetree;
			}
		}
	}
	else if (snode->texfrom == SNODE_TEX_BRUSH) {
		struct Brush *brush = NULL;
		
		if (ob && (ob->mode & OB_MODE_SCULPT))
			brush = BKE_paint_brush(&scene->toolsettings->sculpt->paint);
		else
			brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);

		if (brush) {
			*r_from = (ID *)brush;
			tx = give_current_brush_texture(brush);
			if (tx) {
				*r_id = &tx->id;
				*r_ntree = tx->nodetree;
			}
		}
	}
	else if (snode->texfrom == SNODE_TEX_LINESTYLE) {
		FreestyleLineStyle *linestyle = BKE_linestyle_active_from_scene(scene);
		if (linestyle) {
			*r_from = (ID *)linestyle;
			tx = give_current_linestyle_texture(linestyle);
			if (tx) {
				*r_id = &tx->id;
				*r_ntree = tx->nodetree;
			}
		}
	}
}
예제 #16
0
/* settings: 1 - preview, 2 - render
 *
 * The convention goes as following:
 *
 * - Passing original object with apply_modifiers=false will give a
 *   non-modified non-deformed mesh.
 *   The result mesh will point to datablocks from the original "domain". For
 *   example, materials will be original.
 *
 * - Passing original object with apply_modifiers=true will give a mesh which
 *   has all modifiers applied.
 *   The result mesh will point to datablocks from the original "domain". For
 *   example, materials will be original.
 *
 * - Passing evaluated object will ignore apply_modifiers argument, and the
 *   result always contains all modifiers applied.
 *   The result mesh will point to an evaluated datablocks. For example,
 *   materials will be an evaluated IDs from the dependency graph.
 */
Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph,
                               Main *bmain,
                               Scene *sce,
                               Object *ob,
                               const bool apply_modifiers,
                               const bool calc_undeformed)
{
  Mesh *tmpmesh;
  Curve *tmpcu = NULL, *copycu;
  int i;
  const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
  bool effective_apply_modifiers = apply_modifiers;
  bool do_mat_id_data_us = true;

  Object *object_input = ob;
  Object *object_eval = DEG_get_evaluated_object(depsgraph, object_input);
  Object object_for_eval;

  if (object_eval == object_input) {
    /* Evaluated mesh contains all modifiers applied already.
     * The other types of object has them applied, but are stored in other
     * data structures than a mesh. So need to apply modifiers again on a
     * temporary copy before converting result to mesh. */
    if (object_input->type == OB_MESH) {
      effective_apply_modifiers = false;
    }
    else {
      effective_apply_modifiers = true;
    }
    object_for_eval = *object_eval;
  }
  else {
    if (apply_modifiers) {
      object_for_eval = *object_eval;
      if (object_for_eval.runtime.mesh_orig != NULL) {
        object_for_eval.data = object_for_eval.runtime.mesh_orig;
      }
    }
    else {
      object_for_eval = *object_input;
    }
  }

  const bool cage = !effective_apply_modifiers;

  /* perform the mesh extraction based on type */
  switch (object_for_eval.type) {
    case OB_FONT:
    case OB_CURVE:
    case OB_SURF: {
      ListBase dispbase = {NULL, NULL};
      Mesh *me_eval_final = NULL;
      int uv_from_orco;

      /* copies object and modifiers (but not the data) */
      Object *tmpobj;
      BKE_id_copy_ex(NULL, &object_for_eval.id, (ID **)&tmpobj, LIB_ID_COPY_LOCALIZE);
      tmpcu = (Curve *)tmpobj->data;

      /* Copy cached display list, it might be needed by the stack evaluation.
       * Ideally stack should be able to use render-time display list, but doing
       * so is quite tricky and not safe so close to the release.
       *
       * TODO(sergey): Look into more proper solution.
       */
      if (object_for_eval.runtime.curve_cache != NULL) {
        if (tmpobj->runtime.curve_cache == NULL) {
          tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache),
                                                    "CurveCache for curve types");
        }
        BKE_displist_copy(&tmpobj->runtime.curve_cache->disp,
                          &object_for_eval.runtime.curve_cache->disp);
      }

      /* if getting the original caged mesh, delete object modifiers */
      if (cage) {
        BKE_object_free_modifiers(tmpobj, LIB_ID_CREATE_NO_USER_REFCOUNT);
      }

      /* copies the data, but *not* the shapekeys. */
      BKE_id_copy_ex(NULL, object_for_eval.data, (ID **)&copycu, LIB_ID_COPY_LOCALIZE);
      tmpobj->data = copycu;

      /* make sure texture space is calculated for a copy of curve,
       * it will be used for the final result.
       */
      BKE_curve_texspace_calc(copycu);

      /* temporarily set edit so we get updates from edit mode, but
       * also because for text datablocks copying it while in edit
       * mode gives invalid data structures */
      copycu->editfont = tmpcu->editfont;
      copycu->editnurb = tmpcu->editnurb;

      /* get updated display list, and convert to a mesh */
      BKE_displist_make_curveTypes_forRender(
          depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, NULL);

      copycu->editfont = NULL;
      copycu->editnurb = NULL;

      tmpobj->runtime.mesh_eval = me_eval_final;

      /* convert object type to mesh */
      uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
      BKE_mesh_from_nurbs_displist(
          bmain, tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2, true);
      /* Function above also frees copycu (aka tmpobj->data), make this obvious here. */
      copycu = NULL;

      tmpmesh = tmpobj->data;
      id_us_min(
          &tmpmesh->id); /* Gets one user from its creation in BKE_mesh_from_nurbs_displist(). */

      BKE_displist_free(&dispbase);

      /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked.
       * if it didn't the curve did not have any segments or otherwise
       * would have generated an empty mesh */
      if (tmpobj->type != OB_MESH) {
        BKE_id_free(NULL, tmpobj);
        return NULL;
      }

      BKE_id_free(NULL, tmpobj);

      /* XXX The curve to mesh conversion is convoluted...
       *     But essentially, BKE_mesh_from_nurbs_displist()
       *     already transfers the ownership of materials from the temp copy of the Curve ID to the
       *     new Mesh ID, so we do not want to increase materials' usercount later. */
      do_mat_id_data_us = false;

      break;
    }

    case OB_MBALL: {
      /* metaballs don't have modifiers, so just convert to mesh */
      Object *basis_ob = BKE_mball_basis_find(sce, object_input);
      /* todo, re-generatre for render-res */
      /* metaball_polygonize(scene, ob) */

      if (basis_ob != object_input) {
        /* Only do basis metaball. */
        return NULL;
      }

      tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2);
      /* BKE_mesh_add gives us a user count we don't need */
      id_us_min(&tmpmesh->id);

      if (render) {
        ListBase disp = {NULL, NULL};
        BKE_displist_make_mball_forRender(depsgraph, sce, &object_for_eval, &disp);
        BKE_mesh_from_metaball(&disp, tmpmesh);
        BKE_displist_free(&disp);
      }
      else {
        ListBase disp = {NULL, NULL};
        if (object_for_eval.runtime.curve_cache) {
          disp = object_for_eval.runtime.curve_cache->disp;
        }
        BKE_mesh_from_metaball(&disp, tmpmesh);
      }

      BKE_mesh_texspace_copy_from_object(tmpmesh, &object_for_eval);

      break;
    }
    case OB_MESH:
      /* copies object and modifiers (but not the data) */
      if (cage) {
        /* copies the data (but *not* the shapekeys). */
        Mesh *mesh = object_for_eval.data;
        BKE_id_copy_ex(bmain, &mesh->id, (ID **)&tmpmesh, 0);
        /* XXX BKE_mesh_copy() already handles materials usercount. */
        do_mat_id_data_us = false;
      }
      /* if not getting the original caged mesh, get final derived mesh */
      else {
        /* Make a dummy mesh, saves copying */
        Mesh *me_eval;
        CustomData_MeshMasks mask = CD_MASK_MESH; /* this seems more suitable, exporter,
                                                   * for example, needs CD_MASK_MDEFORMVERT */

        if (calc_undeformed) {
          mask.vmask |= CD_MASK_ORCO;
        }

        if (render) {
          me_eval = mesh_create_eval_final_render(depsgraph, sce, &object_for_eval, &mask);
        }
        else {
          me_eval = mesh_create_eval_final_view(depsgraph, sce, &object_for_eval, &mask);
        }

        tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2);
        BKE_mesh_nomain_to_mesh(me_eval, tmpmesh, &object_for_eval, &mask, true);

        /* Copy autosmooth settings from original mesh. */
        Mesh *me = (Mesh *)object_for_eval.data;
        tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH);
        tmpmesh->smoothresh = me->smoothresh;
      }

      /* BKE_mesh_add/copy gives us a user count we don't need */
      id_us_min(&tmpmesh->id);

      break;
    default:
      /* "Object does not have geometry data") */
      return NULL;
  }

  /* Copy materials to new mesh */
  switch (object_for_eval.type) {
    case OB_SURF:
    case OB_FONT:
    case OB_CURVE:
      tmpmesh->totcol = tmpcu->totcol;

      /* free old material list (if it exists) and adjust user counts */
      if (tmpcu->mat) {
        for (i = tmpcu->totcol; i-- > 0;) {
          /* are we an object material or data based? */
          tmpmesh->mat[i] = give_current_material(object_input, i + 1);

          if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
              tmpmesh->mat[i]) {
            id_us_plus(&tmpmesh->mat[i]->id);
          }
        }
      }
      break;

    case OB_MBALL: {
      MetaBall *tmpmb = (MetaBall *)object_for_eval.data;
      tmpmesh->mat = MEM_dupallocN(tmpmb->mat);
      tmpmesh->totcol = tmpmb->totcol;

      /* free old material list (if it exists) and adjust user counts */
      if (tmpmb->mat) {
        for (i = tmpmb->totcol; i-- > 0;) {
          /* are we an object material or data based? */
          tmpmesh->mat[i] = give_current_material(object_input, i + 1);

          if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
              tmpmesh->mat[i]) {
            id_us_plus(&tmpmesh->mat[i]->id);
          }
        }
      }
      break;
    }

    case OB_MESH:
      if (!cage) {
        Mesh *origmesh = object_for_eval.data;
        tmpmesh->flag = origmesh->flag;
        tmpmesh->mat = MEM_dupallocN(origmesh->mat);
        tmpmesh->totcol = origmesh->totcol;
        tmpmesh->smoothresh = origmesh->smoothresh;
        if (origmesh->mat) {
          for (i = origmesh->totcol; i-- > 0;) {
            /* are we an object material or data based? */
            tmpmesh->mat[i] = give_current_material(object_input, i + 1);

            if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
                tmpmesh->mat[i]) {
              id_us_plus(&tmpmesh->mat[i]->id);
            }
          }
        }
      }
      break;
  } /* end copy materials */

  return tmpmesh;
}
예제 #17
0
void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
{
	bool all_uv_layers = !active_uv_only;
	COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();

	if (export_texture_type == BC_TEXTURE_TYPE_UV)
	{
		std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
		std::set<Image *>::iterator uv_images_iter;
		for (uv_images_iter = uv_images.begin();
			uv_images_iter != uv_images.end();
			uv_images_iter++) {
			Image *ima = *uv_images_iter;
			std::string matid(id_name(ima));
			matid = get_material_id_from_id(matid);
			std::ostringstream ostr;
			ostr << matid;
			COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));

			// create <bind_vertex_input> for each uv map
			Mesh *me = (Mesh *)ob->data;
			int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);

			int map_index = 0;
			int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
			for (int b = 0; b < totlayer; b++) {
				if (!active_uv_only || b == active_uv_index) {
					char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
					im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
				}
			}

			iml.push_back(im);
		}
	}

	else {
		for (int a = 0; a < ob->totcol; a++) {
			Material *ma = give_current_material(ob, a + 1);
			if (ma) {
				std::string matid(get_material_id(ma));
				matid = translate_id(matid);
				std::ostringstream ostr;
				ostr << matid;
				COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));

				// create <bind_vertex_input> for each uv map
				Mesh *me = (Mesh *)ob->data;
				int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);

				int map_index = 0;
				int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
				for (int b = 0; b < totlayer; b++) {
					if (!active_uv_only || b == active_uv_index) {
						char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
						im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
					}
				}

				iml.push_back(im);
			}
		}
	}
}
예제 #18
0
/* if all is good tag image and return true */
static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports)
{
	Image *image;
	void *lock;
	int i;

	if ((ob->lay & scene->lay) == 0) {
		BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not on a scene layer", ob->id.name + 2);
		return false;
	}

	if (ob->type != OB_MESH) {
		BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
		return false;
	}
	else {
		Mesh *me = (Mesh *)ob->data;

		if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
			BKE_reportf(reports, RPT_ERROR,
			            "No active UV layer found in the object \"%s\"", ob->id.name + 2);
			return false;
		}
	}

	for (i = 0; i < ob->totcol; i++) {
		bNodeTree *ntree = NULL;
		bNode *node = NULL;
		ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree);

		if (image) {
			ImBuf *ibuf;

			if (node) {
				if (BKE_node_is_connected_to_output(ntree, node)) {
					/* we don't return false since this may be a false positive
					 * this can't be RPT_ERROR though, otherwise it prevents
					 * multiple highpoly objects to be baked at once */
					BKE_reportf(reports, RPT_INFO,
					            "Circular dependency for image \"%s\" from object \"%s\"",
					            image->id.name + 2, ob->id.name + 2);
				}
			}

			ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);

			if (ibuf) {
				BKE_image_release_ibuf(image, ibuf, lock);
			}
			else {
				BKE_reportf(reports, RPT_ERROR,
				            "Uninitialized image \"%s\" from object \"%s\"",
				            image->id.name + 2, ob->id.name + 2);

				BKE_image_release_ibuf(image, ibuf, lock);
				return false;
			}
		}
		else {
			Material *mat = give_current_material(ob, i);
			if (mat != NULL) {
				BKE_reportf(reports, RPT_INFO,
				            "No active image found in material \"%s\" (%d) for object \"%s\"",
				            mat->id.name + 2, i, ob->id.name + 2);
			}
			else {
				BKE_reportf(reports, RPT_INFO,
				            "No active image found in material slot (%d) for object \"%s\"",
				            i, ob->id.name + 2);
			}
			continue;
		}

		image->id.tag |= LIB_TAG_DOIT;
	}
	return true;
}
예제 #19
0
/* This function is used to loop over the keyframe data in an Object */
static short ob_keyframes_loop(KeyframeEditData *ked, Object *ob, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int filterflag)
{
	Key *key= ob_get_key(ob);
	
	/* sanity check */
	if (ob == NULL)
		return 0;
	
	/* firstly, Object's own AnimData */
	if (ob->adt) {
		if (adt_keyframes_loop(ked, ob->adt, key_ok, key_cb, fcu_cb, filterflag))
			return 1;
	}
	
	/* shapekeys */
	if ((key && key->adt) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) {
		if (adt_keyframes_loop(ked, key->adt, key_ok, key_cb, fcu_cb, filterflag))
			return 1;
	}
		
	/* Add material keyframes */
	if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) {
		int a;
		
		for (a=1; a <= ob->totcol; a++) {
			Material *ma= give_current_material(ob, a);
			
			/* there might not be a material */
			if (ELEM(NULL, ma, ma->adt)) 
				continue;
			
			/* add material's data */
			if (adt_keyframes_loop(ked, ma->adt, key_ok, key_cb, fcu_cb, filterflag))
				return 1;
		}
	}
	
	/* Add object data keyframes */
	switch (ob->type) {
		case OB_CAMERA: /* ------- Camera ------------ */
		{
			Camera *ca= (Camera *)ob->data;
			
			if ((ca->adt) && !(filterflag & ADS_FILTER_NOCAM)) {
				if (adt_keyframes_loop(ked, ca->adt, key_ok, key_cb, fcu_cb, filterflag))
					return 1;
			}
		}
			break;
		case OB_LAMP: /* ---------- Lamp ----------- */
		{
			Lamp *la= (Lamp *)ob->data;
			
			if ((la->adt) && !(filterflag & ADS_FILTER_NOLAM)) {
				if (adt_keyframes_loop(ked, la->adt, key_ok, key_cb, fcu_cb, filterflag))
					return 1;
			}
		}
			break;
		case OB_CURVE: /* ------- Curve ---------- */
		case OB_SURF: /* ------- Nurbs Surface ---------- */
		case OB_FONT: /* ------- Text Curve ---------- */
		{
			Curve *cu= (Curve *)ob->data;
			
			if ((cu->adt) && !(filterflag & ADS_FILTER_NOCUR)) {
				if (adt_keyframes_loop(ked, cu->adt, key_ok, key_cb, fcu_cb, filterflag))
					return 1;
			}
		}
			break;
		case OB_MBALL: /* ------- MetaBall ---------- */
		{
			MetaBall *mb= (MetaBall *)ob->data;
			
			if ((mb->adt) && !(filterflag & ADS_FILTER_NOMBA)) {
				if (adt_keyframes_loop(ked, mb->adt, key_ok, key_cb, fcu_cb, filterflag))
					return 1;
			}
		}
			break;
		case OB_ARMATURE: /* ------- Armature ---------- */
		{
			bArmature *arm= (bArmature *)ob->data;
			
			if ((arm->adt) && !(filterflag & ADS_FILTER_NOARM)) {
				if (adt_keyframes_loop(ked, arm->adt, key_ok, key_cb, fcu_cb, filterflag))
					return 1;
			}
		}
			break;
		case OB_MESH: /* ------- Mesh ---------- */
		{
			Mesh *me= (Mesh *)ob->data;
			
			if ((me->adt) && !(filterflag & ADS_FILTER_NOMESH)) {
				if (adt_keyframes_loop(ked, me->adt, key_ok, key_cb, fcu_cb, filterflag))
					return 1;
			}
		}
			break;
		case OB_LATTICE: /* ---- Lattice ------ */
		{
			Lattice *lt= (Lattice *)ob->data;
			
			if ((lt->adt) && !(filterflag & ADS_FILTER_NOLAT)) {
				if (adt_keyframes_loop(ked, lt->adt, key_ok, key_cb, fcu_cb, filterflag))
					return 1;
			}
		}
			break;
	}
	
	/* Add Particle System Keyframes */
	if ((ob->particlesystem.first) && !(filterflag & ADS_FILTER_NOPART)) {
		ParticleSystem *psys = ob->particlesystem.first;
		
		for(; psys; psys=psys->next) {
			if (ELEM(NULL, psys->part, psys->part->adt))
				continue;
				
			if (adt_keyframes_loop(ked, psys->part->adt, key_ok, key_cb, fcu_cb, filterflag))
				return 1;
		}
	}
	
	return 0;
}
예제 #20
0
/* Iterate over the CSG Output Descriptors and create a new DerivedMesh
   from them */
static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
	CSG_FaceIteratorDescriptor *face_it,
	CSG_VertexIteratorDescriptor *vertex_it,
	float parinv[][4],
	float mapmat[][4],
	Material **mat,
	int *totmat,
	DerivedMesh *dm1,
	Object *ob1,
	DerivedMesh *dm2,
	Object *ob2)
{
	DerivedMesh *result, *orig_dm;
	GHash *material_hash = NULL;
	Mesh *me1= (Mesh*)ob1->data;
	Mesh *me2= (Mesh*)ob2->data;
	int i;

	// create a new DerivedMesh
	result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
	CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
					  CD_DEFAULT, face_it->num_elements); 
	CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
					  CD_DEFAULT, face_it->num_elements); 

	// step through the vertex iterators:
	for (i = 0; !vertex_it->Done(vertex_it->it); i++) {
		CSG_IVertex csgvert;
		MVert *mvert = CDDM_get_vert(result, i);

		// retrieve a csg vertex from the boolean module
		vertex_it->Fill(vertex_it->it, &csgvert);
		vertex_it->Step(vertex_it->it);

		// we have to map the vertex coordinates back in the coordinate frame
		// of the resulting object, since it was computed in world space
		mul_v3_m4v3(mvert->co, parinv, csgvert.position);
	}

	// a hash table to remap materials to indices
	if (mat) {
		material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "CSG_mat gh");
		*totmat = 0;
	}

	// step through the face iterators
	for(i = 0; !face_it->Done(face_it->it); i++) {
		Mesh *orig_me;
		Object *orig_ob;
		Material *orig_mat;
		CSG_IFace csgface;
		MFace *mface;
		int orig_index, mat_nr;

		// retrieve a csg face from the boolean module
		face_it->Fill(face_it->it, &csgface);
		face_it->Step(face_it->it);

		// find the original mesh and data
		orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2;
		orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2;
		orig_me = (orig_ob == ob1)? me1: me2;
		orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1);

		// copy all face layers, including mface
		CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1);

		// set mface
		mface = CDDM_get_face(result, i);
		mface->v1 = csgface.vertex_index[0];
		mface->v2 = csgface.vertex_index[1];
		mface->v3 = csgface.vertex_index[2];
		mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0;

		// set material, based on lookup in hash table
		orig_mat= give_current_material(orig_ob, mface->mat_nr+1);

		if (mat && orig_mat) {
			if (!BLI_ghash_haskey(material_hash, orig_mat)) {
				mat[*totmat] = orig_mat;
				mat_nr = mface->mat_nr = (*totmat)++;
				BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
			}
			else
				mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
		}
		else
			mface->mat_nr = 0;

		InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number,
					  (orig_me == me2)? mapmat: NULL);

		test_index_face(mface, &result->faceData, i, csgface.vertex_number);
	}

	if (material_hash)
		BLI_ghash_free(material_hash, NULL, NULL);

	CDDM_calc_edges(result);
	CDDM_calc_normals(result);

	return result;
}
예제 #21
0
/* call this with NULL to restore assigned ID pointers in preview scene */
static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
	Scene *sce;
	Base *base;
	
	if(pr_main==NULL) return NULL;
	
	sce= pr_main->scene.first;
	if(sce) {
		
		/* this flag tells render to not execute depsgraph or ipos etc */
		sce->r.scemode |= R_PREVIEWBUTS;
		/* set world always back, is used now */
		sce->world= pr_main->world.first;
		/* now: exposure copy */
		if(scene->world) {
			sce->world->exp= scene->world->exp;
			sce->world->range= scene->world->range;
		}
		
		sce->r.color_mgt_flag = scene->r.color_mgt_flag;
		
		/* prevent overhead for small renders and icons (32) */
		if(id && sp->sizex < 40)
			sce->r.xparts= sce->r.yparts= 1;
		else
			sce->r.xparts= sce->r.yparts= 4;
		
		/* exception: don't color manage texture previews or icons */
		if((id && sp->pr_method==PR_ICON_RENDER) || id_type == ID_TE)
			sce->r.color_mgt_flag &= ~R_COLOR_MANAGEMENT;
		
		if((id && sp->pr_method==PR_ICON_RENDER) && id_type != ID_WO)
			sce->r.alphamode= R_ALPHAPREMUL;
		else
			sce->r.alphamode= R_ADDSKY;

		sce->r.cfra= scene->r.cfra;
		strcpy(sce->r.engine, scene->r.engine);
		
		if(id_type==ID_MA) {
			Material *mat= NULL, *origmat= (Material *)id;
			
			if(origmat) {
				/* work on a copy */
				mat= localize_material(origmat);
				sp->matcopy= mat;
				BLI_addtail(&pr_main->mat, mat);
				
				init_render_material(mat, 0, NULL);		/* call that retrieves mode_l */
				end_render_material(mat);
				
				/* un-useful option */
				if(sp->pr_method==PR_ICON_RENDER)
					mat->shade_flag &= ~MA_OBCOLOR;

				/* turn on raytracing if needed */
				if(mat->mode_l & MA_RAYMIRROR)
					sce->r.mode |= R_RAYTRACE;
				if(mat->material_type == MA_TYPE_VOLUME)
					sce->r.mode |= R_RAYTRACE;
				if((mat->mode_l & MA_RAYTRANSP) && (mat->mode_l & MA_TRANSP))
					sce->r.mode |= R_RAYTRACE;
				if(preview_mat_has_sss(mat, NULL))
					sce->r.mode |= R_SSS;
				
				/* turn off fake shadows if needed */
				/* this only works in a specific case where the preview.blend contains
				 * an object starting with 'c' which has a material linked to it (not the obdata)
				 * and that material has a fake shadow texture in the active texture slot */
				for(base= sce->base.first; base; base= base->next) {
					if(base->object->id.name[2]=='c') {
						Material *shadmat= give_current_material(base->object, base->object->actcol);
						if(shadmat) {
							if (mat->mode & MA_SHADBUF) shadmat->septex = 0;
							else shadmat->septex |= 1;
						}
					}
				}
				
				/* turn off bounce lights for volume, 
				 * doesn't make much visual difference and slows it down too */
				if(mat->material_type == MA_TYPE_VOLUME) {
					for(base= sce->base.first; base; base= base->next) {
						if(base->object->type == OB_LAMP) {
							/* if doesn't match 'Lamp.002' --> main key light */
							if( strcmp(base->object->id.name+2, "Lamp.002") != 0 ) {
								base->object->restrictflag |= OB_RESTRICT_RENDER;
							}
						}
					}
				}

				
				if(sp->pr_method==PR_ICON_RENDER) {
					if (mat->material_type == MA_TYPE_HALO) {
						sce->lay= 1<<MA_FLAT;
					} 
					else {
						sce->lay= 1<<MA_SPHERE_A;
					}
				}
				else {
					sce->lay= 1<<mat->pr_type;
					if(mat->nodetree && sp->pr_method==PR_NODE_RENDER) {
						/* two previews, they get copied by wmJob */
						ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
						ntreeInitPreview(origmat->nodetree, sp->sizex, sp->sizey);
					}
				}
			}
			else {
				sce->r.mode &= ~(R_OSA|R_RAYTRACE|R_SSS);
				
			}
			
			for(base= sce->base.first; base; base= base->next) {
				if(base->object->id.name[2]=='p') {
					/* copy over object color, in case material uses it */
					copy_v4_v4(base->object->col, sp->col);
					
					if(ELEM4(base->object->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL)) {
						/* don't use assign_material, it changed mat->id.us, which shows in the UI */
						Material ***matar= give_matarar(base->object);
						int actcol= MAX2(base->object->actcol > 0, 1) - 1;

						if(matar && actcol < base->object->totcol)
							(*matar)[actcol]= mat;
					} else if (base->object->type == OB_LAMP) {
						base->object->restrictflag &= ~OB_RESTRICT_RENDER;
					}
				}
			}
		}
		else if(id_type==ID_TE) {
			Tex *tex= NULL, *origtex= (Tex *)id;
			
			if(origtex) {
				tex= localize_texture(origtex);
				sp->texcopy= tex;
				BLI_addtail(&pr_main->tex, tex);
			}			
			sce->lay= 1<<MA_TEXTURE;
			
			for(base= sce->base.first; base; base= base->next) {
				if(base->object->id.name[2]=='t') {
					Material *mat= give_current_material(base->object, base->object->actcol);
					if(mat && mat->mtex[0]) {
						mat->mtex[0]->tex= tex;
						
						if(tex && sp->slot)
							mat->mtex[0]->which_output = sp->slot->which_output;
						
						/* show alpha in this case */
						if(tex==NULL || (tex->flag & TEX_PRV_ALPHA)) {
							mat->mtex[0]->mapto |= MAP_ALPHA;
							mat->alpha= 0.0f;
						}
						else {
							mat->mtex[0]->mapto &= ~MAP_ALPHA;
							mat->alpha= 1.0f;
						}
					}
				}
			}

			if(tex && tex->nodetree && sp->pr_method==PR_NODE_RENDER) {
				/* two previews, they get copied by wmJob */
				ntreeInitPreview(origtex->nodetree, sp->sizex, sp->sizey);
				ntreeInitPreview(tex->nodetree, sp->sizex, sp->sizey);
			}
		}
		else if(id_type==ID_LA) {
			Lamp *la= NULL, *origla= (Lamp *)id;

			/* work on a copy */
			if(origla) {
				la= localize_lamp(origla);
				sp->lampcopy= la;
				BLI_addtail(&pr_main->lamp, la);
			}
			
			if(la && la->type==LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
				sce->lay= 1<<MA_ATMOS;
				sce->world= scene->world;
				sce->camera= (Object *)BLI_findstring(&pr_main->object, "CameraAtmo", offsetof(ID, name)+2);
			}
			else {
				sce->lay= 1<<MA_LAMP;
				sce->world= NULL;
				sce->camera= (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name)+2);
			}
			sce->r.mode &= ~R_SHADOW;
			
			for(base= sce->base.first; base; base= base->next) {
				if(base->object->id.name[2]=='p') {
					if(base->object->type==OB_LAMP)
						base->object->data= la;
				}
			}
		}
		else if(id_type==ID_WO) {
			World *wrld= NULL, *origwrld= (World *)id;

			if(origwrld) {
				wrld= localize_world(origwrld);
				sp->worldcopy= wrld;
				BLI_addtail(&pr_main->world, wrld);
			}

			sce->lay= 1<<MA_SKY;
			sce->world= wrld;
		}
		
		return sce;
	}
	
	return NULL;
}
예제 #22
0
파일: BL_Action.cpp 프로젝트: UPBGE/blender
bool BL_Action::Play(const std::string& name,
					float start,
					float end,
					short priority,
					float blendin,
					short play_mode,
					float layer_weight,
					short ipo_flags,
					float playback_speed,
					short blend_mode)
{

	// Only start playing a new action if we're done, or if
	// the new action has a higher priority
	if (!IsDone() && priority > m_priority)
		return false;
	m_priority = priority;
	bAction* prev_action = m_action;

	KX_Scene* kxscene = m_obj->GetScene();

	// First try to load the action
	m_action = (bAction*)kxscene->GetLogicManager()->GetActionByName(name);
	if (!m_action)
	{
		CM_Error("failed to load action: " << name);
		m_done = true;
		return false;
	}

	// If we have the same settings, don't play again
	// This is to resolve potential issues with pulses on sensors such as the ones
	// reported in bug #29412. The fix is here so it works for both logic bricks and Python.
	// However, this may eventually lead to issues where a user wants to override an already
	// playing action with the same action and settings. If this becomes an issue,
	// then this fix may have to be re-evaluated.
	if (!IsDone() && m_action == prev_action && m_startframe == start && m_endframe == end
			&& m_priority == priority && m_speed == playback_speed)
		return false;

	// Keep a copy of the action for threading purposes
	if (m_tmpaction) {
		BKE_libblock_free(G.main, m_tmpaction);
		m_tmpaction = NULL;
	}
	m_tmpaction = BKE_action_copy(G.main, m_action);

	// First get rid of any old controllers
	ClearControllerList();

	// Create an SG_Controller
	SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, kxscene->GetSceneConverter());
	m_sg_contr_list.push_back(sg_contr);
	m_obj->GetSGNode()->AddSGController(sg_contr);
	sg_contr->SetObject(m_obj->GetSGNode());

	// World
	sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene->GetSceneConverter());
	if (sg_contr) {
		m_sg_contr_list.push_back(sg_contr);
		m_obj->GetSGNode()->AddSGController(sg_contr);
		sg_contr->SetObject(m_obj->GetSGNode());
	}

	// Try obcolor
	sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter());
	if (sg_contr) {
		m_sg_contr_list.push_back(sg_contr);
		m_obj->GetSGNode()->AddSGController(sg_contr);
		sg_contr->SetObject(m_obj->GetSGNode());
	}

	// Now try materials
	for (int matidx = 1; matidx <= m_obj->GetBlenderObject()->totcol; ++matidx) {
		Material *mat = give_current_material(m_obj->GetBlenderObject(), matidx);
		if (!mat) {
			continue;
		}

		KX_BlenderSceneConverter *converter = kxscene->GetSceneConverter();
		RAS_IPolyMaterial *polymat = converter->FindCachedPolyMaterial(kxscene, mat);
		if (!polymat) {
			continue;
		}

		sg_contr = BL_CreateMaterialIpo(m_action, mat, polymat, m_obj, converter);
		if (sg_contr) {
			m_sg_contr_list.push_back(sg_contr);
			m_obj->GetSGNode()->AddSGController(sg_contr);
			sg_contr->SetObject(m_obj->GetSGNode());
		}
	}

	// Extra controllers
	if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
	{
		sg_contr = BL_CreateLampIPO(m_action, m_obj, kxscene->GetSceneConverter());
		m_sg_contr_list.push_back(sg_contr);
		m_obj->GetSGNode()->AddSGController(sg_contr);
		sg_contr->SetObject(m_obj->GetSGNode());
	}
	else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
	{
		sg_contr = BL_CreateCameraIPO(m_action, m_obj, kxscene->GetSceneConverter());
		m_sg_contr_list.push_back(sg_contr);
		m_obj->GetSGNode()->AddSGController(sg_contr);
		sg_contr->SetObject(m_obj->GetSGNode());
	}
	
	m_ipo_flags = ipo_flags;
	InitIPO();

	// Setup blendin shapes/poses
	if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
	{
		BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
		obj->GetPose(&m_blendinpose);
	}
	else
	{
		BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
		BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
		
		if (shape_deformer && shape_deformer->GetKey())
		{
			obj->GetShape(m_blendinshape);

			// Now that we have the previous blend shape saved, we can clear out the key to avoid any
			// further interference.
			KeyBlock *kb;
			for (kb=(KeyBlock *)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock *)kb->next)
				kb->curval = 0.f;
		}
	}

	// Now that we have an action, we have something we can play
	m_starttime = KX_GetActiveEngine()->GetFrameTime() - kxscene->getSuspendedDelta();
	m_startframe = m_localframe = start;
	m_endframe = end;
	m_blendin = blendin;
	m_playmode = play_mode;
	m_blendmode = blend_mode;
	m_blendframe = 0.f;
	m_blendstart = 0.f;
	m_speed = playback_speed;
	m_layer_weight = layer_weight;
	
	m_done = false;
	m_appliedToObject = false;

	m_prevUpdate = -1.0f;

	return true;
}
예제 #23
0
파일: meshtools.c 프로젝트: BHCLL/blendocv
int join_mesh_exec(bContext *C, wmOperator *op)
{
	Main *bmain= CTX_data_main(C);
	Scene *scene= CTX_data_scene(C);
	Object *ob= CTX_data_active_object(C);
	Material **matar, *ma;
	Mesh *me;
	MVert *mvert, *mv;
	MEdge *medge = NULL;
	MFace *mface = NULL;
	Key *key, *nkey=NULL;
	KeyBlock *kb, *okb, *kbn;
	float imat[4][4], cmat[4][4], *fp1, *fp2, curpos;
	int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0;
	int vertofs, *matmap=NULL;
	int	i, j, index, haskey=0, edgeofs, faceofs;
	bDeformGroup *dg, *odg;
	MDeformVert *dvert;
	CustomData vdata, edata, fdata;

	if(scene->obedit) {
		BKE_report(op->reports, RPT_WARNING, "Cant join while in editmode");
		return OPERATOR_CANCELLED;
	}
	
	/* ob is the object we are adding geometry to */
	if(!ob || ob->type!=OB_MESH) {
		BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh");
		return OPERATOR_CANCELLED;
	}
	
	/* count & check */
	CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
		if(base->object->type==OB_MESH) {
			me= base->object->data;
			
			totvert+= me->totvert;
			totedge+= me->totedge;
			totface+= me->totface;
			totmat+= base->object->totcol;
			
			if(base->object == ob)
				ok= 1;
			
			/* check for shapekeys */
			if(me->key)
				haskey++;
		}
	}
	CTX_DATA_END;
	
	/* that way the active object is always selected */ 
	if(ok==0) {
		BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh");
		return OPERATOR_CANCELLED;
	}
	
	/* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */
	me= (Mesh *)ob->data;
	key= me->key;

	if(totvert==0 || totvert==me->totvert) {
		BKE_report(op->reports, RPT_WARNING, "No mesh data to join");
		return OPERATOR_CANCELLED;
	}
	
	if(totvert > MESH_MAX_VERTS) {
		BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is " STRINGIFY(MESH_MAX_VERTS), totvert);
		return OPERATOR_CANCELLED;		
	}

	/* new material indices and material array */
	matar= MEM_callocN(sizeof(void*)*totmat, "join_mesh matar");
	if (totmat) matmap= MEM_callocN(sizeof(int)*totmat, "join_mesh matmap");
	totcol= ob->totcol;
	
	/* obact materials in new main array, is nicer start! */
	for(a=0; a<ob->totcol; a++) {
		matar[a]= give_current_material(ob, a+1);
		id_us_plus((ID *)matar[a]);
		/* increase id->us : will be lowered later */
	}
	
	/* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders
	 * 	with arrays that are large enough to hold shapekey data for all meshes
	 * -	if destination mesh didn't have shapekeys, but we encountered some in the meshes we're 
	 *	joining, set up a new keyblock and assign to the mesh
	 */
	if(key) {
		/* make a duplicate copy that will only be used here... (must remember to free it!) */
		nkey= copy_key(key);
		
		/* for all keys in old block, clear data-arrays */
		for(kb= key->block.first; kb; kb= kb->next) {
			if(kb->data) MEM_freeN(kb->data);
			kb->data= MEM_callocN(sizeof(float)*3*totvert, "join_shapekey");
			kb->totelem= totvert;
			kb->weights= NULL;
		}
	}
	else if(haskey) {
		/* add a new key-block and add to the mesh */
		key= me->key= add_key((ID *)me);
		key->type = KEY_RELATIVE;
	}
	
	/* first pass over objects - copying materials and vertexgroups across */
	CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
		/* only act if a mesh, and not the one we're joining to */
		if((ob!=base->object) && (base->object->type==OB_MESH)) {
			me= base->object->data;
			
			/* Join this object's vertex groups to the base one's */
			for(dg=base->object->defbase.first; dg; dg=dg->next) {
				/* See if this group exists in the object (if it doesn't, add it to the end) */
				if(!defgroup_find_name(ob, dg->name)) {
					odg = MEM_callocN(sizeof(bDeformGroup), "join deformGroup");
					memcpy(odg, dg, sizeof(bDeformGroup));
					BLI_addtail(&ob->defbase, odg);
				}
			}
			if(ob->defbase.first && ob->actdef==0)
				ob->actdef=1;
			
			
			if(me->totvert) {
				/* Add this object's materials to the base one's if they don't exist already (but only if limits not exceeded yet) */
				if(totcol < MAXMAT) {
					for(a=1; a<=base->object->totcol; a++) {
						ma= give_current_material(base->object, a);

						for(b=0; b<totcol; b++) {
							if(ma == matar[b]) break;
						}
						if(b==totcol) {
							matar[b]= ma;
							if(ma) {
								id_us_plus(&ma->id);
							}
							totcol++;
						}
						if(totcol >= MAXMAT)
							break;
					}
				}
				
				/* if this mesh has shapekeys, check if destination mesh already has matching entries too */
				if(me->key && key) {
					for(kb= me->key->block.first; kb; kb= kb->next) {
						/* if key doesn't exist in destination mesh, add it */
						if(key_get_named_keyblock(key, kb->name) == NULL) {
							/* copy this existing one over to the new shapekey block */
							kbn= MEM_dupallocN(kb);
							kbn->prev= kbn->next= NULL;
							
							/* adjust adrcode and other settings to fit (allocate a new data-array) */
							kbn->data= MEM_callocN(sizeof(float)*3*totvert, "joined_shapekey");
							kbn->totelem= totvert;
							kbn->weights= NULL;
							
							okb= key->block.last;
							curpos= (okb) ? okb->pos : -0.1f;
							if(key->type == KEY_RELATIVE)
								kbn->pos= curpos + 0.1f;
							else
								kbn->pos= curpos;
							
							BLI_addtail(&key->block, kbn);
							kbn->adrcode= key->totkey;
							key->totkey++;
							if(key->totkey==1) key->refkey= kbn;
							
							// XXX 2.5 Animato
#if 0
							/* also, copy corresponding ipo-curve to ipo-block if applicable */
							if(me->key->ipo && key->ipo) {
								// FIXME... this is a luxury item!
								puts("FIXME: ignoring IPO's when joining shapekeys on Meshes for now...");
							}
#endif
						}
					}
				}
			}
		}
	}
	CTX_DATA_END;
	
	/* setup new data for destination mesh */
	memset(&vdata, 0, sizeof(vdata));
	memset(&edata, 0, sizeof(edata));
	memset(&fdata, 0, sizeof(fdata));
	
	mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
	medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
	mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);

	vertofs= 0;
	edgeofs= 0;
	faceofs= 0;
	
	/* inverse transform for all selected meshes in this object */
	invert_m4_m4(imat, ob->obmat);
	
	CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
		/* only join if this is a mesh */
		if(base->object->type==OB_MESH) {
			me= base->object->data;
			
			if(me->totvert) {
				/* standard data */
				CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
				CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert);
				
				/* vertex groups */
				dvert= CustomData_get(&vdata, vertofs, CD_MDEFORMVERT);
				
				/* NB: vertex groups here are new version */
				if(dvert) {
					for(i=0; i<me->totvert; i++) {
						for(j=0; j<dvert[i].totweight; j++) {
							/*	Find the old vertex group */
							odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr);
							if(odg) {
								/*	Search for a match in the new object, and set new index */
								for(dg=ob->defbase.first, index=0; dg; dg=dg->next, index++) {
									if(!strcmp(dg->name, odg->name)) {
										dvert[i].dw[j].def_nr = index;
										break;
									}
								}
							}
						}
					}
				}
				
				/* if this is the object we're merging into, no need to do anything */
				if(base->object != ob) {
					/* watch this: switch matmul order really goes wrong */
					mul_m4_m4m4(cmat, base->object->obmat, imat);
					
					/* transform vertex coordinates into new space */
					for(a=0, mv=mvert; a < me->totvert; a++, mv++) {
						mul_m4_v3(cmat, mv->co);
					}
					
					/* for each shapekey in destination mesh:
					 *	- if there's a matching one, copy it across (will need to transform vertices into new space...)
					 *	- otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
					 */
					if(key) {
						/* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
						for(kb= key->block.first; kb; kb= kb->next) {
							/* get pointer to where to write data for this mesh in shapekey's data array */
							fp1= ((float *)kb->data) + (vertofs*3);	
							
							/* check if this mesh has such a shapekey */
							okb= key_get_named_keyblock(me->key, kb->name);
							if(okb) {
								/* copy this mesh's shapekey to the destination shapekey (need to transform first) */
								fp2= ((float *)(okb->data));
								for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) {
									VECCOPY(fp1, fp2);
									mul_m4_v3(cmat, fp1);
								}
							}
							else {
								/* copy this mesh's vertex coordinates to the destination shapekey */
								mv= mvert;
								for(a=0; a < me->totvert; a++, fp1+=3, mv++) {
									VECCOPY(fp1, mv->co);
								}
							}
						}
					}
				}
				else {
					/* for each shapekey in destination mesh:
					 *	- if it was an 'original', copy the appropriate data from nkey
					 *	- otherwise, copy across plain coordinates (no need to transform coordinates)
					 */
					if(key) {
						for(kb= key->block.first; kb; kb= kb->next) {
							/* get pointer to where to write data for this mesh in shapekey's data array */
							fp1= ((float *)kb->data) + (vertofs*3);	
							
							/* check if this was one of the original shapekeys */
							okb= key_get_named_keyblock(nkey, kb->name);
							if(okb) {
								/* copy this mesh's shapekey to the destination shapekey */
								fp2= ((float *)(okb->data));
								for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) {
									VECCOPY(fp1, fp2);
								}
							}
							else {
								/* copy base-coordinates to the destination shapekey */
								mv= mvert;
								for(a=0; a < me->totvert; a++, fp1+=3, mv++) {
									VECCOPY(fp1, mv->co);
								}
							}
						}
					}
				}
				
				/* advance mvert pointer to end of base mesh's data */
				mvert+= me->totvert;
			}
			
			if(me->totface) {
				/* make mapping for materials */
				for(a=1; a<=base->object->totcol; a++) {
					ma= give_current_material(base->object, a);

					for(b=0; b<totcol; b++) {
						if(ma == matar[b]) {
							matmap[a-1]= b;
							break;
						}
					}
				}
				
				if(base->object!=ob)
					multiresModifier_prepare_join(scene, base->object, ob);

				CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
				CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface);
				
				for(a=0; a<me->totface; a++, mface++) {
					mface->v1+= vertofs;
					mface->v2+= vertofs;
					mface->v3+= vertofs;
					if(mface->v4) mface->v4+= vertofs;
					
					if (matmap)
						mface->mat_nr= matmap[(int)mface->mat_nr];
					else 
						mface->mat_nr= 0;
				}
				
				faceofs += me->totface;
			}
			
			if(me->totedge) {
				CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
				CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge);
				
				for(a=0; a<me->totedge; a++, medge++) {
					medge->v1+= vertofs;
					medge->v2+= vertofs;
				}
				
				edgeofs += me->totedge;
			}
			
			/* vertofs is used to help newly added verts be reattached to their edge/face 
			 * (cannot be set earlier, or else reattaching goes wrong)
			 */
			vertofs += me->totvert;
			
			/* free base, now that data is merged */
			if(base->object != ob)
				ED_base_object_free_and_unlink(bmain, scene, base);
		}
	}
	CTX_DATA_END;
	
	/* return to mesh we're merging to */
	me= ob->data;
	
	CustomData_free(&me->vdata, me->totvert);
	CustomData_free(&me->edata, me->totedge);
	CustomData_free(&me->fdata, me->totface);

	me->totvert= totvert;
	me->totedge= totedge;
	me->totface= totface;
	
	me->vdata= vdata;
	me->edata= edata;
	me->fdata= fdata;

	mesh_update_customdata_pointers(me);
	
	/* old material array */
	for(a=1; a<=ob->totcol; a++) {
		ma= ob->mat[a-1];
		if(ma) ma->id.us--;
	}
	for(a=1; a<=me->totcol; a++) {
		ma= me->mat[a-1];
		if(ma) ma->id.us--;
	}
	if(ob->mat) MEM_freeN(ob->mat);
	if(ob->matbits) MEM_freeN(ob->matbits);
	if(me->mat) MEM_freeN(me->mat);
	ob->mat= me->mat= NULL;
	ob->matbits= NULL;
	
	if(totcol) {
		me->mat= matar;
		ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar");
		ob->matbits= MEM_callocN(sizeof(char)*totcol, "join obmatbits");
	}
	else
		MEM_freeN(matar);
	
	ob->totcol= me->totcol= totcol;
	ob->colbits= 0;

	if (matmap) MEM_freeN(matmap);
	
	/* other mesh users */
	test_object_materials((ID *)me);
	
	/* free temp copy of destination shapekeys (if applicable) */
	if(nkey) {
		// XXX 2.5 Animato
#if 0
		/* free it's ipo too - both are not actually freed from memory yet as ID-blocks */
		if(nkey->ipo) {
			free_ipo(nkey->ipo);
			BLI_remlink(&bmain->ipo, nkey->ipo);
			MEM_freeN(nkey->ipo);
		}
#endif
		
		free_key(nkey);
		BLI_remlink(&bmain->key, nkey);
		MEM_freeN(nkey);
	}
	
	DAG_scene_sort(bmain, scene);	// removed objects, need to rebuild dag before editmode call

#if 0
	ED_object_enter_editmode(C, EM_WAITCURSOR);
	ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR|EM_DO_UNDO);
#else
	/* toggle editmode using lower level functions so this can be called from python */
	make_editMesh(scene, ob);
	load_editMesh(scene, ob);
	free_editMesh(me->edit_mesh);
	MEM_freeN(me->edit_mesh);
	me->edit_mesh= NULL;
	DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA);
#endif
	WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);

	return OPERATOR_FINISHED;
}
예제 #24
0
파일: drivers.c 프로젝트: azhugg/blendocv
/* Temporary wrapper for driver operators for buttons to make it easier to create
 * such drivers by rerouting all paths through the active object instead so that
 * they will get picked up by the dependency system.
 *
 * < C: context pointer - for getting active data 
 * <> ptr: RNA pointer for property's datablock. May be modified as result of path remapping.
 * < prop: RNA definition of property to add for
 *
 * > returns: MEM_alloc'd string representing the path to the property from the given PointerRNA
 */
static char *get_driver_path_hack (bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
	ID *id = (ID *)ptr->id.data;
	ScrArea *sa = CTX_wm_area(C);
	
	/* get standard path which may be extended */
	char *basepath = RNA_path_from_ID_to_property(ptr, prop);
	char *path = basepath; /* in case no remapping is needed */
	
	/* Remapping will only be performed in the Properties Editor, as only this 
	 * restricts the subspace of options to the 'active' data (a manageable state)
	 */
	// TODO: watch out for pinned context?
	if ((sa) && (sa->spacetype == SPACE_BUTS)) {
		Object *ob = CTX_data_active_object(C);
		
		if (ob && id) {
			/* only id-types which can be remapped to go through objects should be considered */
			switch (GS(id->name)) {
				case ID_MA: /* materials */
				{
					Material *ma = give_current_material(ob, ob->actcol);
					
					/* assumes: material will only be shown if it is active objects's active material it's ok */
					if ((ID*)ma == id) {
						/* create new path */
						// TODO: use RNA path functions to construct instead?
						path = BLI_sprintfN("material_slots[\"%s\"].material.%s",
							ma->id.name+2, basepath);
							
						/* free old one */
						MEM_freeN(basepath);
					}
				}
					break;
					
				case ID_TE: /* textures */
				{
					Material *ma = give_current_material(ob, ob->actcol);
					Tex *tex = give_current_material_texture(ma);
					
					/* assumes: texture will only be shown if it is active material's active texture it's ok */
					if ((ID*)tex == id) {
						/* create new path */
						// TODO: use RNA path functions to construct step by step instead?
						path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", 
							ma->id.name+2, tex->id.name+2, basepath);
							
						/* free old one */
						MEM_freeN(basepath);
					}
				}
					break;
			}
			
			/* fix RNA pointer, as we've now changed the ID root by changing the paths */
			if (basepath != path) {
				/* rebase provided pointer so that it starts from object... */
				RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr);
			}
		}
	}
	
	/* the path should now have been corrected for use */
	return path;
}