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;
}
int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
{
	SpaceButs *sbuts = CTX_wm_space_buts(C);
	ButsContextPath *path = sbuts ? sbuts->path : NULL;

	if (!path)
		return 0;

	/* here we handle context, getting data from precomputed path */
	if (CTX_data_dir(member)) {
		/* in case of new shading system we skip texture_slot, complex python
		 * UI script logic depends on checking if this is available */
		if (sbuts->texuser)
			CTX_data_dir_set(result, buttons_context_dir + 1);
		else
			CTX_data_dir_set(result, buttons_context_dir);
		return 1;
	}
	else if (CTX_data_equals(member, "scene")) {
		/* Do not return one here if scene not found in path, in this case we want to get default context scene! */
		return set_pointer_type(path, result, &RNA_Scene);
	}
	else if (CTX_data_equals(member, "world")) {
		set_pointer_type(path, result, &RNA_World);
		return 1;
	}
	else if (CTX_data_equals(member, "object")) {
		set_pointer_type(path, result, &RNA_Object);
		return 1;
	}
	else if (CTX_data_equals(member, "mesh")) {
		set_pointer_type(path, result, &RNA_Mesh);
		return 1;
	}
	else if (CTX_data_equals(member, "armature")) {
		set_pointer_type(path, result, &RNA_Armature);
		return 1;
	}
	else if (CTX_data_equals(member, "lattice")) {
		set_pointer_type(path, result, &RNA_Lattice);
		return 1;
	}
	else if (CTX_data_equals(member, "curve")) {
		set_pointer_type(path, result, &RNA_Curve);
		return 1;
	}
	else if (CTX_data_equals(member, "meta_ball")) {
		set_pointer_type(path, result, &RNA_MetaBall);
		return 1;
	}
	else if (CTX_data_equals(member, "lamp")) {
		set_pointer_type(path, result, &RNA_Lamp);
		return 1;
	}
	else if (CTX_data_equals(member, "camera")) {
		set_pointer_type(path, result, &RNA_Camera);
		return 1;
	}
	else if (CTX_data_equals(member, "speaker")) {
		set_pointer_type(path, result, &RNA_Speaker);
		return 1;
	}
	else if (CTX_data_equals(member, "material")) {
		set_pointer_type(path, result, &RNA_Material);
		return 1;
	}
	else if (CTX_data_equals(member, "texture")) {
		ButsContextTexture *ct = sbuts->texuser;

		if (ct) {
			/* new shading system */
			CTX_data_pointer_set(result, &ct->texture->id, &RNA_Texture, ct->texture);
		}
		else {
			/* old shading system */
			set_pointer_type(path, result, &RNA_Texture);
		}

		return 1;
	}
	else if (CTX_data_equals(member, "material_slot")) {
		PointerRNA *ptr = get_pointer_type(path, &RNA_Object);

		if (ptr) {
			Object *ob = ptr->data;

			if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) {
				/* a valid actcol isn't ensured [#27526] */
				int matnr = ob->actcol - 1;
				if (matnr < 0) matnr = 0;
				CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]);
			}
		}

		return 1;
	}
	else if (CTX_data_equals(member, "texture_user")) {
		ButsContextTexture *ct = sbuts->texuser;

		if (!ct)
			return -1;  /* old shading system (found but not available) */

		if (ct->user && ct->user->ptr.data) {
			ButsTextureUser *user = ct->user;
			CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data);
		}

		return 1;
	}
	else if (CTX_data_equals(member, "texture_user_property")) {
		ButsContextTexture *ct = sbuts->texuser;

		if (!ct)
			return -1;  /* old shading system (found but not available) */

		if (ct->user && ct->user->ptr.data) {
			ButsTextureUser *user = ct->user;
			CTX_data_pointer_set(result, NULL, &RNA_Property, user->prop);
		}

		return 1;
	}
	else if (CTX_data_equals(member, "texture_node")) {
		ButsContextTexture *ct = sbuts->texuser;

		if (ct) {
			/* new shading system */
			if (ct->user && ct->user->node) {
				CTX_data_pointer_set(result, &ct->user->ntree->id, &RNA_Node, ct->user->node);
			}

			return 1;
		}
		else {
			/* old shading system */
			PointerRNA *ptr;

			if ((ptr = get_pointer_type(path, &RNA_Material))) {
				Material *ma = ptr->data;

				if (ma) {
					bNode *node = give_current_material_texture_node(ma);
					CTX_data_pointer_set(result, &ma->nodetree->id, &RNA_Node, node);
				}
			}

			return 1;
		}
	}
	else if (CTX_data_equals(member, "texture_slot")) {
		ButsContextTexture *ct = sbuts->texuser;
		PointerRNA *ptr;

		/* Particles slots are used in both old and new textures handling. */
		if ((ptr = get_pointer_type(path, &RNA_ParticleSystem))) {
			ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;

			if (part)
				CTX_data_pointer_set(result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[(int)part->texact]);
		}
		else if (ct) {
			return 0;  /* new shading system */
		}
		else if ((ptr = get_pointer_type(path, &RNA_Material))) {
			Material *ma = ptr->data;

			/* if we have a node material, get slot from material in material node */
			if (ma && ma->use_nodes && ma->nodetree) {
				/* if there's an active texture node in the node tree,
				 * then that texture is in context directly, without a texture slot */
				if (give_current_material_texture_node(ma))
					return 0;

				ma = give_node_material(ma);
				if (ma)
					CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
				else
					return 0;
			}
			else if (ma) {
				CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
			}
		}
		else if ((ptr = get_pointer_type(path, &RNA_Lamp))) {
			Lamp *la = ptr->data;

			if (la)
				CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]);
		}
		else if ((ptr = get_pointer_type(path, &RNA_World))) {
			World *wo = ptr->data;

			if (wo)
				CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
		}
		else if ((ptr = get_pointer_type(path, &RNA_FreestyleLineStyle))) {
			FreestyleLineStyle *ls = ptr->data;

			if (ls)
				CTX_data_pointer_set(result, &ls->id, &RNA_LineStyleTextureSlot, ls->mtex[(int)ls->texact]);
		}

		return 1;
	}
	else if (CTX_data_equals(member, "bone")) {
		set_pointer_type(path, result, &RNA_Bone);
		return 1;
	}
	else if (CTX_data_equals(member, "edit_bone")) {
		set_pointer_type(path, result, &RNA_EditBone);
		return 1;
	}
	else if (CTX_data_equals(member, "pose_bone")) {
		set_pointer_type(path, result, &RNA_PoseBone);
		return 1;
	}
	else if (CTX_data_equals(member, "particle_system")) {
		set_pointer_type(path, result, &RNA_ParticleSystem);
		return 1;
	}
	else if (CTX_data_equals(member, "particle_system_editable")) {
		if (PE_poll((bContext *)C))
			set_pointer_type(path, result, &RNA_ParticleSystem);
		else
			CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
		return 1;
	}
	else if (CTX_data_equals(member, "particle_settings")) {
		/* only available when pinned */
		PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
		
		if (ptr && ptr->data) {
			CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data);
			return 1;
		}
		else {
			/* get settings from active particle system instead */
			ptr = get_pointer_type(path, &RNA_ParticleSystem);
			
			if (ptr && ptr->data) {
				ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
				CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part);
				return 1;
			}
		}
		set_pointer_type(path, result, &RNA_ParticleSettings);
		return 1;
	}
	else if (CTX_data_equals(member, "cloth")) {
		PointerRNA *ptr = get_pointer_type(path, &RNA_Object);

		if (ptr && ptr->data) {
			Object *ob = ptr->data;
			ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
			CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "soft_body")) {
		PointerRNA *ptr = get_pointer_type(path, &RNA_Object);

		if (ptr && ptr->data) {
			Object *ob = ptr->data;
			ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
			CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "fluid")) {
		PointerRNA *ptr = get_pointer_type(path, &RNA_Object);

		if (ptr && ptr->data) {
			Object *ob = ptr->data;
			ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
			CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
			return 1;
		}
	}
	
	else if (CTX_data_equals(member, "smoke")) {
		PointerRNA *ptr = get_pointer_type(path, &RNA_Object);

		if (ptr && ptr->data) {
			Object *ob = ptr->data;
			ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
			CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "collision")) {
		PointerRNA *ptr = get_pointer_type(path, &RNA_Object);

		if (ptr && ptr->data) {
			Object *ob = ptr->data;
			ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
			CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "brush")) {
		set_pointer_type(path, result, &RNA_Brush);
		return 1;
	}
	else if (CTX_data_equals(member, "dynamic_paint")) {
		PointerRNA *ptr = get_pointer_type(path, &RNA_Object);

		if (ptr && ptr->data) {
			Object *ob = ptr->data;
			ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint);
			CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md);
			return 1;
		}
	}
	else if (CTX_data_equals(member, "line_style")) {
		set_pointer_type(path, result, &RNA_FreestyleLineStyle);
		return 1;
	}
	else {
		return 0; /* not found */
	}

	return -1; /* found but not available */
}
/* call this with NULL to restore assigned ID pointers in preview scene */
static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
	Scene *sce;
	Base *base;
	Main *pr_main = sp->pr_main;

	memcpy(pr_main->name, bmain->name, sizeof(pr_main->name));

	sce = preview_get_scene(pr_main);
	if (sce) {
		
		/* this flag tells render to not execute depsgraph or ipos etc */
		sce->r.scemode |= R_BUTS_PREVIEW;
		/* 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 && !check_engine_supports_textures(scene)) {
			/* Force blender internal for texture icons and nodes render,
			 * seems commonly used render engines does not support
			 * such kind of rendering.
			 */
			BLI_strncpy(sce->r.engine, RE_engine_id_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->mode2 & MA_CASTSHADOW) shadmat->septex = 0;
								else shadmat->septex |= 1;
							}
						}
					}
					
					/* turn off bounce lights for volume, 
					 * doesn't make much visual difference and slows it down too */
					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 (!STREQ(base->object->id.name + 2, "Lamp.002")) {
								if (mat->material_type == MA_TYPE_VOLUME)
									base->object->restrictflag |= OB_RESTRICT_RENDER;
								else
									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 = BKE_texture_localize(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;
}
Example #4
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(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= 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;
}
Example #5
0
/* call this with NULL to restore assigned ID pointers in preview scene */
static Scene *preview_prepare_scene(
    Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
  Scene *sce;
  Main *pr_main = sp->pr_main;

  memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name));

  sce = preview_get_scene(pr_main);
  if (sce) {
    ViewLayer *view_layer = sce->view_layers.first;

    /* this flag tells render to not execute depsgraph or ipos etc */
    sce->r.scemode |= R_BUTS_PREVIEW;
    /* set world always back, is used now */
    sce->world = pr_main->worlds.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) {
      /* Texture is not actually rendered with engine, just set dummy value. */
      BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, 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 */
        BLI_assert(sp->id_copy != NULL);
        mat = sp->matcopy = (Material *)sp->id_copy;
        sp->id_copy = NULL;
        BLI_addtail(&pr_main->materials, mat);

        /* Use current scene world for lighting. */
        if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) {
          /* Use current scene world to light sphere. */
          sce->world = preview_get_localized_world(sp, scene->world);
        }
        else if (sce->world) {
          /* Use a default world color. Using the current
           * scene world can be slow if it has big textures. */
          sce->world->use_nodes = false;
          sce->world->horr = 0.05f;
          sce->world->horg = 0.05f;
          sce->world->horb = 0.05f;
        }

        if (sp->pr_method == PR_ICON_RENDER && sp->pr_main == G_pr_main_grease_pencil) {
          /* For grease pencil, always use sphere for icon renders. */
          set_preview_visibility(sce, view_layer, MA_SPHERE_A, sp->pr_method);
        }
        else {
          /* Use specified preview shape for both preview panel and icon previews. */
          set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
        }

        if (sp->pr_method != PR_ICON_RENDER) {
          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);
            /* WATCH: Accessing origmat is not safe! */
            BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true);
          }
        }
      }
      else {
        sce->display.render_aa = SCE_DISPLAY_AA_OFF;
      }

      for (Base *base = view_layer->object_bases.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->color, sp->color);

          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->flag |= BASE_VISIBLE;
          }
        }
      }
    }
    else if (id_type == ID_TE) {
      Tex *tex = NULL, *origtex = (Tex *)id;

      if (origtex) {
        BLI_assert(sp->id_copy != NULL);
        tex = sp->texcopy = (Tex *)sp->id_copy;
        sp->id_copy = NULL;
        BLI_addtail(&pr_main->textures, tex);
      }

      if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
        /* two previews, they get copied by wmJob */
        BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true);
        /* WATCH: Accessing origtex is not safe! */
        BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true);
      }
    }
    else if (id_type == ID_LA) {
      Light *la = NULL, *origla = (Light *)id;

      /* work on a copy */
      if (origla) {
        BLI_assert(sp->id_copy != NULL);
        la = sp->lampcopy = (Light *)sp->id_copy;
        sp->id_copy = NULL;
        BLI_addtail(&pr_main->lights, la);
      }

      set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);

      if (sce->world) {
        /* Only use lighting from the light. */
        sce->world->use_nodes = false;
        sce->world->horr = 0.0f;
        sce->world->horg = 0.0f;
        sce->world->horb = 0.0f;
      }

      for (Base *base = view_layer->object_bases.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(la->nodetree, sp->sizex, sp->sizey, true);
        /* WATCH: Accessing origla is not safe! */
        BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true);
      }
    }
    else if (id_type == ID_WO) {
      World *wrld = NULL, *origwrld = (World *)id;

      if (origwrld) {
        BLI_assert(sp->id_copy != NULL);
        wrld = sp->worldcopy = (World *)sp->id_copy;
        sp->id_copy = NULL;
        BLI_addtail(&pr_main->worlds, wrld);
      }

      set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
      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);
        /* WATCH: Accessing origwrld is not safe! */
        BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true);
      }
    }

    return sce;
  }

  return NULL;
}