static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **scene, SceneRenderLayer **srl)
{
	/* single layer re-render */
	if (RNA_struct_property_is_set(op->ptr, "scene")) {
		Scene *scn;
		char scene_name[MAX_ID_NAME - 2];

		RNA_string_get(op->ptr, "scene", scene_name);
		scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
		
		if (scn) {
			/* camera switch wont have updated */
			scn->r.cfra = (*scene)->r.cfra;
			BKE_scene_camera_switch_update(scn);

			*scene = scn;
		}
	}

	if (RNA_struct_property_is_set(op->ptr, "layer")) {
		SceneRenderLayer *rl;
		char rl_name[RE_MAXNAME];

		RNA_string_get(op->ptr, "layer", rl_name);
		rl = (SceneRenderLayer *)BLI_findstring(&(*scene)->r.layers, rl_name, offsetof(SceneRenderLayer, name));
		
		if (rl)
			*srl = rl;
	}
}
Beispiel #2
0
static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
{
  Main *bmain = CTX_data_main(C);
  const char *app_template = template_v;
  bool has_startup_items = false;

  wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true);
  WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template);
  WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template);

  if (startup_config) {
    for (WorkSpace *workspace = startup_config->workspaces.first; workspace;
         workspace = workspace->id.next) {
      uiLayout *row = uiLayoutRow(layout, false);
      if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
        uiLayoutSetActive(row, false);
      }

      workspace_append_button(row, ot_append, workspace, startup_config->main);
      has_startup_items = true;
    }
  }

  if (builtin_config) {
    bool has_title = false;

    for (WorkSpace *workspace = builtin_config->workspaces.first; workspace;
         workspace = workspace->id.next) {
      if (startup_config &&
          BLI_findstring(&startup_config->workspaces, workspace->id.name, offsetof(ID, name))) {
        continue;
      }

      if (!has_title) {
        if (has_startup_items) {
          uiItemS(layout);
        }
        has_title = true;
      }

      uiLayout *row = uiLayoutRow(layout, false);
      if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
        uiLayoutSetActive(row, false);
      }

      workspace_append_button(row, ot_append, workspace, builtin_config->main);
    }
  }

  if (startup_config) {
    BKE_blendfile_workspace_config_data_free(startup_config);
  }
  if (builtin_config) {
    BKE_blendfile_workspace_config_data_free(builtin_config);
  }
}
bool RE_RenderResult_is_stereo(RenderResult *res)
{
	if (! BLI_findstring(&res->views, STEREO_LEFT_NAME, offsetof(RenderView, name)))
		return false;

	if (! BLI_findstring(&res->views, STEREO_RIGHT_NAME, offsetof(RenderView, name)))
		return false;

	return true;
}
Beispiel #4
0
static int workspace_append_activate_exec(bContext *C, wmOperator *op)
{
  Main *bmain = CTX_data_main(C);
  char idname[MAX_ID_NAME - 2], filepath[FILE_MAX];

  if (!RNA_struct_property_is_set(op->ptr, "idname") ||
      !RNA_struct_property_is_set(op->ptr, "filepath")) {
    return OPERATOR_CANCELLED;
  }
  RNA_string_get(op->ptr, "idname", idname);
  RNA_string_get(op->ptr, "filepath", filepath);

  if (workspace_append(C, filepath, idname) != OPERATOR_CANCELLED) {
    WorkSpace *appended_workspace = BLI_findstring(
        &bmain->workspaces, idname, offsetof(ID, name) + 2);
    BLI_assert(appended_workspace != NULL);

    if (appended_workspace) {
      /* Reorder to last position. */
      BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);

      /* Changing workspace changes context. Do delayed! */
      WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);

      return OPERATOR_FINISHED;
    }
  }

  return OPERATOR_CANCELLED;
}
Beispiel #5
0
/* (currently used for action constraints and in rebuild_pose) */
bPoseChannel *verify_pose_channel(bPose *pose, const char *name)
{
	bPoseChannel *chan;
	
	if (pose == NULL)
		return NULL;
	
	/* See if this channel exists */
	chan= BLI_findstring(&pose->chanbase, name, offsetof(bPoseChannel, name));
	if(chan) {
		return chan;
	}

	/* If not, create it and add it */
	chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
	
	BLI_strncpy(chan->name, name, sizeof(chan->name));
	/* init vars to prevent math errors */
	unit_qt(chan->quat);
	unit_axis_angle(chan->rotAxis, &chan->rotAngle);
	chan->size[0] = chan->size[1] = chan->size[2] = 1.0f;
	
	chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f;
	chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f;
	chan->stiffness[0]= chan->stiffness[1]= chan->stiffness[2]= 0.0f;
	chan->ikrotweight = chan->iklinweight = 0.0f;
	unit_m4(chan->constinv);
	
	chan->protectflag = OB_LOCK_ROT4D;	/* lock by components by default */
	
	BLI_addtail(&pose->chanbase, chan);
	free_pose_channels_hash(pose);
	
	return chan;
}
Beispiel #6
0
void wm_file_read_report(bContext *C)
{
	ReportList *reports = NULL;
	Scene *sce;

	for (sce = G.main->scene.first; sce; sce = sce->id.next) {
		if (sce->r.engine[0] &&
		    BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL)
		{
			if (reports == NULL) {
				reports = CTX_wm_reports(C);
			}

			BKE_reportf(reports, RPT_ERROR,
			            "Engine '%s' not available for scene '%s' "
			            "(an addon may need to be installed or enabled)",
			            sce->r.engine, sce->id.name + 2);
		}
	}

	if (reports) {
		if (!G.background) {
			WM_report_banner_show();
		}
	}
}
Beispiel #7
0
static int set_engine(int argc, const char **argv, void *data)
{
	bContext *C = data;
	if (argc >= 2) {
		if (!strcmp(argv[1], "help")) {
			RenderEngineType *type = NULL;
			printf("Blender Engine Listing:\n");
			for (type = R_engines.first; type; type = type->next) {
				printf("\t%s\n", type->idname);
			}
			exit(0);
		}
		else {
			Scene *scene = CTX_data_scene(C);
			if (scene) {
				RenderData *rd = &scene->r;

				if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
					BLI_strncpy_utf8(rd->engine, argv[1], sizeof(rd->engine));
				}
			}
			else {
				printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
			}
		}

		return 1;
	}
	else {
		printf("\nEngine not specified, give 'help' for a list of available engines.\n");
		return 0;
	}
}
Beispiel #8
0
PyObject *bpy_text_import_name(const char *name, int *found)
{
	Text *text;
	char txtname[MAX_ID_NAME - 2];
	int namelen = strlen(name);
//XXX	Main *maggie = bpy_import_main ? bpy_import_main:G.main;
	Main *maggie = bpy_import_main;
	
	*found = 0;

	if (!maggie) {
		printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
		return NULL;
	}

	/* we know this cant be importable, the name is too long for blender! */
	if (namelen >= (MAX_ID_NAME - 2) - 3) return NULL;

	memcpy(txtname, name, namelen);
	memcpy(&txtname[namelen], ".py", 4);

	text = BLI_findstring(&maggie->text, txtname, offsetof(ID, name) + 2);

	if (!text)
		return NULL;
	else
		*found = 1;
	
	return bpy_text_import(text);
}
static void *ml_addview_cb(void *base, const char *str)
{
	RenderResult *rr = base;
	RenderView *rv;

	rv = MEM_callocN(sizeof(RenderView), "new render view");
	BLI_strncpy(rv->name, str, EXR_VIEW_MAXNAME);

	/* For stereo drawing we need to ensure:
	 * STEREO_LEFT_NAME  == STEREO_LEFT_ID and
	 * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */

	if (STREQ(str, STEREO_LEFT_NAME)) {
		BLI_addhead(&rr->views, rv);
	}
	else if (STREQ(str, STEREO_RIGHT_NAME)) {
		RenderView *left_rv = BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name));

		if (left_rv == NULL) {
			BLI_addhead(&rr->views, rv);
		}
		else {
			BLI_insertlinkafter(&rr->views, left_rv, rv);
		}
	}
	else {
		BLI_addtail(&rr->views, rv);
	}

	return rv;
}
Beispiel #10
0
/* Find a group with the given name */
bActionGroup *BKE_action_group_find_name(bAction *act, const char name[])
{
	/* sanity checks */
	if (ELEM(NULL, act, act->groups.first, name) || (name[0] == 0))
		return NULL;
		
	/* do string comparisons */
	return BLI_findstring(&act->groups, name, offsetof(bActionGroup, name));
}
Beispiel #11
0
/* Find KeyingSet type info given a name */
KeyingSetInfo *ANIM_keyingset_info_find_name(const char name[])
{
	/* sanity checks */
	if ((name == NULL) || (name[0] == 0))
		return NULL;
		
	/* search by comparing names */
	return BLI_findstring(&keyingset_type_infos, name, offsetof(KeyingSetInfo, idname));
}
Beispiel #12
0
RenderEngineType *RE_engines_find(const char *idname)
{
	RenderEngineType *type;
	
	type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
	if (!type)
		type = &internal_render_type;
	
	return type;
}
Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String &name)
{
	Scene *sce;

	/**
	 * Find the specified scene by name, or NULL if nothing matches.
	 */
	if ((sce = (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
		return sce;

	for (vector<Main *>::iterator it=m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) {
		Main *main = *it;

		if ((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
			return sce;
	}

	return NULL;
}
Beispiel #14
0
/**
 * Return a pointer to the pose channel of the given name
 * from this pose.
 */
bPoseChannel *BKE_pose_channel_find_name(const bPose *pose, const char *name)
{
	if (ELEM(NULL, pose, name) || (name[0] == '\0'))
		return NULL;
	
	if (pose->chanhash)
		return BLI_ghash_lookup(pose->chanhash, (const void *)name);
	
	return BLI_findstring(&((const bPose *)pose)->chanbase, name, offsetof(bPoseChannel, name));
}
static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
{
	Scene *scene = CTX_data_scene(C);
	bGPDlayer *gpl;
	bGPDframe *gpf;
	bGPDstroke *gps;
	RulerItem *ruler_item;
	const char *ruler_name = RULER_ID;
	bool changed = false;

	if (scene->gpd == NULL) {
		scene->gpd = gpencil_data_addnew("GPencil");
	}

	gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
	if (gpl == NULL) {
		gpl = gpencil_layer_addnew(scene->gpd, ruler_name, false);
		gpl->thickness = 1;
		gpl->flag |= GP_LAYER_HIDE;
	}

	gpf = gpencil_layer_getframe(gpl, CFRA, true);
	free_gpencil_strokes(gpf);

	for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) {
		bGPDspoint *pt;
		int j;

		/* allocate memory for a new stroke */
		gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
		if (ruler_item->flag & RULERITEM_USE_ANGLE) {
			gps->totpoints = 3;
			pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
			for (j = 0; j < 3; j++) {
				copy_v3_v3(&pt->x, ruler_item->co[j]);
				pt->pressure = 1.0f;
				pt++;
			}
		}
		else {
			gps->totpoints = 2;
			pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
			for (j = 0; j < 3; j += 2) {
				copy_v3_v3(&pt->x, ruler_item->co[j]);
				pt->pressure = 1.0f;
				pt++;
			}
		}
		gps->flag = GP_STROKE_3DSPACE;
		BLI_addtail(&gpf->strokes, gps);
		changed = true;
	}

	return changed;
}
Beispiel #16
0
PyObject *bpy_text_reimport(PyObject *module, int *found)
{
	Text *text;
	const char *name;
	char *filepath;
	char *buf = NULL;
//XXX	Main *maggie = bpy_import_main ? bpy_import_main:G.main;
	Main *maggie = bpy_import_main;
	
	if (!maggie) {
		printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
		return NULL;
	}
	
	*found = 0;
	
	/* get name, filename from the module itself */
	if ((name = PyModule_GetName(module)) == NULL)
		return NULL;

	if ((filepath = (char *)PyModule_GetFilename(module)) == NULL)
		return NULL;

	/* look up the text object */
	text = BLI_findstring(&maggie->text, BLI_path_basename(filepath), offsetof(ID, name) + 2);

	/* uh-oh.... didn't find it */
	if (!text)
		return NULL;
	else
		*found = 1;

	/* if previously compiled, free the object */
	/* (can't see how could be NULL, but check just in case) */ 
	if (text->compiled) {
		Py_DECREF((PyObject *)text->compiled);
	}

	/* compile the buffer */
	buf = txt_to_buf(text);
	text->compiled = Py_CompileString(buf, text->id.name + 2, Py_file_input);
	MEM_freeN(buf);

	/* if compile failed.... return this error */
	if (PyErr_Occurred()) {
		PyErr_Print();
		PyErr_Clear();
		PySys_SetObject("last_traceback", NULL);
		free_compiled_text(text);
		return NULL;
	}

	/* make into a module */
	return PyImport_ExecCodeModule((char *)name, text->compiled);
}
/* XXX: read a style configure */
uiStyle *UI_style_get(void)
{
#if 0
	uiStyle *style = NULL;
	/* offset is two struct uiStyle pointers */
	style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2);
	return (style != NULL) ? style : U.uistyles.first;
#else
	return U.uistyles.first;
#endif
}
Beispiel #18
0
static wmKeyConfig *WM_keyconfig_active(wmWindowManager *wm)
{
	wmKeyConfig *keyconf;

	/* first try from preset */
	keyconf = BLI_findstring(&wm->keyconfigs, U.keyconfigstr, offsetof(wmKeyConfig, idname));
	if (keyconf)
		return keyconf;
	
	/* otherwise use default */
	return wm->defaultconf;
}
Beispiel #19
0
static bActuator *edit_actuator_property_get(bContext *C, wmOperator *op, Object **ob)
{
    char actuator_name[MAX_NAME];
    bActuator *act;

    RNA_string_get(op->ptr, "actuator", actuator_name);

    *ob = edit_object_property_get(C, op);
    if (!*ob) return NULL;

    act = BLI_findstring(&((*ob)->actuators), actuator_name, offsetof(bActuator, name));
    return act;
}
Beispiel #20
0
static bController *edit_controller_property_get(bContext *C, wmOperator *op, Object **ob)
{
    char controller_name[MAX_NAME];
    bController *cont;

    RNA_string_get(op->ptr, "controller", controller_name);

    *ob = edit_object_property_get(C, op);
    if (!*ob) return NULL;

    cont = BLI_findstring(&((*ob)->controllers), controller_name, offsetof(bController, name));
    return cont;
}
Beispiel #21
0
static bSensor *edit_sensor_property_get(bContext *C, wmOperator *op, Object **ob)
{
    char sensor_name[MAX_NAME];
    bSensor *sens;

    RNA_string_get(op->ptr, "sensor", sensor_name);

    *ob = edit_object_property_get(C, op);
    if (!*ob) return NULL;

    sens = BLI_findstring(&((*ob)->sensors), sensor_name, offsetof(bSensor, name));
    return sens;
}
Beispiel #22
0
/* return success (1) */
int BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, ReportList *reports)
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	Main *mainl = NULL;
	Library *lib;
	BlendHandle *bh;
		
	bh = BLO_blendhandle_from_file(libname, reports);
	
	if (bh == NULL) {
		/* error reports will have been made by BLO_blendhandle_from_file() */
		return 0;
	}

	BKE_scene_base_deselect_all(scene);
	
	/* tag everything, all untagged data can be made local
	 * its also generally useful to know what is new
	 *
	 * take extra care BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false) is called after! */
	BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, true);
	
	/* here appending/linking starts */
	mainl = BLO_library_link_begin(bmain, &bh, libname);
	
	BLO_library_link_all(mainl, bh, flag, scene, v3d);

	BLO_library_link_end(mainl, &bh, flag, scene, v3d);
	
	/* mark all library linked objects to be updated */
	BKE_main_lib_objects_recalc_all(bmain);
	IMB_colormanagement_check_file_config(bmain);
	
	/* append, rather than linking */
	lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath));
	BKE_library_make_local(bmain, lib, true, false);
	
	/* important we unset, otherwise these object wont
	 * link into other scenes from this blend file */
	BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false);
	
	/* recreate dependency graph to include new objects */
	DAG_relations_tag_update(bmain);
	
	BLO_blendhandle_close(bh);
	/* remove library... */
	
	return 1;
}
Beispiel #23
0
static void data_dir_add(ListBase *lb, const char *member)
{
	LinkData *link;
	
	if(strcmp(member, "scene") == 0) /* exception */
		return;

	if(BLI_findstring(lb, member, offsetof(LinkData, data)))
		return;
	
	link= MEM_callocN(sizeof(LinkData), "LinkData");
	link->data= (void*)member;
	BLI_addtail(lb, link);
}
Beispiel #24
0
void test_idbutton(char *name)
{
	/* called from buttons: when name already exists: call new_id */
	ListBase *lb;
	ID *idtest;
	

	lb= which_libbase(G.main, GS(name-2) );
	if(lb==NULL) return;
	
	/* search for id */
	idtest= BLI_findstring(lb, name, offsetof(ID, name) + 2);

	if(idtest) if( new_id(lb, idtest, name)==0 ) sort_alpha_id(lb, idtest);
}
Beispiel #25
0
static Object *edit_object_property_get(bContext *C, wmOperator *op)
{
    char ob_name[MAX_NAME];
    Object *ob;

    RNA_string_get(op->ptr, "object", ob_name);

    /* if ob_name is valid try to find the object with this name
     * otherwise gets the active object */
    if (*ob_name)
        ob = BLI_findstring(&(CTX_data_main(C)->object), ob_name, offsetof(ID, name) + 2);
    else
        ob = ED_object_active_context(C);

    return ob;
}
Beispiel #26
0
int unpackImage(ReportList *reports, Image *ima, int how)
{
	int ret_value = RET_ERROR;

	if (ima != NULL) {
		while (ima->packedfiles.last) {
			char localname[FILE_MAX], absname[FILE_MAX];
			char *newname;
			ImagePackedFile *imapf = ima->packedfiles.last;

			unpack_generate_paths(imapf->filepath, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname));
			newname = unpackFile(reports, absname, localname, imapf->packedfile, how);

			if (newname != NULL) {
				ImageView *iv;

				ret_value = ret_value == RET_ERROR ? RET_ERROR : RET_OK;
				freePackedFile(imapf->packedfile);
				imapf->packedfile = NULL;

				/* update the new corresponding view filepath */
				iv = BLI_findstring(&ima->views, imapf->filepath, offsetof(ImageView, filepath));
				if (iv) {
					BLI_strncpy(iv->filepath, newname, sizeof(imapf->filepath));
				}

				/* keep the new name in the image for non-pack specific reasons */
				if (how != PF_REMOVE) {
					BLI_strncpy(ima->name, newname, sizeof(imapf->filepath));
				}
				MEM_freeN(newname);
			}
			else {
				ret_value = RET_ERROR;
			}

			BLI_remlink(&ima->packedfiles, imapf);
			MEM_freeN(imapf);
		}
	}

	if (ret_value == RET_OK) {
		BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
	}

	return(ret_value);
}
Beispiel #27
0
PyObject *bpy_text_reimport(PyObject *module, int *found)
{
	Text *text;
	const char *name;
	const char *filepath;
//XXX	Main *maggie = bpy_import_main ? bpy_import_main:G.main;
	Main *maggie = bpy_import_main;
	
	if (!maggie) {
		printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
		return NULL;
	}
	
	*found = 0;
	
	/* get name, filename from the module itself */
	if ((name = PyModule_GetName(module)) == NULL)
		return NULL;

	{
		PyObject *module_file = PyModule_GetFilenameObject(module);
		if (module_file == NULL) {
			return NULL;
		}
		filepath = _PyUnicode_AsString(module_file);
		Py_DECREF(module_file);
		if (filepath == NULL) {
			return NULL;
		}
	}

	/* look up the text object */
	text = BLI_findstring(&maggie->text, BLI_path_basename(filepath), offsetof(ID, name) + 2);

	/* uh-oh.... didn't find it */
	if (!text)
		return NULL;
	else
		*found = 1;

	if (bpy_text_compile(text) == false) {
		return NULL;
	}

	/* make into a module */
	return PyImport_ExecCodeModule(name, text->compiled);
}
static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info)
{
	Scene *scene = CTX_data_scene(C);
	bool changed = false;

	if (scene->gpd) {
		bGPDlayer *gpl;
		const char *ruler_name = RULER_ID;
		gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
		if (gpl) {
			bGPDframe *gpf;
			gpf = gpencil_layer_getframe(gpl, CFRA, false);
			if (gpf) {
				bGPDstroke *gps;
				for (gps = gpf->strokes.first; gps; gps = gps->next) {
					bGPDspoint *pt = gps->points;
					int j;
					if (gps->totpoints == 3) {
						RulerItem *ruler_item = ruler_item_add(ruler_info);
						for (j = 0; j < 3; j++) {
							copy_v3_v3(ruler_item->co[j], &pt->x);
							pt++;
						}
						ruler_item->flag |= RULERITEM_USE_ANGLE;
						changed = true;
					}
					else if (gps->totpoints == 2) {
						RulerItem *ruler_item = ruler_item_add(ruler_info);
						for (j = 0; j < 3; j += 2) {
							copy_v3_v3(ruler_item->co[j], &pt->x);
							pt++;
						}
						changed = true;
					}
				}
			}
		}
	}

	return changed;
}
Beispiel #29
0
bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *reports)
{
	BlendHandle *bh = BLO_blendhandle_from_file(libname, reports);
	if (bh == NULL) {
		/* Error reports will have been made by BLO_blendhandle_from_file(). */
		return false;
	}
	/* Here appending/linking starts. */
	Main *mainl = BLO_library_link_begin(bmain_dst, &bh, libname);
	BLO_library_link_copypaste(mainl, bh);
	BLO_library_link_end(mainl, &bh, 0, NULL, NULL);
	/* Mark all library linked objects to be updated. */
	BKE_main_lib_objects_recalc_all(bmain_dst);
	IMB_colormanagement_check_file_config(bmain_dst);
	/* Append, rather than linking. */
	Library *lib = BLI_findstring(&bmain_dst->library, libname, offsetof(Library, filepath));
	BKE_library_make_local(bmain_dst, lib, true, false);
	/* Important we unset, otherwise these object wont
	 * link into other scenes from this blend file.
	 */
	BKE_main_id_tag_all(bmain_dst, LIB_TAG_PRE_EXISTING, false);
	BLO_blendhandle_close(bh);
	return true;
}
static int bake(
        Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
        const ScenePassType pass_type, const int margin,
        const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
        const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
        const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[],
        const char *custom_cage, const char *filepath, const int width, const int height,
        const char *identifier, ScrArea *sa, const char *uv_layer)
{
	int op_result = OPERATOR_CANCELLED;
	bool ok = false;

	Object *ob_cage = NULL;

	BakeHighPolyData *highpoly = NULL;
	int tot_highpoly = 0;

	char restrict_flag_low = ob_low->restrictflag;
	char restrict_flag_cage = 0;

	Mesh *me_low = NULL;
	Mesh *me_cage = NULL;

	float *result = NULL;

	BakePixel *pixel_array_low = NULL;
	BakePixel *pixel_array_high = NULL;

	const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
	const bool is_noncolor = is_noncolor_pass(pass_type);
	const int depth = RE_pass_depth(pass_type);

	BakeImages bake_images = {NULL};

	size_t num_pixels;
	int tot_materials;

	RE_bake_engine_set_engine_parameters(re, bmain, scene);

	if (!RE_bake_has_engine(re)) {
		BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
		goto cleanup;
	}

	tot_materials = ob_low->totcol;

	if (uv_layer && uv_layer[0] != '\0') {
		Mesh *me = (Mesh *)ob_low->data;
		if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer) == -1) {
			BKE_reportf(reports, RPT_ERROR,
			            "No UV layer named \"%s\" found in the object \"%s\"", uv_layer, ob_low->id.name + 2);
			goto cleanup;
		}
	}

	if (tot_materials == 0) {
		if (is_save_internal) {
			BKE_report(reports, RPT_ERROR,
			           "No active image found, add a material or bake to an external file");

			goto cleanup;
		}
		else if (is_split_materials) {
			BKE_report(reports, RPT_ERROR,
			           "No active image found, add a material or bake without the Split Materials option");

			goto cleanup;
		}
		else {
			/* baking externally without splitting materials */
			tot_materials = 1;
		}
	}

	/* we overallocate in case there is more materials than images */
	bake_images.data = MEM_mallocN(sizeof(BakeImage) * tot_materials, "bake images dimensions (width, height, offset)");
	bake_images.lookup = MEM_mallocN(sizeof(int) * tot_materials, "bake images lookup (from material to BakeImage)");

	build_image_lookup(bmain, ob_low, &bake_images);

	if (is_save_internal) {
		num_pixels = initialize_internal_images(&bake_images, reports);

		if (num_pixels == 0) {
			goto cleanup;
		}
	}
	else {
		/* when saving extenally always use the size specified in the UI */

		num_pixels = (size_t)width * (size_t)height * bake_images.size;

		for (int i = 0; i < bake_images.size; i++) {
			bake_images.data[i].width = width;
			bake_images.data[i].height = height;
			bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
			bake_images.data[i].image = NULL;
		}

		if (!is_split_materials) {
			/* saving a single image */
			for (int i = 0; i < tot_materials; i++) {
				bake_images.lookup[i] = 0;
			}
		}
	}

	if (is_selected_to_active) {
		CollectionPointerLink *link;
		tot_highpoly = 0;

		for (link = selected_objects->first; link; link = link->next) {
			Object *ob_iter = link->ptr.data;

			if (ob_iter == ob_low)
				continue;

			tot_highpoly ++;
		}

		if (is_cage && custom_cage[0] != '\0') {
			ob_cage = BLI_findstring(&bmain->object, custom_cage, offsetof(ID, name) + 2);

			if (ob_cage == NULL || ob_cage->type != OB_MESH) {
				BKE_report(reports, RPT_ERROR, "No valid cage object");
				goto cleanup;
			}
			else {
				restrict_flag_cage = ob_cage->restrictflag;
				ob_cage->restrictflag |= OB_RESTRICT_RENDER;
			}
		}
	}

	pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
	pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
	result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");

	/* get the mesh as it arrives in the renderer */
	me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
	BKE_mesh_split_faces(me_low);

	/* populate the pixel array with the face data */
	if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
		RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images, uv_layer);
	/* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh)  */

	if (is_selected_to_active) {
		CollectionPointerLink *link;
		ModifierData *md, *nmd;
		ListBase modifiers_tmp, modifiers_original;
		int i = 0;

		/* prepare cage mesh */
		if (ob_cage) {
			me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 0, 0);
			BKE_mesh_split_faces(me_cage);
			if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
				BKE_report(reports, RPT_ERROR,
				           "Invalid cage object, the cage mesh must have the same number "
				           "of faces as the active object");
				goto cleanup;
			}
		}
		else if (is_cage) {
			modifiers_original = ob_low->modifiers;
			BLI_listbase_clear(&modifiers_tmp);

			for (md = ob_low->modifiers.first; md; md = md->next) {
				/* Edge Split cannot be applied in the cage,
				 * the cage is supposed to have interpolated normals
				 * between the faces unless the geometry is physically
				 * split. So we create a copy of the low poly mesh without
				 * the eventual edge split.*/

				if (md->type == eModifierType_EdgeSplit)
					continue;

				nmd = modifier_new(md->type);
				BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
				modifier_copyData(md, nmd);
				BLI_addtail(&modifiers_tmp, nmd);
			}

			/* temporarily replace the modifiers */
			ob_low->modifiers = modifiers_tmp;

			/* get the cage mesh as it arrives in the renderer */
			me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
			BKE_mesh_split_faces(me_cage);
			RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
		}

		highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");

		/* populate highpoly array */
		for (link = selected_objects->first; link; link = link->next) {
			TriangulateModifierData *tmd;
			Object *ob_iter = link->ptr.data;

			if (ob_iter == ob_low)
				continue;

			/* initialize highpoly_data */
			highpoly[i].ob = ob_iter;
			highpoly[i].restrict_flag = ob_iter->restrictflag;

			/* triangulating so BVH returns the primitive_id that will be used for rendering */
			highpoly[i].tri_mod = ED_object_modifier_add(
			        reports, bmain, scene, highpoly[i].ob,
			        "TmpTriangulate", eModifierType_Triangulate);
			tmd = (TriangulateModifierData *)highpoly[i].tri_mod;
			tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
			tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP;

			highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 0, 0);
			highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
			BKE_mesh_split_faces(highpoly[i].me);

			/* lowpoly to highpoly transformation matrix */
			copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
			invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);

			highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);

			i++;
		}

		BLI_assert(i == tot_highpoly);

		ob_low->restrictflag |= OB_RESTRICT_RENDER;

		/* populate the pixel arrays with the corresponding face data for each high poly object */
		if (!RE_bake_pixels_populate_from_objects(
		            me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
		            cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage))
		{
			BKE_report(reports, RPT_ERROR, "Error handling selected objects");
			goto cage_cleanup;
		}

		/* the baking itself */
		for (i = 0; i < tot_highpoly; i++) {
			ok = RE_bake_engine(re, highpoly[i].ob, i, pixel_array_high,
			                    num_pixels, depth, pass_type, result);
			if (!ok) {
				BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
				goto cage_cleanup;
			}
		}

