/* groups display their internal tree name as label */ void node_group_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen) { BLI_strncpy(label, (node->id) ? node->id->name + 2 : IFACE_("Missing Datablock"), maxlen); }
int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain) { Scene *scene= CTX_data_scene(C); int i; FluidsimSettings *domainSettings; char debugStrBuffer[256]; int gridlevels = 0; const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp const char *suffixConfig = FLUID_SUFFIX_CONFIG; const char *suffixSurface = FLUID_SUFFIX_SURFACE; char targetDir[FILE_MAXDIR+FILE_MAXFILE]; // store & modify output settings char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access int outStringsChanged = 0; // modified? copy back before baking float domainMat[4][4]; float invDomMat[4][4]; int noFrames; int origFrame = scene->r.cfra; FluidAnimChannels *channels = MEM_callocN(sizeof(FluidAnimChannels), "fluid domain animation channels"); ListBase *fobjects = MEM_callocN(sizeof(ListBase), "fluid objects"); FluidsimModifierData *fluidmd = NULL; Mesh *mesh = NULL; wmJob *steve; FluidBakeJob *fb; elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings"); steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation", WM_JOB_PROGRESS); fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job"); if(getenv(strEnvName)) { int dlevel = atoi(getenv(strEnvName)); elbeemSetDebugLevel(dlevel); snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName); elbeemDebugOut(debugStrBuffer); } /* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */; noFrames = scene->r.efra - 0; if(noFrames<=0) { BKE_report(reports, RPT_ERROR, "No frames to export - check your animation range settings."); fluidbake_free_data(channels, fobjects, fsset, fb); return 0; } /* check scene for sane object/modifier settings */ if (!fluid_validate_scene(reports, scene, fsDomain)) { fluidbake_free_data(channels, fobjects, fsset, fb); return 0; } /* these both have to be valid, otherwise we wouldnt be here */ fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim); domainSettings = fluidmd->fss; mesh = fsDomain->data; domainSettings->bakeStart = 1; domainSettings->bakeEnd = scene->r.efra; // calculate bounding box fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize); // reset last valid frame domainSettings->lastgoodframe = -1; /* rough check of settings... */ if(domainSettings->previewresxyz > domainSettings->resolutionxyz) { snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz , domainSettings->resolutionxyz); elbeemDebugOut(debugStrBuffer); domainSettings->previewresxyz = domainSettings->resolutionxyz; } // set adaptive coarsening according to resolutionxyz // this should do as an approximation, with in/outflow // doing this more accurate would be overkill // perhaps add manual setting? if(domainSettings->maxRefine <0) { if(domainSettings->resolutionxyz>128) { gridlevels = 2; } else if(domainSettings->resolutionxyz>64) { gridlevels = 1; } else { gridlevels = 0; } } else { gridlevels = domainSettings->maxRefine; } snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels ); elbeemDebugOut(debugStrBuffer); /* ******** prepare output file paths ******** */ outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer); channels->length = scene->r.efra; channels->aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames; /* ******** initialise and allocate animation channels ******** */ fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects); /* reset to original current frame */ scene->r.cfra = origFrame; ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1); /* ---- XXX: No Time animation curve for now, leaving this code here for reference { int timeIcu[1] = { FLUIDSIM_TIME }; float timeDef[1] = { 1. }; // time channel is a bit special, init by hand... timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex"); for(i=0; i<=scene->r.efra; i++) { timeAtIndex[i] = (float)(i-startFrame); } fluidsimInitChannel(scene, &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB // time channel is a multiplicator for if(channelDomainTime) { for(i=0; i<allchannelSize; i++) { channelDomainTime[i*2+0] = aniFrameTime * channelDomainTime[i*2+0]; if(channelDomainTime[i*2+0]<0.) channelDomainTime[i*2+0] = 0.; } } timeAtFrame = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatframe"); timeAtFrame[0] = timeAtFrame[1] = domainSettings->animStart; // start at index 1 if(channelDomainTime) { for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0]; } fsset->} else { for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; } } } // domain channel init */ /* ******** init domain object's matrix ******** */ copy_m4_m4(domainMat, fsDomain->obmat); if(!invert_m4_m4(invDomMat, domainMat)) { snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); elbeemDebugOut(debugStrBuffer); BKE_report(reports, RPT_ERROR, "Invalid object matrix."); fluidbake_free_data(channels, fobjects, fsset, fb); return 0; } /* ******** start writing / exporting ******** */ // use .tmp, dont overwrite/delete original file BLI_snprintf(targetFile, sizeof(targetFile), "%s%s.tmp", targetDir, suffixConfig); // make sure these directories exist as well if(outStringsChanged) { BLI_make_existing_file(targetFile); } /* ******** export domain to elbeem ******** */ elbeemResetSettings(fsset); fsset->version = 1; // setup global settings copy_v3_v3(fsset->geoStart, domainSettings->bbStart); copy_v3_v3(fsset->geoSize, domainSettings->bbSize); // simulate with 50^3 fsset->resolutionxyz = (int)domainSettings->resolutionxyz; fsset->previewresxyz = (int)domainSettings->previewresxyz; fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings); fsset->viscosity = get_fluid_viscosity(domainSettings); get_fluid_gravity(fsset->gravity, scene, domainSettings); // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz fsset->animStart = domainSettings->animStart; fsset->aniFrameTime = channels->aniFrameTime; fsset->noOfFrames = noFrames; // is otherwise subtracted in parser BLI_snprintf(targetFile, sizeof(targetFile), "%s%s", targetDir, suffixSurface); // defaults for compressibility and adaptive grids fsset->gstar = domainSettings->gstar; fsset->maxRefine = domainSettings->maxRefine; // check <-> gridlevels fsset->generateParticles = domainSettings->generateParticles; fsset->numTracerParticles = domainSettings->generateTracers; fsset->surfaceSmoothing = domainSettings->surfaceSmoothing; fsset->surfaceSubdivs = domainSettings->surfaceSubdivs; fsset->farFieldSize = domainSettings->farFieldSize; BLI_strncpy(fsset->outputPath, targetFile, sizeof(fsset->outputPath)); // domain channels fsset->channelSizeFrameTime = fsset->channelSizeViscosity = fsset->channelSizeGravity = channels->length; fsset->channelFrameTime = channels->DomainTime; fsset->channelViscosity = channels->DomainViscosity; fsset->channelGravity = channels->DomainGravity; fsset->runsimCallback = &runSimulationCallback; fsset->runsimUserData = fb; if (domainSettings->typeFlags & OB_FSBND_NOSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_NOSLIP; else if (domainSettings->typeFlags&OB_FSBND_PARTSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP; else if (domainSettings->typeFlags&OB_FSBND_FREESLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP; fsset->domainobsPartslip = domainSettings->partSlipValue; fsset->generateVertexVectors = (domainSettings->domainNovecgen==0); // init blender domain transform matrix { int j; for(i=0; i<4; i++) { for(j=0; j<4; j++) { fsset->surfaceTrafo[i*4+j] = invDomMat[j][i]; } } } /* ******** init solver with settings ******** */ elbeemInit(); elbeemAddDomain(fsset); /* ******** export all fluid objects to elbeem ******** */ export_fluid_objects(fobjects, scene, channels->length); /* custom data for fluid bake job */ fb->settings = fsset; /* setup job */ WM_jobs_customdata(steve, fb, fluidbake_free); WM_jobs_timer(steve, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME); WM_jobs_callbacks(steve, fluidbake_startjob, NULL, NULL, fluidbake_endjob); WM_jobs_start(CTX_wm_manager(C), steve); /* ******** free stored animation data ******** */ fluidbake_free_data(channels, fobjects, NULL, NULL); // elbeemFree(); return 1; }
/* 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_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, "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 (strcmp(base->object->id.name + 2, "Lamp.002") != 0) { 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 = 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; }
void BKE_color_managed_colorspace_settings_copy(ColorManagedColorspaceSettings *colorspace_settings, const ColorManagedColorspaceSettings *settings) { BLI_strncpy(colorspace_settings->name, settings->name, sizeof(colorspace_settings->name)); }
/* Applies new_w weights to org_w ones, using either a texture, vgroup or constant value as factor. * Return values are in org_w. * If indices is not NULL, it must be a table of same length as org_w and new_w, mapping to the real * vertex index (in case the weight tables do not cover the whole vertices...). * XXX The standard "factor" value is assumed in [0.0, 1.0] range. Else, weird results might appear. */ void weightvg_do_mask(int num, const int *indices, float *org_w, const float *new_w, Object *ob, DerivedMesh *dm, float fact, const char defgrp_name[MAX_VGROUP_NAME], Scene *scene, Tex *texture, int tex_use_channel, int tex_mapping, Object *tex_map_object, const char *tex_uvlayer_name) { int ref_didx; int i; /* If influence factor is null, nothing to do! */ if (fact == 0.0f) return; /* If we want to mask vgroup weights from a texture. */ if (texture) { /* The texture coordinates. */ float (*tex_co)[3]; /* See mapping note below... */ MappingInfoModifierData t_map; float (*v_co)[3]; /* Use new generic get_texture_coords, but do not modify our DNA struct for it... * XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters ? * What e.g. if a modifier wants to use several textures ? * Why use only v_co, and not MVert (or both) ? */ t_map.texture = texture; t_map.map_object = tex_map_object; BLI_strncpy(t_map.uvlayer_name, tex_uvlayer_name, sizeof(t_map.uvlayer_name)); t_map.texmapping = tex_mapping; v_co = MEM_mallocN(sizeof(*v_co) * num, "WeightVG Modifier, TEX mode, v_co"); dm->getVertCos(dm, v_co); tex_co = MEM_callocN(sizeof(*tex_co) * num, "WeightVG Modifier, TEX mode, tex_co"); get_texture_coords(&t_map, ob, dm, v_co, tex_co, num); MEM_freeN(v_co); modifier_init_texture(scene, texture); /* For each weight (vertex), make the mix between org and new weights. */ for (i = 0; i < num; ++i) { int idx = indices ? indices[i] : i; TexResult texres; float hsv[3]; /* For HSV color space. */ bool do_color_manage; do_color_manage = tex_use_channel != MOD_WVG_MASK_TEX_USE_INT; texres.nor = NULL; get_texture_value(scene, texture, tex_co[idx], &texres, do_color_manage); /* Get the good channel value... */ switch (tex_use_channel) { case MOD_WVG_MASK_TEX_USE_INT: org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact))); break; case MOD_WVG_MASK_TEX_USE_RED: org_w[i] = (new_w[i] * texres.tr * fact) + (org_w[i] * (1.0f - (texres.tr * fact))); break; case MOD_WVG_MASK_TEX_USE_GREEN: org_w[i] = (new_w[i] * texres.tg * fact) + (org_w[i] * (1.0f - (texres.tg * fact))); break; case MOD_WVG_MASK_TEX_USE_BLUE: org_w[i] = (new_w[i] * texres.tb * fact) + (org_w[i] * (1.0f - (texres.tb * fact))); break; case MOD_WVG_MASK_TEX_USE_HUE: rgb_to_hsv_v(&texres.tr, hsv); org_w[i] = (new_w[i] * hsv[0] * fact) + (org_w[i] * (1.0f - (hsv[0] * fact))); break; case MOD_WVG_MASK_TEX_USE_SAT: rgb_to_hsv_v(&texres.tr, hsv); org_w[i] = (new_w[i] * hsv[1] * fact) + (org_w[i] * (1.0f - (hsv[1] * fact))); break; case MOD_WVG_MASK_TEX_USE_VAL: rgb_to_hsv_v(&texres.tr, hsv); org_w[i] = (new_w[i] * hsv[2] * fact) + (org_w[i] * (1.0f - (hsv[2] * fact))); break; case MOD_WVG_MASK_TEX_USE_ALPHA: org_w[i] = (new_w[i] * texres.ta * fact) + (org_w[i] * (1.0f - (texres.ta * fact))); break; default: org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact))); break; } } MEM_freeN(tex_co); } else if ((ref_didx = defgroup_name_index(ob, defgrp_name)) != -1) { MDeformVert *dvert = NULL; /* Check whether we want to set vgroup weights from a constant weight factor or a vertex * group. */ /* Get vgroup idx from its name. */ /* Proceed only if vgroup is valid, else use constant factor. */ /* Get actual dverts (ie vertex group data). */ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); /* Proceed only if vgroup is valid, else assume factor = O. */ if (dvert == NULL) return; /* For each weight (vertex), make the mix between org and new weights. */ for (i = 0; i < num; i++) { int idx = indices ? indices[i] : i; const float f = defvert_find_weight(&dvert[idx], ref_didx) * fact; org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f - f)); /* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */ } } else { /* Default "influence" behavior. */ /* For each weight (vertex), make the mix between org and new weights. */ const float ifact = 1.0f - fact; for (i = 0; i < num; i++) { org_w[i] = (new_w[i] * fact) + (org_w[i] * ifact); } } }
static int load_file(int UNUSED(argc), const char **argv, void *data) { bContext *C = data; /* Make the path absolute because its needed for relative linked blends to be found */ char filename[FILE_MAX]; /* note, we could skip these, but so far we always tried to load these files */ if (argv[0][0] == '-') { fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]); } BLI_strncpy(filename, argv[0], sizeof(filename)); BLI_path_cwd(filename); if (G.background) { int retval = BKE_read_file(C, filename, NULL); /* we successfully loaded a blend file, get sure that * pointcache works */ if (retval != BKE_READ_FILE_FAIL) { wmWindowManager *wm = CTX_wm_manager(C); /* special case, 2.4x files */ if (wm == NULL && CTX_data_main(C)->wm.first == NULL) { extern void wm_add_default(bContext *C); /* wm_add_default() needs the screen to be set. */ CTX_wm_screen_set(C, CTX_data_main(C)->screen.first); wm_add_default(C); } CTX_wm_manager_set(C, NULL); /* remove wm to force check */ WM_check(C); G.relbase_valid = 1; if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */ DAG_on_visible_update(CTX_data_main(C), TRUE); } else { /* failed to load file, stop processing arguments */ return -1; } /* WM_file_read() runs normally but since we're in background mode do here */ #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ BPY_python_reset(C); #endif /* happens for the UI on file reading too (huh? (ton))*/ // XXX BKE_reset_undo(); // BKE_write_undo("original"); /* save current state */ } else { /* we are not running in background mode here, but start blender in UI mode with * a file - this should do everything a 'load file' does */ ReportList reports; BKE_reports_init(&reports, RPT_PRINT); WM_file_autoexec_init(filename); WM_file_read(C, filename, &reports); BKE_reports_clear(&reports); } G.file_loaded = 1; return 0; }
void BKE_color_managed_display_settings_copy(ColorManagedDisplaySettings *new_settings, const ColorManagedDisplaySettings *settings) { BLI_strncpy(new_settings->display_device, settings->display_device, sizeof(new_settings->display_device)); }
extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing) { /* context values */ struct wmWindowManager *wm= CTX_wm_manager(C); struct wmWindow *win= CTX_wm_window(C); struct Scene *startscene= CTX_data_scene(C); struct Main* maggie1= CTX_data_main(C); RAS_Rect area_rect; area_rect.SetLeft(cam_frame->xmin); area_rect.SetBottom(cam_frame->ymin); area_rect.SetRight(cam_frame->xmax); area_rect.SetTop(cam_frame->ymax); int exitrequested = KX_EXIT_REQUEST_NO_REQUEST; Main* blenderdata = maggie1; char* startscenename = startscene->id.name+2; char pathname[FILE_MAXDIR+FILE_MAXFILE], oldsce[FILE_MAXDIR+FILE_MAXFILE]; STR_String exitstring = ""; BlendFileData *bfd= NULL; BLI_strncpy(pathname, blenderdata->name, sizeof(pathname)); BLI_strncpy(oldsce, G.main->name, sizeof(oldsce)); #ifdef WITH_PYTHON resetGamePythonPath(); // need this so running a second time wont use an old blendfiles path setGamePythonPath(G.main->name); // Acquire Python's GIL (global interpreter lock) // so we can safely run Python code and API calls PyGILState_STATE gilstate = PyGILState_Ensure(); PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */ #endif bgl::InitExtensions(true); // VBO code for derived mesh is not compatible with BGE (couldn't find why), so disable int disableVBO = (U.gameflags & USER_DISABLE_VBO); U.gameflags |= USER_DISABLE_VBO; // Globals to be carried on over blender files GlobalSettings gs; gs.matmode= startscene->gm.matmode; gs.glslflag= startscene->gm.flag; do { View3D *v3d= CTX_wm_view3d(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); // get some preferences SYS_SystemHandle syshandle = SYS_GetSystem(); bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0); bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0); bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool animation_record = (SYS_GetCommandLineInt(syshandle, "animation_record", 0) != 0); bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0); #ifdef WITH_PYTHON bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0); #endif // bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0); bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE; bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES; if (animation_record) usefixed= false; /* override since you don't want to run full-speed for sim recording */ // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(wm, win, area_rect, ar); // default mouse state set on render panel if (mouse_state) canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); else canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); RAS_IRenderTools* rendertools = new KX_BlenderRenderTools(); RAS_IRasterizer* rasterizer = NULL; //Don't use displaylists with VBOs //If auto starts using VBOs, make sure to check for that here if (displaylists && startscene->gm.raster_storage != RAS_STORE_VBO) rasterizer = new RAS_ListRasterizer(canvas, true, startscene->gm.raster_storage); else rasterizer = new RAS_OpenGLRasterizer(canvas, startscene->gm.raster_storage); RAS_IRasterizer::MipmapOption mipmapval = rasterizer->GetMipmapping(); // create the inputdevices KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice(); KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice(); // create a networkdevice NG_NetworkDeviceInterface* networkdevice = new NG_LoopBackNetworkDeviceInterface(); // // create a ketsji/blendersystem (only needed for timing and stuff) KX_BlenderSystem* kxsystem = new KX_BlenderSystem(); // create the ketsjiengine KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem); // set the devices ketsjiengine->SetKeyboardDevice(keyboarddevice); ketsjiengine->SetMouseDevice(mousedevice); ketsjiengine->SetNetworkDevice(networkdevice); ketsjiengine->SetCanvas(canvas); ketsjiengine->SetRenderTools(rendertools); ketsjiengine->SetRasterizer(rasterizer); ketsjiengine->SetUseFixedTime(usefixed); ketsjiengine->SetTimingDisplay(frameRate, profile, properties); ketsjiengine->SetRestrictAnimationFPS(restrictAnimFPS); KX_KetsjiEngine::SetExitKey(ConvertKeyCode(startscene->gm.exitkey)); //set the global settings (carried over if restart/load new files) ketsjiengine->SetGlobalSettings(&gs); #ifdef WITH_PYTHON CValue::SetDeprecationWarnings(nodepwarnings); #endif //lock frame and camera enabled - storing global values int tmp_lay= startscene->lay; Object *tmp_camera = startscene->camera; if (v3d->scenelock==0) { startscene->lay= v3d->lay; startscene->camera= v3d->camera; } // some blender stuff float camzoom; int draw_letterbox = 0; if (rv3d->persp==RV3D_CAMOB) { if (startscene->gm.framing.type == SCE_GAMEFRAMING_BARS) { /* Letterbox */ camzoom = 1.0f; draw_letterbox = 1; } else { camzoom = 1.0f / BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); } } else { camzoom = 2.0; } ketsjiengine->SetDrawType(v3d->drawtype); ketsjiengine->SetCameraZoom(camzoom); // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file if (exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME || exitrequested == KX_EXIT_REQUEST_RESTART_GAME) { exitrequested = KX_EXIT_REQUEST_NO_REQUEST; if (bfd) BLO_blendfiledata_free(bfd); char basedpath[FILE_MAX]; // base the actuator filename with respect // to the original file working directory if (exitstring != "") strcpy(basedpath, exitstring.Ptr()); // load relative to the last loaded file, this used to be relative // to the first file but that makes no sense, relative paths in // blend files should be relative to that file, not some other file // that happened to be loaded first BLI_path_abs(basedpath, pathname); bfd = load_game_data(basedpath); // if it wasn't loaded, try it forced relative if (!bfd) { // just add "//" in front of it char temppath[242]; strcpy(temppath, "//"); strcat(temppath, basedpath); BLI_path_abs(temppath, pathname); bfd = load_game_data(temppath); } // if we got a loaded blendfile, proceed if (bfd) { blenderdata = bfd->main; startscenename = bfd->curscene->id.name + 2; if (blenderdata) { BLI_strncpy(G.main->name, blenderdata->name, sizeof(G.main->name)); BLI_strncpy(pathname, blenderdata->name, sizeof(pathname)); #ifdef WITH_PYTHON setGamePythonPath(G.main->name); #endif } } // else forget it, we can't find it else { exitrequested = KX_EXIT_REQUEST_QUIT_GAME; } } Scene *scene= bfd ? bfd->curscene : (Scene *)BLI_findstring(&blenderdata->scene, startscenename, offsetof(ID, name) + 2); if (scene) { int startFrame = scene->r.cfra; ketsjiengine->SetAnimRecordMode(animation_record, startFrame); // Quad buffered needs a special window. if (scene->gm.stereoflag == STEREO_ENABLED) { if (scene->gm.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) scene->gm.stereomode); rasterizer->SetEyeSeparation(scene->gm.eyeseparation); } rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f); } if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME) { if (rv3d->persp != RV3D_CAMOB) { ketsjiengine->EnableCameraOverride(startscenename); ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == RV3D_ORTHO)); ketsjiengine->SetCameraOverrideProjectionMatrix(MT_CmMatrix4x4(rv3d->winmat)); ketsjiengine->SetCameraOverrideViewMatrix(MT_CmMatrix4x4(rv3d->viewmat)); if (rv3d->persp == RV3D_ORTHO) { ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); } else { ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); } ketsjiengine->SetCameraOverrideLens(v3d->lens); } // create a scene converter, create and convert the startingscene KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine); ketsjiengine->SetSceneConverter(sceneconverter); sceneconverter->addInitFromFrame=false; if (always_use_expand_framing) sceneconverter->SetAlwaysUseExpandFraming(true); bool usemat = false, useglslmat = false; if (GLEW_ARB_multitexture && GLEW_VERSION_1_1) usemat = true; if (GPU_glsl_support()) useglslmat = true; else if (gs.matmode == GAME_MAT_GLSL) usemat = false; if (usemat && (gs.matmode != GAME_MAT_TEXFACE)) sceneconverter->SetMaterials(true); if (useglslmat && (gs.matmode == GAME_MAT_GLSL)) sceneconverter->SetGLSLMaterials(true); if (scene->gm.flag & GAME_NO_MATERIAL_CACHING) sceneconverter->SetCacheMaterials(false); KX_Scene* startscene = new KX_Scene(keyboarddevice, mousedevice, networkdevice, startscenename, scene, canvas); #ifdef WITH_PYTHON // some python things PyObject *gameLogic, *gameLogic_keys; setupGamePython(ketsjiengine, startscene, blenderdata, pyGlobalDict, &gameLogic, &gameLogic_keys, 0, NULL); #endif // WITH_PYTHON //initialize Dome Settings if (scene->gm.stereoflag == STEREO_DOME) ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext); // initialize 3D Audio Settings AUD_I3DDevice* dev = AUD_get3DDevice(); if (dev) { dev->setSpeedOfSound(scene->audio.speed_of_sound); dev->setDopplerFactor(scene->audio.doppler_factor); dev->setDistanceModel(AUD_DistanceModel(scene->audio.distance_model)); } // from see blender.c: // FIXME: this version patching should really be part of the file-reading code, // but we still get too many unrelated data-corruption crashes otherwise... if (blenderdata->versionfile < 250) do_versions_ipos_to_animato(blenderdata); if (sceneconverter) { // convert and add scene sceneconverter->ConvertScene( startscene, rendertools, canvas); ketsjiengine->AddScene(startscene); // init the rasterizer rasterizer->Init(); // start the engine ketsjiengine->StartEngine(true); // Set the animation playback rate for ipo's and actions // the framerate below should patch with FPS macro defined in blendef.h // Could be in StartEngine set the framerate, we need the scene to do this ketsjiengine->SetAnimFrameRate(FPS); #ifdef WITH_PYTHON char *python_main = NULL; pynextframestate.state = NULL; pynextframestate.func = NULL; python_main = KX_GetPythonMain(scene); // the mainloop printf("\nBlender Game Engine Started\n"); if (python_main) { char *python_code = KX_GetPythonCode(blenderdata, python_main); if (python_code) { ketsjinextframestate.ketsjiengine = ketsjiengine; ketsjinextframestate.C = C; ketsjinextframestate.win = win; ketsjinextframestate.scene = scene; ketsjinextframestate.ar = ar; ketsjinextframestate.keyboarddevice = keyboarddevice; ketsjinextframestate.mousedevice = mousedevice; ketsjinextframestate.draw_letterbox = draw_letterbox; pynextframestate.state = &ketsjinextframestate; pynextframestate.func = &BL_KetsjiPyNextFrame; printf("Yielding control to Python script '%s'...\n", python_main); PyRun_SimpleString(python_code); printf("Exit Python script '%s'\n", python_main); MEM_freeN(python_code); } } else #endif /* WITH_PYTHON */ { while (!exitrequested) { exitrequested = BL_KetsjiNextFrame(ketsjiengine, C, win, scene, ar, keyboarddevice, mousedevice, draw_letterbox); } } printf("Blender Game Engine Finished\n"); exitstring = ketsjiengine->GetExitString(); #ifdef WITH_PYTHON if (python_main) MEM_freeN(python_main); #endif /* WITH_PYTHON */ gs = *(ketsjiengine->GetGlobalSettings()); // when exiting the mainloop #ifdef WITH_PYTHON // Clears the dictionary by hand: // This prevents, extra references to global variables // inside the GameLogic dictionary when the python interpreter is finalized. // which allows the scene to safely delete them :) // see: (space.c)->start_game //PyDict_Clear(PyModule_GetDict(gameLogic)); // Keep original items, means python plugins will autocomplete members PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic)); const Py_ssize_t numitems= PyList_GET_SIZE(gameLogic_keys_new); Py_ssize_t listIndex; for (listIndex=0; listIndex < numitems; listIndex++) { PyObject *item = PyList_GET_ITEM(gameLogic_keys_new, listIndex); if (!PySequence_Contains(gameLogic_keys, item)) { PyDict_DelItem( PyModule_GetDict(gameLogic), item); } } Py_DECREF(gameLogic_keys_new); gameLogic_keys_new = NULL; #endif ketsjiengine->StopEngine(); #ifdef WITH_PYTHON exitGamePythonScripting(); #endif networkdevice->Disconnect(); } if (sceneconverter) { delete sceneconverter; sceneconverter = NULL; } #ifdef WITH_PYTHON Py_DECREF(gameLogic_keys); gameLogic_keys = NULL; #endif } //lock frame and camera enabled - restoring global values if (v3d->scenelock==0) { startscene->lay= tmp_lay; startscene->camera= tmp_camera; } if (exitrequested != KX_EXIT_REQUEST_OUTSIDE) { // set the cursor back to normal canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); // set mipmap setting back to its original value rasterizer->SetMipmapping(mipmapval); } // clean up some stuff if (ketsjiengine) { delete ketsjiengine; ketsjiengine = NULL; } if (kxsystem) { delete kxsystem; kxsystem = NULL; } if (networkdevice) { delete networkdevice; networkdevice = NULL; } if (keyboarddevice) { delete keyboarddevice; keyboarddevice = NULL; } if (mousedevice) { delete mousedevice; mousedevice = NULL; } if (rasterizer) { delete rasterizer; rasterizer = NULL; } if (rendertools) { delete rendertools; rendertools = NULL; } if (canvas) { delete canvas; canvas = NULL; } // stop all remaining playing sounds AUD_getDevice()->stopAll(); } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME); if (!disableVBO) U.gameflags &= ~USER_DISABLE_VBO; if (bfd) BLO_blendfiledata_free(bfd); BLI_strncpy(G.main->name, oldsce, sizeof(G.main->name)); #ifdef WITH_PYTHON Py_DECREF(pyGlobalDict); // Release Python's GIL PyGILState_Release(gilstate); #endif }
static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory category, short *nr, int icon, int allow_delete, int reverse) { SpaceFile *sfile= CTX_wm_space_file(C); uiBlock *block; uiBut *but; uiLayout *box, *col; struct FSMenu* fsmenu = fsmenu_get(); int i, i_iter, nentries = fsmenu_get_nentries(fsmenu, category); /* reset each time */ *nr= -1; /* hide if no entries */ if(nentries == 0) return; /* layout */ uiLayoutSetAlignment(pa->layout, UI_LAYOUT_ALIGN_LEFT); block= uiLayoutGetBlock(pa->layout); box= uiLayoutBox(pa->layout); col= uiLayoutColumn(box, 1); for (i_iter=0; i_iter< nentries;++i_iter) { char dir[FILE_MAX]; char temp[FILE_MAX]; uiLayout* layout = uiLayoutRow(col, 0); char *entry; i= reverse ? nentries-(i_iter+1) : i_iter; entry = fsmenu_get_entry(fsmenu, category, i); /* set this list item as active if we have a match */ if(sfile->params) { if(BLI_path_cmp(sfile->params->dir, entry) == 0) { *nr= i; } } /* create nice bookmark name, shows last directory in the full path currently */ BLI_strncpy(temp, entry, FILE_MAX); BLI_add_slash(temp); BLI_getlastdir(temp, dir, FILE_MAX); BLI_del_slash(dir); if(dir[0] == 0) BLI_strncpy(dir, entry, FILE_MAX); /* create list item */ but= uiDefIconTextButS(block, LISTROW, 0, icon, dir, 0,0,UI_UNIT_X*10,UI_UNIT_Y, nr, 0, i, 0, 0, entry); uiButSetFunc(but, file_panel_cb, entry, NULL); uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT); /* create delete button */ if(allow_delete && fsmenu_can_save(fsmenu, category, i)) { uiBlockSetEmboss(block, UI_EMBOSSN); uiItemIntO(layout, "", ICON_X, "FILE_OT_delete_bookmark", "index", i); uiBlockSetEmboss(block, UI_EMBOSS); } } }
/** * \see #wm_homefile_write_exec wraps #BLO_write_file in a similar way. */ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *reports) { Library *li; int len; int ret = -1; BlendThumbnail *thumb, *main_thumb; ImBuf *ibuf_thumb = NULL; len = strlen(filepath); if (len == 0) { BKE_report(reports, RPT_ERROR, "Path is empty, cannot save"); return ret; } if (len >= FILE_MAX) { BKE_report(reports, RPT_ERROR, "Path too long, cannot save"); return ret; } /* Check if file write permission is ok */ if (BLI_exists(filepath) && !BLI_file_is_writable(filepath)) { BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath); return ret; } /* note: used to replace the file extension (to ensure '.blend'), * no need to now because the operator ensures, * its handy for scripts to save to a predefined name without blender editing it */ /* send the OnSave event */ for (li = G.main->library.first; li; li = li->id.next) { if (BLI_path_cmp(li->filepath, filepath) == 0) { BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath); return ret; } } /* Call pre-save callbacks befores writing preview, that way you can generate custom file thumbnail... */ BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE); /* blend file thumbnail */ /* save before exit_editmode, otherwise derivedmeshes for shared data corrupt #27765) */ /* Main now can store a .blend thumbnail, usefull for background mode or thumbnail customization. */ main_thumb = thumb = CTX_data_main(C)->blen_thumb; if ((U.flag & USER_SAVE_PREVIEWS) && BLI_thread_is_main()) { ibuf_thumb = blend_file_thumb(CTX_data_scene(C), CTX_wm_screen(C), &thumb); } /* operator now handles overwrite checks */ if (G.fileflags & G_AUTOPACK) { packAll(G.main, reports, false); } /* don't forget not to return without! */ WM_cursor_wait(1); ED_editors_flush_edits(C, false); fileflags |= G_FILE_HISTORY; /* write file history */ /* first time saving */ /* XXX temp solution to solve bug, real fix coming (ton) */ if ((G.main->name[0] == '\0') && !(fileflags & G_FILE_SAVE_COPY)) { BLI_strncpy(G.main->name, filepath, sizeof(G.main->name)); } /* XXX temp solution to solve bug, real fix coming (ton) */ G.main->recovered = 0; if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) { if (!(fileflags & G_FILE_SAVE_COPY)) { G.relbase_valid = 1; BLI_strncpy(G.main->name, filepath, sizeof(G.main->name)); /* is guaranteed current file */ G.save_over = 1; /* disable untitled.blend convention */ } BKE_BIT_TEST_SET(G.fileflags, fileflags & G_FILE_COMPRESS, G_FILE_COMPRESS); BKE_BIT_TEST_SET(G.fileflags, fileflags & G_FILE_AUTOPLAY, G_FILE_AUTOPLAY); /* prevent background mode scripts from clobbering history */ if (!G.background) { wm_history_file_update(); } BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_POST); /* run this function after because the file cant be written before the blend is */ if (ibuf_thumb) { IMB_thumb_delete(filepath, THB_FAIL); /* without this a failed thumb overrides */ ibuf_thumb = IMB_thumb_create(filepath, THB_LARGE, THB_SOURCE_BLEND, ibuf_thumb); } ret = 0; /* Success. */ } if (ibuf_thumb) { IMB_freeImBuf(ibuf_thumb); } if (thumb && thumb != main_thumb) { MEM_freeN(thumb); } WM_cursor_wait(0); return ret; }
static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) { GPUInput *input; GPUNode *outnode; const char *name; if(link->output) { outnode = link->output->node; name = outnode->name; if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) { input = MEM_dupallocN(outnode->inputs.first); input->type = type; if(input->link) input->link->users++; BLI_addtail(&node->inputs, input); return; } } input = MEM_callocN(sizeof(GPUInput), "GPUInput"); input->node = node; if(link->builtin) { /* builtin uniform */ input->type = type; input->source = GPU_SOURCE_BUILTIN; input->builtin = link->builtin; MEM_freeN(link); } else if(link->output) { /* link to a node output */ input->type = type; input->source = GPU_SOURCE_TEX_PIXEL; input->link = link; link->users++; } else if(link->dynamictex) { /* dynamic texture, GPUTexture is updated/deleted externally */ input->type = type; input->source = GPU_SOURCE_TEX; input->tex = link->dynamictex; input->textarget = GL_TEXTURE_2D; input->textype = type; input->dynamictex = 1; input->dynamicdata = link->ptr2; MEM_freeN(link); } else if(link->texture) { /* small texture created on the fly, like for colorbands */ input->type = GPU_VEC4; input->source = GPU_SOURCE_TEX; input->textype = type; //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL); input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL); input->textarget = GL_TEXTURE_2D; MEM_freeN(link->ptr1); MEM_freeN(link); } else if(link->image) { /* blender image */ input->type = GPU_VEC4; input->source = GPU_SOURCE_TEX; input->ima = link->ptr1; input->iuser = link->ptr2; input->textarget = GL_TEXTURE_2D; input->textype = GPU_TEX2D; MEM_freeN(link); } else if(link->attribtype) { /* vertex attribute */ input->type = type; input->source = GPU_SOURCE_ATTRIB; input->attribtype = link->attribtype; BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname)); MEM_freeN(link); } else { /* uniform vector */ input->type = type; input->source = GPU_SOURCE_VEC_UNIFORM; memcpy(input->vec, link->ptr1, type*sizeof(float)); if(link->dynamic) { input->dynamicvec= link->ptr1; input->dynamictype= link->dynamictype; input->dynamicdata= link->ptr2; } MEM_freeN(link); } BLI_addtail(&node->inputs, input); }
/** * called on startup, (context entirely filled with NULLs) * or called for 'New File' * both startup.blend and userpref.blend are checked * the optional parameter custom_file points to an alternative startup page * custom_file can be NULL */ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file) { ListBase wmbase; char startstr[FILE_MAX]; char prefstr[FILE_MAX]; int success = 0; /* Indicates whether user preferences were really load from memory. * * This is used for versioning code, and for this we can not rely on from_memory * passed via argument. This is because there might be configuration folder * exists but it might not have userpref.blend and in this case we fallback to * reading home file from memory. * * And in this case versioning code is to be run. */ bool read_userdef_from_memory = true; /* options exclude eachother */ BLI_assert((from_memory && custom_file) == 0); if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) { BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC); } BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); UI_view2d_zoom_cache_reset(); G.relbase_valid = 0; if (!from_memory) { const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); if (custom_file) { BLI_strncpy(startstr, custom_file, FILE_MAX); if (cfgdir) { BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); } else { prefstr[0] = '\0'; } } else if (cfgdir) { BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE); BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); } else { startstr[0] = '\0'; prefstr[0] = '\0'; from_memory = 1; } } /* put aside screens to match with persistent windows later */ wm_window_match_init(C, &wmbase); if (!from_memory) { if (BLI_access(startstr, R_OK) == 0) { success = (BKE_read_file(C, startstr, NULL) != BKE_READ_FILE_FAIL); } if (BLI_listbase_is_empty(&U.themes)) { if (G.debug & G_DEBUG) printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr); success = 0; } } if (success == 0 && custom_file && reports) { BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", custom_file); /*We can not return from here because wm is already reset*/ } if (success == 0) { success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true); if (BLI_listbase_is_empty(&wmbase)) { wm_clear_default_size(C); } BKE_tempdir_init(U.tempdir); #ifdef WITH_PYTHON_SECURITY /* use alternative setting for security nuts * otherwise we'd need to patch the binary blob - startup.blend.c */ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; #endif } /* check new prefs only after startup.blend was finished */ if (!from_memory && BLI_exists(prefstr)) { int done = BKE_read_file_userdef(prefstr, NULL); if (done != BKE_READ_FILE_FAIL) { read_userdef_from_memory = false; printf("Read new prefs: %s\n", prefstr); } } /* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise * can remove this eventually, only in a 2.53 and older, now its not written */ G.fileflags &= ~G_FILE_RELATIVE_REMAP; /* check userdef before open window, keymaps etc */ wm_init_userdef(C, read_userdef_from_memory); /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); WM_check(C); /* opens window(s), checks keymaps */ G.main->name[0] = '\0'; /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ if (!G.background) GPU_default_lights(); /* XXX */ G.save_over = 0; // start with save preference untitled.blend G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */ // refresh_interface_font(); // undo_editmode_clear(); BKE_undo_reset(); BKE_undo_write(C, "original"); /* save current state */ CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); ED_editors_init(C); DAG_on_visible_update(CTX_data_main(C), true); #ifdef WITH_PYTHON if (CTX_py_init_get(C)) { /* sync addons, these may have changed from the defaults */ BPY_string_exec(C, "__import__('addon_utils').reset_all()"); BPY_python_reset(C); } #endif WM_operatortype_last_properties_clear_all(); /* important to do before NULL'ing the context */ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); /* in background mode the scene will stay NULL */ if (!G.background) { CTX_wm_window_set(C, NULL); /* exits queues */ } return true; }
static void wm_window_match_do(bContext *C, ListBase *oldwmlist) { wmWindowManager *oldwm, *wm; wmWindow *oldwin, *win; /* cases 1 and 2 */ if (BLI_listbase_is_empty(oldwmlist)) { if (G.main->wm.first) { /* nothing todo */ } else { wm_add_default(C); } } else { /* cases 3 and 4 */ /* we've read file without wm..., keep current one entirely alive */ if (BLI_listbase_is_empty(&G.main->wm)) { bScreen *screen = NULL; /* when loading without UI, no matching needed */ if (!(G.fileflags & G_FILE_NO_UI) && (screen = CTX_wm_screen(C))) { /* match oldwm to new dbase, only old files */ for (wm = oldwmlist->first; wm; wm = wm->id.next) { for (win = wm->windows.first; win; win = win->next) { /* all windows get active screen from file */ if (screen->winid == 0) win->screen = screen; else win->screen = ED_screen_duplicate(win, screen); BLI_strncpy(win->screenname, win->screen->id.name + 2, sizeof(win->screenname)); win->screen->winid = win->winid; } } } G.main->wm = *oldwmlist; /* screens were read from file! */ ED_screens_initialize(G.main->wm.first); } else { bool has_match = false; /* what if old was 3, and loaded 1? */ /* this code could move to setup_appdata */ oldwm = oldwmlist->first; wm = G.main->wm.first; /* preserve key configurations in new wm, to preserve their keymaps */ wm->keyconfigs = oldwm->keyconfigs; wm->addonconf = oldwm->addonconf; wm->defaultconf = oldwm->defaultconf; wm->userconf = oldwm->userconf; BLI_listbase_clear(&oldwm->keyconfigs); oldwm->addonconf = NULL; oldwm->defaultconf = NULL; oldwm->userconf = NULL; /* ensure making new keymaps and set space types */ wm->initialized = 0; wm->winactive = NULL; /* only first wm in list has ghostwins */ for (win = wm->windows.first; win; win = win->next) { for (oldwin = oldwm->windows.first; oldwin; oldwin = oldwin->next) { if (oldwin->winid == win->winid) { has_match = true; wm_window_substitute_old(wm, oldwin, win); } } } /* make sure at least one window is kept open so we don't lose the context, check T42303 */ if (!has_match) { oldwin = oldwm->windows.first; win = wm->windows.first; wm_window_substitute_old(wm, oldwin, win); } wm_close_and_free_all(C, oldwmlist); } } }
void IMB_suffix_anim(struct anim *anim, const char *suffix) { BLI_strncpy(anim->suffix, suffix, sizeof(anim->suffix)); }
/** * \brief get the ID from the screen. * */ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth) { /* we could use some clever */ wmWindow *win = CTX_wm_window(C); ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my); Scene *scene = win->screen->scene; UnitSettings *unit = &scene->unit; const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0; ScrArea *area_prev = CTX_wm_area(C); ARegion *ar_prev = CTX_wm_region(C); ddr->name[0] = '\0'; if (sa) { if (sa->spacetype == SPACE_VIEW3D) { ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); if (ar) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; /* weak, we could pass in some reference point */ const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3]; const int mval[2] = { mx - ar->winrct.xmin, my - ar->winrct.ymin}; float co[3]; CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); /* grr, always draw else we leave stale text */ ED_region_tag_redraw(ar); view3d_operator_needs_opengl(C); if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) { const float mval_center_fl[2] = { (float)ar->winx / 2, (float)ar->winy / 2}; float co_align[3]; /* quick way to get view-center aligned point */ ED_view3d_win_to_3d(ar, co, mval_center_fl, co_align); *r_depth = len_v3v3(view_co, co_align); bUnit_AsString(ddr->name, sizeof(ddr->name), (double)*r_depth, 4, unit->system, B_UNIT_LENGTH, do_split, false); } else { BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name)); } } } } CTX_wm_area_set(C, area_prev); CTX_wm_region_set(C, ar_prev); }
/** * \note RNA_struct_property_is_set_ex is used here because we want * the previously used settings to be used here rather then overriding them */ short ED_fileselect_set_params(SpaceFile *sfile) { FileSelectParams *params; wmOperator *op = sfile->op; /* create new parameters if necessary */ if (!sfile->params) { sfile->params = MEM_callocN(sizeof(FileSelectParams), "fileselparams"); /* set path to most recently opened .blend */ BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); sfile->params->filter_glob[0] = '\0'; } params = sfile->params; /* set the parameters from the operator, if it exists */ if (op) { PropertyRNA *prop; const bool is_files = (RNA_struct_find_property(op->ptr, "files") != NULL); const bool is_filepath = (RNA_struct_find_property(op->ptr, "filepath") != NULL); const bool is_filename = (RNA_struct_find_property(op->ptr, "filename") != NULL); const bool is_directory = (RNA_struct_find_property(op->ptr, "directory") != NULL); const bool is_relative_path = (RNA_struct_find_property(op->ptr, "relative_path") != NULL); BLI_strncpy_utf8(params->title, RNA_struct_ui_name(op->type->srna), sizeof(params->title)); if (RNA_struct_find_property(op->ptr, "filemode")) params->type = RNA_int_get(op->ptr, "filemode"); else params->type = FILE_SPECIAL; if (is_filepath && RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { char name[FILE_MAX]; RNA_string_get(op->ptr, "filepath", name); if (params->type == FILE_LOADLIB) { BLI_strncpy(params->dir, name, sizeof(params->dir)); sfile->params->file[0] = '\0'; } else { BLI_split_dirfile(name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); } } else { if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", false)) { RNA_string_get(op->ptr, "directory", params->dir); sfile->params->file[0] = '\0'; } if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", false)) { RNA_string_get(op->ptr, "filename", params->file); } } if (params->dir[0]) { BLI_cleanup_dir(G.main->name, params->dir); BLI_path_abs(params->dir, G.main->name); } if (is_directory == true && is_filename == false && is_filepath == false && is_files == false) { params->flag |= FILE_DIRSEL_ONLY; } else { params->flag &= ~FILE_DIRSEL_ONLY; } params->filter = 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_blender"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_backup"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE_BACKUP : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_image"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? IMAGEFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_movie"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? MOVIEFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_python"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? PYSCRIPTFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_font"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FTFONTFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_sound"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? SOUNDFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_text"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? TEXTFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_folder"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FOLDERFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_btx"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BTXFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_collada"))) params->filter |= RNA_property_boolean_get(op->ptr, prop) ? COLLADAFILE : 0; if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) { RNA_property_string_get(op->ptr, prop, params->filter_glob); params->filter |= (OPERATORFILE | FOLDERFILE); } else { params->filter_glob[0] = '\0'; } if (params->filter != 0) { if (U.uiflag & USER_FILTERFILEEXTS) { params->flag |= FILE_FILTER; } else { params->flag &= ~FILE_FILTER; } } if (U.uiflag & USER_HIDE_DOT) { params->flag |= FILE_HIDE_DOT; } else { params->flag &= ~FILE_HIDE_DOT; } if (params->type == FILE_LOADLIB) { params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0; params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0; params->flag |= RNA_boolean_get(op->ptr, "active_layer") ? FILE_ACTIVELAY : 0; } if (RNA_struct_find_property(op->ptr, "display_type")) params->display = RNA_enum_get(op->ptr, "display_type"); if (params->display == FILE_DEFAULTDISPLAY) { if (U.uiflag & USER_SHOW_THUMBNAILS) { if (params->filter & (IMAGEFILE | MOVIEFILE)) params->display = FILE_IMGDISPLAY; else params->display = FILE_SHORTDISPLAY; } else { params->display = FILE_SHORTDISPLAY; } } if (is_relative_path) { if (!RNA_struct_property_is_set_ex(op->ptr, "relative_path", false)) { RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS); } } } else { /* default values, if no operator */ params->type = FILE_UNIX; params->flag |= FILE_HIDE_DOT; params->flag &= ~FILE_DIRSEL_ONLY; params->display = FILE_SHORTDISPLAY; params->filter = 0; params->filter_glob[0] = '\0'; } /* operator has no setting for this */ params->sort = FILE_SORT_ALPHA; /* initialize the list with previous folders */ if (!sfile->folders_prev) sfile->folders_prev = folderlist_new(); if (!sfile->params->dir[0]) { if (G.main->name[0]) { BLI_split_dir_part(G.main->name, sfile->params->dir, sizeof(sfile->params->dir)); } else { const char *doc_path = BLI_getDefaultDocumentFolder(); if (doc_path) { BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir)); } } } folderlist_pushdir(sfile->folders_prev, sfile->params->dir); /* switching thumbnails needs to recalc layout [#28809] */ if (sfile->layout) { sfile->layout->dirty = true; } return 1; }
KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) { Main *main_newlib; /* stored as a dynamic 'main' until we free it */ const int idcode = BKE_idcode_from_name(group); ReportList reports; static char err_local[255]; // TIMEIT_START(bge_link_blend_file); KX_LibLoadStatus *status; /* only scene and mesh supported right now */ if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } if (GetMainDynamicPath(path)) { snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } if (bpy_openlib == NULL) { snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); *err_str = err_local; return NULL; } main_newlib = BKE_main_new(); BKE_reports_init(&reports, RPT_STORE); short flag = 0; /* don't need any special options */ /* created only for linking, then freed */ Main *main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); load_datablocks(main_tmp, bpy_openlib, path, idcode); if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { load_datablocks(main_tmp, bpy_openlib, path, ID_TXT); } /* now do another round of linking for Scenes so all actions are properly loaded */ if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { load_datablocks(main_tmp, bpy_openlib, path, ID_AC); } BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); /* done linking */ /* needed for lookups*/ GetMainDynamic().push_back(main_newlib); BLI_strncpy(main_newlib->name, path, sizeof(main_newlib->name)); status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path); if (idcode == ID_ME) { /* Convert all new meshes into BGE meshes */ ID *mesh; for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) printf("MeshName: %s\n", mesh->name + 2); RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); } } else if (idcode == ID_AC) { /* Convert all actions */ ID *action; for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) printf("ActionName: %s\n", action->name + 2); scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } else if (idcode == ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; // scenes gets deleted by the thread when it's done using it (look in async_convert()) vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene *>() : NULL; for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) { if (options & LIB_LOAD_VERBOSE) printf("SceneName: %s\n", scene->name + 2); if (options & LIB_LOAD_ASYNC) { scenes->push_back((Scene *)scene); } else { /* merge into the base scene */ KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene delete other; } } if (options & LIB_LOAD_ASYNC) { pthread_t id; status->SetData(scenes); pthread_create(&id, NULL, &async_convert, (void *)status); m_threadinfo->threads.push_back(id); } #ifdef WITH_PYTHON /* Handle any text datablocks */ if (options & LIB_LOAD_LOAD_SCRIPTS) addImportMain(main_newlib); #endif /* Now handle all the actions */ if (options & LIB_LOAD_LOAD_ACTIONS) { ID *action; for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) printf("ActionName: %s\n", action->name + 2); scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } } if (!(options & LIB_LOAD_ASYNC)) status->Finish(); // TIMEIT_END(bge_link_blend_file); m_status_map[main_newlib->name] = status; return status; }
/* only called once, for startup */ void WM_init(bContext *C, int argc, const char **argv) { if (!G.background) { wm_ghost_init(C); /* note: it assigns C to ghost! */ wm_init_cursor_data(); } GHOST_CreateSystemPaths(); wm_operatortype_init(); WM_menutype_init(); set_free_windowmanager_cb(wm_close_and_free); /* library.c */ set_blender_test_break_cb(wm_window_testbreak); /* blender.c */ DAG_editors_update_cb(ED_render_id_flush_update); /* depsgraph.c */ ED_spacetypes_init(); /* editors/space_api/spacetype.c */ ED_file_init(); /* for fsmenu */ ED_init_node_butfuncs(); BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */ BLF_lang_init(); /* get the default database, plus a wm */ WM_read_homefile(C, NULL, G.factory_startup); BLF_lang_set(NULL); /* note: there is a bug where python needs initializing before loading the * startup.blend because it may contain PyDrivers. It also needs to be after * initializing space types and other internal data. * * However cant redo this at the moment. Solution is to load python * before WM_read_homefile() or make py-drivers check if python is running. * Will try fix when the crash can be repeated. - campbell. */ #ifdef WITH_PYTHON BPY_context_set(C); /* necessary evil */ BPY_python_start(argc, argv); BPY_driver_reset(); BPY_app_handlers_reset(); /* causes addon callbacks to be freed [#28068], * but this is actually what we want. */ BPY_modules_load_user(C); #else (void)argc; /* unused */ (void)argv; /* unused */ #endif if (!G.background && !wm_start_with_console) GHOST_toggleConsole(3); wm_init_reports(C); /* reports cant be initialized before the wm */ if (!G.background) { GPU_extensions_init(); GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); GPU_set_anisotropic(U.anisotropic_filter); UI_init(); } clear_matcopybuf(); ED_render_clear_mtex_copybuf(); // glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); ED_preview_init_dbase(); WM_read_history(); /* allow a path of "", this is what happens when making a new file */ /* if(G.main->name[0] == 0) BLI_make_file_string("/", G.main->name, BLI_getDefaultDocumentFolder(), "untitled.blend"); */ BLI_strncpy(G.lib, G.main->name, FILE_MAX); }
void BKE_color_managed_display_settings_init(ColorManagedDisplaySettings *settings) { const char *display_name = IMB_colormanagement_display_get_default_name(); BLI_strncpy(settings->display_device, display_name, sizeof(settings->display_device)); }
/* * Do actual bake operation. Loop through to-be-baked frames. * Returns 0 on failure. */ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surface, Object *cObject) { DynamicPaintCanvasSettings *canvas = surface->canvas; Scene *scene = CTX_data_scene(C); wmWindow *win = CTX_wm_window(C); int frame = 1; int frames; frames = surface->end_frame - surface->start_frame + 1; if (frames <= 0) { BLI_strncpy(canvas->error, N_("No frames to bake"), sizeof(canvas->error)); return 0; } /* Set frame to start point (also inits modifier data) */ frame = surface->start_frame; scene->r.cfra = (int)frame; ED_update_for_newframe(CTX_data_main(C), scene, 1); /* Init surface */ if (!dynamicPaint_createUVSurface(scene, surface)) return 0; /* Loop through selected frames */ for (frame = surface->start_frame; frame <= surface->end_frame; frame++) { float progress = (frame - surface->start_frame) / (float)frames * 100; surface->current_frame = frame; /* If user requested stop (esc), quit baking */ if (blender_test_break()) return 0; /* Update progress bar cursor */ if (!G.background) { WM_cursor_time(win, (int)progress); } /* calculate a frame */ scene->r.cfra = (int)frame; ED_update_for_newframe(CTX_data_main(C), scene, 1); if (!dynamicPaint_calculateFrame(surface, scene, cObject, frame)) return 0; /* * Save output images */ { char filename[FILE_MAX]; /* primary output layer */ if (surface->flags & MOD_DPAINT_OUT1) { /* set filepath */ BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name); BLI_path_frame(filename, frame, 4); /* save image */ dynamicPaint_outputSurfaceImage(surface, filename, 0); } /* secondary output */ if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) { /* set filepath */ BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name2); BLI_path_frame(filename, frame, 4); /* save image */ dynamicPaint_outputSurfaceImage(surface, filename, 1); } } } return 1; }
void BKE_color_managed_colorspace_settings_init(ColorManagedColorspaceSettings *colorspace_settings) { BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name)); }
/* name functions that ignore the first two ID characters */ void rna_ID_name_get(PointerRNA *ptr, char *value) { ID *id = (ID *)ptr->data; BLI_strncpy(value, id->name + 2, sizeof(id->name) - 2); }
void OutputOpenExrMultiLayerOperation::deinitExecution() { unsigned int width = this->getWidth(); unsigned int height = this->getHeight(); if (width != 0 && height != 0) { Main *bmain = G.main; /* TODO, have this passed along */ char filename[FILE_MAX]; void *exrhandle = IMB_exr_get_handle(); BKE_makepicstring_from_type(filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER, (this->m_rd->scemode & R_EXTENSION), true); BLI_make_existing_file(filename); for (unsigned int i = 0; i < this->m_layers.size(); ++i) { char channelname[EXR_TOT_MAXNAME]; BLI_strncpy(channelname, this->m_layers[i].name, sizeof(channelname) - 2); char *channelname_ext = channelname + strlen(channelname); float *buf = this->m_layers[i].outputBuffer; /* create channels */ switch (this->m_layers[i].datatype) { case COM_DT_VALUE: strcpy(channelname_ext, ".V"); IMB_exr_add_channel(exrhandle, 0, channelname, 1, width, buf); break; case COM_DT_VECTOR: strcpy(channelname_ext, ".X"); IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf); strcpy(channelname_ext, ".Y"); IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 1); strcpy(channelname_ext, ".Z"); IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3 * width, buf + 2); break; case COM_DT_COLOR: strcpy(channelname_ext, ".R"); IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf); strcpy(channelname_ext, ".G"); IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 1); strcpy(channelname_ext, ".B"); IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 2); strcpy(channelname_ext, ".A"); IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4 * width, buf + 3); break; default: break; } } /* when the filename has no permissions, this can fail */ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec)) { IMB_exr_write_channels(exrhandle); } else { /* TODO, get the error from openexr's exception */ /* XXX nice way to do report? */ printf("Error Writing Render Result, see console\n"); } IMB_exr_close(exrhandle); for (unsigned int i = 0; i < this->m_layers.size(); ++i) { if (this->m_layers[i].outputBuffer) { MEM_freeN(this->m_layers[i].outputBuffer); this->m_layers[i].outputBuffer = NULL; } this->m_layers[i].imageInput = NULL; } } }
bool RE_bake_engine( Render *re, Object *object, const int object_id, const BakePixel pixel_array[], const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0; /* set render info */ re->i.cfra = re->scene->r.cfra; BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2); re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ engine = re->engine; if (!engine) { engine = RE_engine_create(type); re->engine = engine; } engine->flag |= RE_ENGINE_RENDERING; /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; engine->resolution_x = re->winx; engine->resolution_y = re->winy; RE_parts_init(re, false); engine->tile_x = re->r.tilex; engine->tile_y = re->r.tiley; /* update is only called so we create the engine.session */ if (type->update) type->update(engine, re->main, re->scene); if (type->bake) type->bake(engine, re->scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result); engine->tile_x = 0; engine->tile_y = 0; engine->flag &= ~RE_ENGINE_RENDERING; BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); curvemapping_free_data(&re->r.mblur_shutter_curve); /* re->engine becomes zero if user changed active render engine during render */ if (!persistent_data || !re->engine) { RE_engine_free(engine); re->engine = NULL; } RE_parts_free(re); BLI_rw_mutex_unlock(&re->partsmutex); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = true; return true; }
static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetFile, char *debugStrBuffer) { FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim); FluidsimSettings *domainSettings= fluidmd->fss; FILE *fileCfg; int dirExist = 0; char newSurfdataPath[FILE_MAXDIR+FILE_MAXFILE]; // modified output settings const char *suffixConfig = FLUID_SUFFIX_CONFIG; int outStringsChanged = 0; // prepare names... strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); BLI_path_abs(targetDir, G.main->name); // fixed #frame-no // .tmp: dont overwrite/delete original file BLI_snprintf(targetFile, sizeof(targetFile), "%s%s.tmp", targetDir, suffixConfig); // make sure all directories exist // as the bobjs use the same dir, this only needs to be checked // for the cfg output BLI_make_existing_file(targetFile); // check selected directory // simply try to open cfg file for writing to test validity of settings fileCfg = fopen(targetFile, "w"); if(fileCfg) { dirExist = 1; fclose(fileCfg); // remove cfg dummy from directory test BLI_delete(targetFile, 0,0); } if((strlen(targetDir)<1) || (!dirExist)) { char blendDir[FILE_MAXDIR+FILE_MAXFILE]; char blendFile[FILE_MAXDIR+FILE_MAXFILE]; // invalid dir, reset to current/previous BLI_strncpy(blendDir, G.main->name, sizeof(blendDir)); BLI_splitdirstring(blendDir, blendFile); BLI_replace_extension(blendFile, sizeof(blendFile), ""); /* strip .blend */ BLI_snprintf(newSurfdataPath, sizeof(newSurfdataPath) ,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name); BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath); elbeemDebugOut(debugStrBuffer); outStringsChanged=1; } // check if modified output dir is ok #if 0 if(outStringsChanged) { char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256]; int selection=0; BLI_strncpy(dispmsg,"Output settings set to: '", sizeof(dispmsg)); strcat(dispmsg, newSurfdataPath); strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0"); // ask user if thats what he/she wants... selection = pupmenu(dispmsg); if(selection<1) return 0; // 0 from menu, or -1 aborted BLI_strncpy(targetDir, newSurfdataPath, sizeof(targetDir)); strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); BLI_path_abs(targetDir, G.main->name); // fixed #frame-no } #endif return outStringsChanged; }
int RE_engine_render(Render *re, int do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0; /* verify if we can render */ if (!type->render) return 0; if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW)) return 0; if (do_all && !(type->flag & RE_USE_POSTPROCESS)) return 0; if (!do_all && (type->flag & RE_USE_POSTPROCESS)) return 0; /* Lock drawing in UI during data phase. */ if (re->draw_lock) { re->draw_lock(re->dlh, 1); } /* update animation here so any render layer animation is applied before * creating the render result */ if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) { unsigned int lay = re->lay; /* don't update layers excluded on all render layers */ if (type->flag & RE_USE_EXCLUDE_LAYERS) { SceneRenderLayer *srl; unsigned int non_excluded_lay = 0; if (re->r.scemode & R_SINGLE_LAYER) { srl = BLI_findlink(&re->r.layers, re->r.actlay); if (srl) { non_excluded_lay |= ~srl->lay_exclude; /* in this case we must update all because animation for * the scene has not been updated yet, and so may not be * up to date until after BKE_scene_update_for_newframe */ if (render_layer_exclude_animated(re->scene, srl)) non_excluded_lay |= ~0; } } else { for (srl = re->r.layers.first; srl; srl = srl->next) { if (!(srl->layflag & SCE_LAY_DISABLE)) { non_excluded_lay |= ~srl->lay_exclude; if (render_layer_exclude_animated(re->scene, srl)) non_excluded_lay |= ~0; } } } lay &= non_excluded_lay; } BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, re->scene, lay, true); render_update_anim_renderdata(re, &re->scene->r); } /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->result == NULL || !(re->r.scemode & R_BUTS_PREVIEW)) { int savebuffers = RR_USE_MEM; if (re->result) render_result_free(re->result); if ((type->flag & RE_USE_SAVE_BUFFERS) && (re->r.scemode & R_EXR_TILE_FILE)) savebuffers = RR_USE_EXR; re->result = render_result_new(re, &re->disprect, 0, savebuffers, RR_ALL_LAYERS, RR_ALL_VIEWS); } BLI_rw_mutex_unlock(&re->resultmutex); if (re->result == NULL) { /* Clear UI drawing locks. */ if (re->draw_lock) { re->draw_lock(re->dlh, 0); } return 1; } /* set render info */ re->i.cfra = re->scene->r.cfra; BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name)); re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ engine = re->engine; if (!engine) { engine = RE_engine_create(type); re->engine = engine; } engine->flag |= RE_ENGINE_RENDERING; /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; if (re->flag & R_ANIMATION) engine->flag |= RE_ENGINE_ANIMATION; if (re->r.scemode & R_BUTS_PREVIEW) engine->flag |= RE_ENGINE_PREVIEW; engine->camera_override = re->camera_override; engine->layer_override = re->layer_override; engine->resolution_x = re->winx; engine->resolution_y = re->winy; RE_parts_init(re, false); engine->tile_x = re->partx; engine->tile_y = re->party; if (re->result->do_exr_tile) render_result_exr_file_begin(re); if (type->update) type->update(engine, re->main, re->scene); /* Clear UI drawing locks. */ if (re->draw_lock) { re->draw_lock(re->dlh, 0); } if (type->render) type->render(engine, re->scene); engine->tile_x = 0; engine->tile_y = 0; engine->flag &= ~RE_ENGINE_RENDERING; render_result_free_list(&engine->fullresult, engine->fullresult.first); BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE); /* re->engine becomes zero if user changed active render engine during render */ if (!persistent_data || !re->engine) { RE_engine_free(engine); re->engine = NULL; } if (re->result->do_exr_tile) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_save_empty_result_tiles(re); render_result_exr_file_end(re); BLI_rw_mutex_unlock(&re->resultmutex); } if (re->r.scemode & R_EXR_CACHE_FILE) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_cache_write(re); BLI_rw_mutex_unlock(&re->resultmutex); } RE_parts_free(re); BLI_rw_mutex_unlock(&re->partsmutex); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = true; #ifdef WITH_FREESTYLE if (re->r.mode & R_EDGE_FRS) RE_RenderFreestyleExternal(re); #endif return 1; }
static void blender_crash_handler(int signum) { #if 0 { char fname[FILE_MAX]; if (!G.main->name[0]) { BLI_make_file_string("/", fname, BLI_temporary_dir(), "crash.blend"); } else { BLI_strncpy(fname, G.main->name, sizeof(fname)); BLI_replace_extension(fname, sizeof(fname), ".crash.blend"); } printf("Writing: %s\n", fname); fflush(stdout); BKE_undo_save_file(fname); } #endif FILE *fp; char header[512]; wmWindowManager *wm = G.main->wm.first; char fname[FILE_MAX]; if (!G.main->name[0]) { BLI_make_file_string("/", fname, BLI_temporary_dir(), "blender.crash.txt"); } else { BLI_strncpy(fname, G.main->name, sizeof(fname)); BLI_replace_extension(fname, sizeof(fname), ".crash.txt"); } printf("Writing: %s\n", fname); fflush(stdout); BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Revision: %s\n", BLEND_VERSION_ARG, #ifdef BUILD_DATE build_rev #else "Unknown" #endif ); /* open the crash log */ errno = 0; fp = BLI_fopen(fname, "wb"); if (fp == NULL) { fprintf(stderr, "Unable to save '%s': %s\n", fname, errno ? strerror(errno) : "Unknown error opening file"); } else { if (wm) { BKE_report_write_file_fp(fp, &wm->reports, header); } blender_crash_handler_backtrace(fp); fclose(fp); } /* really crash */ signal(signum, SIG_DFL); #ifndef WIN32 kill(getpid(), signum); #else TerminateProcess(GetCurrentProcess(), signum); #endif }
/* Main Driver Management API calls: * Add a new driver for the specified property on the given ID block */ short ANIM_add_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type) { PointerRNA id_ptr, ptr; PropertyRNA *prop; FCurve *fcu; int array_index_max; int done = 0; /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { BKE_reportf(reports, RPT_ERROR, "Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", id->name, rna_path); return 0; } /* key entire array convenience method */ if (array_index == -1) { array_index_max= RNA_property_array_length(&ptr, prop); array_index= 0; } else array_index_max= array_index; /* maximum index should be greater than the start index */ if (array_index == array_index_max) array_index_max += 1; /* will only loop once unless the array index was -1 */ for (; array_index < array_index_max; array_index++) { /* create F-Curve with Driver */ fcu= verify_driver_fcurve(id, rna_path, array_index, 1); if (fcu && fcu->driver) { ChannelDriver *driver= fcu->driver; /* set the type of the driver */ driver->type= type; /* creating drivers for buttons will create the driver(s) with type * "scripted expression" so that their values won't be lost immediately, * so here we copy those values over to the driver's expression */ if (type == DRIVER_TYPE_PYTHON) { PropertyType proptype= RNA_property_type(prop); int array= RNA_property_array_length(&ptr, prop); char *expression= driver->expression; int val, maxlen= sizeof(driver->expression); float fval; if (proptype == PROP_BOOLEAN) { if (!array) val= RNA_property_boolean_get(&ptr, prop); else val= RNA_property_boolean_get_index(&ptr, prop, array_index); BLI_strncpy(expression, (val)? "True": "False", maxlen); } else if (proptype == PROP_INT) { if (!array) val= RNA_property_int_get(&ptr, prop); else val= RNA_property_int_get_index(&ptr, prop, array_index); BLI_snprintf(expression, maxlen, "%d", val); } else if (proptype == PROP_FLOAT) { if (!array) fval= RNA_property_float_get(&ptr, prop); else fval= RNA_property_float_get_index(&ptr, prop, array_index); BLI_snprintf(expression, maxlen, "%.3f", fval); } } /* for easier setup of drivers from UI, a driver variable should be * added if flag is set (UI calls only) */ if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { /* assume that users will mostly want this to be of type "Transform Channel" too, * since this allows the easiest setting up of common rig components */ DriverVar *dvar = driver_add_new_variable(driver); driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); } } /* set the done status */ done += (fcu != NULL); } /* done */ return done; }
/* name can be a dynamic string */ void undo_editmode_push(bContext *C, const char *name, void * (*getdata)(bContext * C), void (*freedata)(void *), void (*to_editmode)(void *, void *, void *), void *(*from_editmode)(void *, void *), int (*validate_undo)(void *, void *)) { UndoElem *uel; Object *obedit = CTX_data_edit_object(C); void *editdata; int nr; uintptr_t memused, totmem, maxmem; /* at first here was code to prevent an "original" key to be inserted twice * this was giving conflicts for example when mesh changed due to keys or apply */ /* remove all undos after (also when curundo == NULL) */ while (undobase.last != curundo) { uel = undobase.last; uel->freedata(uel->undodata); BLI_freelinkN(&undobase, uel); } /* make new */ curundo = uel = MEM_callocN(sizeof(UndoElem), "undo editmode"); BLI_strncpy(uel->name, name, sizeof(uel->name)); BLI_addtail(&undobase, uel); uel->getdata = getdata; uel->freedata = freedata; uel->to_editmode = to_editmode; uel->from_editmode = from_editmode; uel->validate_undo = validate_undo; /* limit amount to the maximum amount*/ nr = 0; uel = undobase.last; while (uel) { nr++; if (nr == U.undosteps) break; uel = uel->prev; } if (uel) { while (undobase.first != uel) { UndoElem *first = undobase.first; first->freedata(first->undodata); BLI_freelinkN(&undobase, first); } } /* copy */ memused = MEM_get_memory_in_use(); editdata = getdata(C); curundo->undodata = curundo->from_editmode(editdata, obedit->data); curundo->undosize = MEM_get_memory_in_use() - memused; curundo->ob = obedit; curundo->id = obedit->id; curundo->type = obedit->type; if (U.undomemory != 0) { /* limit to maximum memory (afterwards, we can't know in advance) */ totmem = 0; maxmem = ((uintptr_t)U.undomemory) * 1024 * 1024; uel = undobase.last; while (uel && uel->prev) { totmem += uel->undosize; if (totmem > maxmem) break; uel = uel->prev; } if (uel) { if (uel->prev && uel->prev->prev) uel = uel->prev; while (undobase.first != uel) { UndoElem *first = undobase.first; first->freedata(first->undodata); BLI_freelinkN(&undobase, first); } } } }
/* draw settings for generator modifier */ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, short width) { FMod_Generator *data = (FMod_Generator *)fcm->data; uiLayout /* *col, */ /* UNUSED */ *row; uiBlock *block; uiBut *but; PointerRNA ptr; short bwidth = width - 30; /* max button width */ /* init the RNA-pointer */ RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr); /* basic settings (backdrop + mode selector + some padding) */ /* col = uiLayoutColumn(layout, TRUE); */ /* UNUSED */ block = uiLayoutGetBlock(layout); uiBlockBeginAlign(block); but = uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL); uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "use_additive", -1, 0, 0, -1, -1, NULL); uiBlockEndAlign(block); /* now add settings for individual modes */ switch (data->mode) { case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ { float *cp = NULL; char xval[32]; unsigned int i; int maxXWidth; /* draw polynomial order selector */ row = uiLayoutRow(layout, FALSE); block = uiLayoutGetBlock(row); but = uiDefButI(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 10, 0, bwidth, 20, &data->poly_order, 1, 100, 0, 0, TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)")); uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); /* calculate maximum width of label for "x^n" labels */ if (data->arraysize > 2) { BLI_snprintf(xval, sizeof(xval), "x^%u", data->arraysize); maxXWidth = UI_GetStringWidth(xval) + 10; /* XXX: UI_GetStringWidth is not accurate */ } else { /* basic size (just "x") */ maxXWidth = UI_GetStringWidth("x") + 10; } /* draw controls for each coefficient and a + sign at end of row */ row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); cp = data->coefficients; for (i = 0; (i < data->arraysize) && (cp); i++, cp++) { /* To align with first line... */ if (i) uiDefBut(block, LABEL, 1, " ", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); else uiDefBut(block, LABEL, 1, "y =", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); /* coefficient */ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, bwidth / 2, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, TIP_("Coefficient for polynomial")); /* 'x' param (and '+' if necessary) */ if (i == 0) BLI_strncpy(xval, "", sizeof(xval)); else if (i == 1) BLI_strncpy(xval, "x", sizeof(xval)); else BLI_snprintf(xval, sizeof(xval), "x^%u", i); uiDefBut(block, LABEL, 1, xval, 0, 0, maxXWidth, 20, NULL, 0.0, 0.0, 0, 0, TIP_("Power of x")); if ( (i != (data->arraysize - 1)) || ((i == 0) && data->arraysize == 2) ) { uiDefBut(block, LABEL, 1, "+", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, ""); /* next coefficient on a new row */ row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); } else { /* For alignment in UI! */ uiDefBut(block, LABEL, 1, " ", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, ""); } } break; } case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* Factorized polynomial expression */ { float *cp = NULL; unsigned int i; /* draw polynomial order selector */ row = uiLayoutRow(layout, FALSE); block = uiLayoutGetBlock(row); but = uiDefButI(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 0, 0, width - 30, 19, &data->poly_order, 1, 100, 0, 0, TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)")); uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); /* draw controls for each pair of coefficients */ row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); cp = data->coefficients; for (i = 0; (i < data->poly_order) && (cp); i++, cp += 2) { /* To align with first line */ if (i) uiDefBut(block, LABEL, 1, " ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); else uiDefBut(block, LABEL, 1, "y =", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); /* opening bracket */ uiDefBut(block, LABEL, 1, "(", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, ""); /* coefficients */ uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, TIP_("Coefficient of x")); uiDefBut(block, LABEL, 1, "x +", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp + 1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, TIP_("Second coefficient")); /* closing bracket and multiplication sign */ if ( (i != (data->poly_order - 1)) || ((i == 0) && data->poly_order == 2) ) { uiDefBut(block, LABEL, 1, ") ×", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); /* set up new row for the next pair of coefficients */ row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); } else uiDefBut(block, LABEL, 1, ") ", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); } } break; } }