cage_cleanup:
		/* reverting data back */
		if ((ob_cage == NULL) && is_cage) {
			ob_low->modifiers = modifiers_original;

			while ((md = BLI_pophead(&modifiers_tmp))) {
				modifier_free(md);
			}
		}

		if (!ok) {
			goto cleanup;
		}
	}
	else {
		/* make sure low poly renders */
		ob_low->restrictflag &= ~OB_RESTRICT_RENDER;

		if (RE_bake_has_engine(re)) {
			ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, result);
		}
		else {
			BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
			goto cleanup;
		}
	}

	/* normal space conversion
	 * the normals are expected to be in world space, +X +Y +Z */
	if (ok && pass_type == SCE_PASS_NORMAL) {
		switch (normal_space) {
			case R_BAKE_SPACE_WORLD:
			{
				/* Cycles internal format */
				if ((normal_swizzle[0] == R_BAKE_POSX) &&
				    (normal_swizzle[1] == R_BAKE_POSY) &&
				    (normal_swizzle[2] == R_BAKE_POSZ))
				{
					break;
				}
				else {
					RE_bake_normal_world_to_world(pixel_array_low, num_pixels,  depth, result, normal_swizzle);
				}
				break;
			}
			case R_BAKE_SPACE_OBJECT:
			{
				RE_bake_normal_world_to_object(pixel_array_low, num_pixels, depth, result, ob_low, normal_swizzle);
				break;
			}
			case R_BAKE_SPACE_TANGENT:
			{
				if (is_selected_to_active) {
					RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_low, normal_swizzle, ob_low->obmat);
				}
				else {
					/* from multiresolution */
					Mesh *me_nores = NULL;
					ModifierData *md = NULL;
					int mode;

					md = modifiers_findByType(ob_low, eModifierType_Multires);

					if (md) {
						mode = md->mode;
						md->mode &= ~eModifierMode_Render;
					}

					me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
					BKE_mesh_split_faces(me_nores);
					RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);

					RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
					BKE_libblock_free(bmain, me_nores);

					if (md)
						md->mode = mode;
				}
				break;
			}
			default:
				break;
		}
	}

	if (!ok) {
		BKE_reportf(reports, RPT_ERROR, "Problem baking object \"%s\"", ob_low->id.name + 2);
		op_result = OPERATOR_CANCELLED;
	}
	else {
		/* save the results */
		for (int i = 0; i < bake_images.size; i++) {
			BakeImage *bk_image = &bake_images.data[i];

			if (is_save_internal) {
				ok = write_internal_bake_pixels(
				         bk_image->image,
				         pixel_array_low + bk_image->offset,
				         result + bk_image->offset * depth,
				         bk_image->width, bk_image->height,
				         margin, is_clear, is_noncolor);

				/* might be read by UI to set active image for display */
				bake_update_image(sa, bk_image->image);

				if (!ok) {
					BKE_reportf(reports, RPT_ERROR,
					           "Problem saving the bake map internally for object \"%s\"", ob_low->id.name + 2);
					op_result = OPERATOR_CANCELLED;
				}
				else {
					BKE_report(reports, RPT_INFO,
					           "Baking map saved to internal image, save it externally or pack it");
					op_result = OPERATOR_FINISHED;
				}
			}
			/* save externally */
			else {
				BakeData *bake = &scene->r.bake;
				char name[FILE_MAX];

				BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false, NULL);

				if (is_automatic_name) {
					BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
					BLI_path_suffix(name, FILE_MAX, identifier, "_");
				}

				if (is_split_materials) {
					if (bk_image->image) {
						BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
					}
					else {
						if (ob_low->mat[i]) {
							BLI_path_suffix(name, FILE_MAX, ob_low->mat[i]->id.name + 2, "_");
						}
						else if (me_low->mat[i]) {
							BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");
						}
						else {
							/* if everything else fails, use the material index */
							char tmp[4];
							sprintf(tmp, "%d", i % 1000);
							BLI_path_suffix(name, FILE_MAX, tmp, "_");
						}
					}
				}

				/* save it externally */
				ok = write_external_bake_pixels(
				        name,
				        pixel_array_low + bk_image->offset,
				        result + bk_image->offset * depth,
				        bk_image->width, bk_image->height,
				        margin, &bake->im_format, is_noncolor);

				if (!ok) {
					BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
					op_result = OPERATOR_CANCELLED;
				}
				else {
					BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
					op_result = OPERATOR_FINISHED;
				}

				if (!is_split_materials) {
					break;
				}
			}
		}
	}

	if (is_save_internal)
		refresh_images(&bake_images);

cleanup:

	if (highpoly) {
		int i;
		for (i = 0; i < tot_highpoly; i++) {
			highpoly[i].ob->restrictflag = highpoly[i].restrict_flag;

			if (highpoly[i].tri_mod)
				ED_object_modifier_remove(reports, bmain, highpoly[i].ob, highpoly[i].tri_mod);

			if (highpoly[i].me)
				BKE_libblock_free(bmain, highpoly[i].me);
		}
		MEM_freeN(highpoly);
	}

	ob_low->restrictflag = restrict_flag_low;

	if (ob_cage)
		ob_cage->restrictflag = restrict_flag_cage;

	if (pixel_array_low)
		MEM_freeN(pixel_array_low);

	if (pixel_array_high)
		MEM_freeN(pixel_array_high);

	if (bake_images.data)
		MEM_freeN(bake_images.data);

	if (bake_images.lookup)
		MEM_freeN(bake_images.lookup);

	if (result)
		MEM_freeN(result);

	if (me_low)
		BKE_libblock_free(bmain, me_low);

	if (me_cage)
		BKE_libblock_free(bmain, me_cage);

	return op_result;
}