/* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */ void draw_gpencil_2dimage (bContext *C, ImBuf *ibuf) { ScrArea *sa= CTX_wm_area(C); ARegion *ar= CTX_wm_region(C); Scene *scene= CTX_data_scene(C); bGPdata *gpd; int offsx, offsy, sizex, sizey; int dflag = GP_DRAWDATA_NOSTATUS; /* check that we have grease-pencil stuff to draw */ if (ELEM(NULL, sa, ibuf)) return; gpd= gpencil_data_get_active(C); // XXX if (gpd == NULL) return; /* calculate rect */ switch (sa->spacetype) { case SPACE_IMAGE: /* image */ { /* just draw using standard scaling (settings here are currently ignored anyways) */ // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled offsx= 0; offsy= 0; sizex= ar->winx; sizey= ar->winy; wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax); dflag |= GP_DRAWDATA_ONLYV2D|GP_DRAWDATA_IEDITHACK; } break; case SPACE_SEQ: /* sequence */ { SpaceSeq *sseq= (SpaceSeq *)sa->spacedata.first; float zoom, zoomx, zoomy; /* calculate accessory values */ zoom= (float)(SEQ_ZOOM_FAC(sseq->zoom)); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { /* XXX sequencer zoom should store it? */ zoomx = zoom; // * (G.scene->r.xasp / G.scene->r.yasp); zoomy = zoom; } else zoomx = zoomy = zoom; /* calculate transforms (Note: we use ibuf here, as we have it) */ sizex= (int)(zoomx * ibuf->x); sizey= (int)(zoomy * ibuf->y); offsx= (int)( (ar->winx-sizex)/2 + sseq->xof ); offsy= (int)( (ar->winy-sizey)/2 + sseq->yof ); dflag |= GP_DRAWDATA_ONLYI2D; } break; default: /* for spacetype not yet handled */ offsx= 0; offsy= 0; sizex= ar->winx; sizey= ar->winy; dflag |= GP_DRAWDATA_ONLYI2D; break; } /* draw it! */ gp_draw_data(gpd, offsx, offsy, sizex, sizey, CFRA, dflag); }
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); rctf viewborder; float upvec[3]; /* tmp */ float mat[3][3]; fly->rv3d = CTX_wm_region_view3d(C); fly->v3d = CTX_wm_view3d(C); fly->ar = CTX_wm_region(C); fly->scene = CTX_data_scene(C); #ifdef NDOF_FLY_DEBUG puts("\n-- fly begin --"); #endif /* sanity check: for rare but possible case (if lib-linking the camera fails) */ if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) { fly->rv3d->persp = RV3D_PERSP; } if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); return false; } if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) { BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked"); return false; } if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) { BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints"); return false; } fly->state = FLY_RUNNING; fly->speed = 0.0f; fly->axis = 2; fly->pan_view = false; fly->xlock = FLY_AXISLOCK_STATE_OFF; fly->zlock = FLY_AXISLOCK_STATE_OFF; fly->xlock_momentum = 0.0f; fly->zlock_momentum = 0.0f; fly->grid = 1.0f; fly->use_precision = false; fly->use_freelook = false; #ifdef NDOF_FLY_DRAW_TOOMUCH fly->redraw = 1; #endif zero_v3(fly->dvec_prev); fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); copy_v2_v2_int(fly->mval, event->mval); fly->ndof = NULL; fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer(); fly->draw_handle_pixel = ED_region_draw_cb_activate(fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL); fly->rv3d->rflag |= RV3D_NAVIGATING; /* detect whether to start with Z locking */ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); copy_m3_m4(mat, fly->rv3d->viewinv); mul_m3_v3(mat, upvec); if (fabsf(upvec[2]) < 0.1f) { fly->zlock = FLY_AXISLOCK_STATE_IDLE; } fly->v3d_camera_control = ED_view3d_cameracontrol_aquire( fly->scene, fly->v3d, fly->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* calculate center */ if (fly->scene->camera) { ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false); fly->width = BLI_rctf_size_x(&viewborder); fly->height = BLI_rctf_size_y(&viewborder); fly->center_mval[0] = viewborder.xmin + fly->width / 2; fly->center_mval[1] = viewborder.ymin + fly->height / 2; } else { fly->width = fly->ar->winx; fly->height = fly->ar->winy; fly->center_mval[0] = fly->width / 2; fly->center_mval[1] = fly->height / 2; } /* center the mouse, probably the UI mafia are against this but without its quite annoying */ WM_cursor_warp(win, fly->ar->winrct.xmin + fly->center_mval[0], fly->ar->winrct.ymin + fly->center_mval[1]); return 1; }
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) { const char *utf8_buf = NULL; char ascii[2] = {'\0', '\0'}; bool updated = false; short idx = n->idx, idx_max = n->idx_max; short dir = STRCUR_DIR_NEXT, mode = STRCUR_JUMP_NONE; int cur; switch (event->type) { case EVT_MODAL_MAP: if (ELEM(event->val, NUM_MODAL_INCREMENT_UP, NUM_MODAL_INCREMENT_DOWN)) { n->val[idx] += (event->val == NUM_MODAL_INCREMENT_UP) ? n->val_inc[idx] : -n->val_inc[idx]; value_to_editstr(n, idx); n->val_flag[idx] |= NUM_EDITED; updated = true; } else { /* might be a char too... */ utf8_buf = event->utf8_buf; ascii[0] = event->ascii; } break; case BACKSPACEKEY: /* Part specific to backspace... */ if (!(n->val_flag[idx] & NUM_EDITED)) { copy_v3_v3(n->val, n->val_org); n->val_flag[0] &= ~NUM_EDITED; n->val_flag[1] &= ~NUM_EDITED; n->val_flag[2] &= ~NUM_EDITED; n->flag |= NUM_FAKE_EDITED; updated = true; break; } else if (event->shift || !n->str[0]) { n->val[idx] = n->val_org[idx]; n->val_flag[idx] &= ~NUM_EDITED; n->str[0] = '\0'; n->str_cur = 0; updated = true; break; } /* Else, common behavior with DELKEY, only difference is remove char(s) before/after the cursor. */ dir = STRCUR_DIR_PREV; ATTR_FALLTHROUGH; case DELKEY: if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) { int t_cur = cur = n->str_cur; if (event->ctrl) { mode = STRCUR_JUMP_DELIM; } BLI_str_cursor_step_utf8(n->str, strlen(n->str), &t_cur, dir, mode, true); if (t_cur != cur) { if (t_cur < cur) { SWAP(int, t_cur, cur); n->str_cur = cur; } memmove(&n->str[cur], &n->str[t_cur], strlen(&n->str[t_cur]) + 1); /* +1 for trailing '\0'. */ updated = true; } if (!n->str[0]) { n->val[idx] = n->val_org[idx]; } } else { return false; } break; case LEFTARROWKEY: dir = STRCUR_DIR_PREV; ATTR_FALLTHROUGH; case RIGHTARROWKEY: cur = n->str_cur; if (event->ctrl) { mode = STRCUR_JUMP_DELIM; } BLI_str_cursor_step_utf8(n->str, strlen(n->str), &cur, dir, mode, true); if (cur != n->str_cur) { n->str_cur = cur; return true; } return false; case HOMEKEY: if (n->str[0]) { n->str_cur = 0; return true; } return false; case ENDKEY: if (n->str[0]) { n->str_cur = strlen(n->str); return true; } return false; case TABKEY: n->val_flag[idx] &= ~(NUM_NEGATE | NUM_INVERSE); idx = (idx + idx_max + (event->ctrl ? 0 : 2)) % (idx_max + 1); n->idx = idx; if (n->val_flag[idx] & NUM_EDITED) { value_to_editstr(n, idx); } else { n->str[0] = '\0'; n->str_cur = 0; } return true; case PADPERIOD: case PERIODKEY: /* Force numdot, some OSs/countries generate a comma char in this case, sic... (T37992) */ ascii[0] = '.'; utf8_buf = ascii; break; #if 0 /* Those keys are not directly accessible in all layouts, preventing to generate matching events. * So we use a hack (ascii value) instead, see below. */ case EQUALKEY: case PADASTERKEY: if (!(n->flag & NUM_EDIT_FULL)) { n->flag |= NUM_EDIT_FULL; n->val_flag[idx] |= NUM_EDITED; return true; } else if (event->ctrl) { n->flag &= ~NUM_EDIT_FULL; return true; } break; #endif case PADMINUS: case MINUSKEY: if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) { n->val_flag[idx] ^= NUM_NEGATE; updated = true; } break; case PADSLASHKEY: case SLASHKEY: if (event->ctrl || !(n->flag & NUM_EDIT_FULL)) { n->val_flag[idx] ^= NUM_INVERSE; updated = true; } break; case CKEY: if (event->ctrl) { /* Copy current str to the copypaste buffer. */ WM_clipboard_text_set(n->str, 0); updated = true; } break; case VKEY: if (event->ctrl) { /* extract the first line from the clipboard */ int pbuf_len; char *pbuf = WM_clipboard_text_get_firstline(false, &pbuf_len); if (pbuf) { const bool success = editstr_insert_at_cursor(n, pbuf, pbuf_len); MEM_freeN(pbuf); if (!success) { return false; } n->val_flag[idx] |= NUM_EDITED; } updated = true; } break; default: break; } if (!updated && !utf8_buf && (event->utf8_buf[0] || event->ascii)) { utf8_buf = event->utf8_buf; ascii[0] = event->ascii; } /* XXX Hack around keyboards without direct access to '=' nor '*'... */ if (ELEM(ascii[0], '=', '*')) { if (!(n->flag & NUM_EDIT_FULL)) { n->flag |= NUM_EDIT_FULL; n->val_flag[idx] |= NUM_EDITED; return true; } else if (event->ctrl) { n->flag &= ~NUM_EDIT_FULL; return true; } } /* Up to this point, if we have a ctrl modifier, skip. * This allows to still access most of modals' shortcuts even in numinput mode. */ if (!updated && event->ctrl) { return false; } if ((!utf8_buf || !utf8_buf[0]) && ascii[0]) { /* Fallback to ascii. */ utf8_buf = ascii; } if (utf8_buf && utf8_buf[0]) { if (!(n->flag & NUM_EDIT_FULL)) { /* In simple edit mode, we only keep a few chars as valid! */ /* no need to decode unicode, ascii is first char only */ if (!editstr_is_simple_numinput(utf8_buf[0])) { return false; } } if (!editstr_insert_at_cursor(n, utf8_buf, BLI_str_utf8_size(utf8_buf))) { return false; } n->val_flag[idx] |= NUM_EDITED; } else if (!updated) { return false; } /* At this point, our value has changed, try to interpret it with python (if str is not empty!). */ if (n->str[0]) { const float val_prev = n->val[idx]; #ifdef WITH_PYTHON Scene *sce = CTX_data_scene(C); double val; char str_unit_convert[NUM_STR_REP_LEN * 6]; /* Should be more than enough! */ const char *default_unit = NULL; /* Use scale_length if needed! */ const float fac = (float)BKE_scene_unit_scale(&sce->unit, n->unit_type[idx], 1.0); /* Make radian default unit when needed. */ if (n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) default_unit = "r"; BLI_strncpy(str_unit_convert, n->str, sizeof(str_unit_convert)); bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), default_unit, fac, n->unit_sys, n->unit_type[idx]); /* Note: with angles, we always get values as radians here... */ if (BPY_execute_string_as_number(C, str_unit_convert, false, &val)) { n->val[idx] = (float)val; n->val_flag[idx] &= ~NUM_INVALID; } else { n->val_flag[idx] |= NUM_INVALID; } #else /* Very unlikely, but does not harm... */ n->val[idx] = (float)atof(n->str); (void)C; #endif /* WITH_PYTHON */ if (n->val_flag[idx] & NUM_NEGATE) { n->val[idx] = -n->val[idx]; } if (n->val_flag[idx] & NUM_INVERSE) { n->val[idx] = 1.0f / n->val[idx]; } if (UNLIKELY(!isfinite(n->val[idx]))) { n->val[idx] = val_prev; n->val_flag[idx] |= NUM_INVALID; } } /* REDRAW SINCE NUMBERS HAVE CHANGED */ return true; }
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) { wmWindow *win = CTX_wm_window(C); walk->rv3d = CTX_wm_region_view3d(C); walk->v3d = CTX_wm_view3d(C); walk->ar = CTX_wm_region(C); walk->scene = CTX_data_scene(C); #ifdef NDOF_WALK_DEBUG puts("\n-- walk begin --"); #endif /* sanity check: for rare but possible case (if lib-linking the camera fails) */ if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) { walk->rv3d->persp = RV3D_PERSP; } if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library"); return false; } if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) { BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked"); return false; } if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) { BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints"); return false; } walk->state = WALK_RUNNING; if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) { base_speed = U.walk_navigation.walk_speed; userdef_speed = U.walk_navigation.walk_speed; } walk->speed = 0.0f; walk->is_fast = false; walk->is_slow = false; walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : 1.f / walk->scene->unit.scale_length; /* user preference settings */ walk->teleport.duration = U.walk_navigation.teleport_time; walk->mouse_speed = U.walk_navigation.mouse_speed; if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); else walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); walk->view_height = U.walk_navigation.view_height; walk->jump_height = U.walk_navigation.jump_height; walk->speed = U.walk_navigation.walk_speed; walk->speed_factor = U.walk_navigation.walk_speed_factor; walk->gravity_state = WALK_GRAVITY_STATE_OFF; if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) { walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]); } else { walk->gravity = 9.80668f; /* m/s2 */ } walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0); #ifdef USE_TABLET_SUPPORT walk->is_cursor_first = true; walk->is_cursor_absolute = false; #endif walk->active_directions = 0; #ifdef NDOF_WALK_DRAW_TOOMUCH walk->redraw = 1; #endif zero_v3(walk->dvec_prev); walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); walk->ndof = NULL; walk->time_lastdraw = PIL_check_seconds_timer(); walk->draw_handle_pixel = ED_region_draw_cb_activate(walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL); walk->rv3d->rflag |= RV3D_NAVIGATING; walk->snap_context = ED_transform_snap_object_context_create_view3d( CTX_data_main(C), walk->scene, SNAP_OBJECT_USE_CACHE, walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( walk->scene, walk->v3d, walk->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* center the mouse */ walk->center_mval[0] = walk->ar->winx * 0.5f; walk->center_mval[1] = walk->ar->winy * 0.5f; #ifdef USE_PIXELSIZE_NATIVE_SUPPORT walk->center_mval[0] += walk->ar->winrct.xmin; walk->center_mval[1] += walk->ar->winrct.ymin; WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]); walk->center_mval[0] -= walk->ar->winrct.xmin; walk->center_mval[1] -= walk->ar->winrct.ymin; #endif copy_v2_v2_int(walk->prev_mval, walk->center_mval); WM_cursor_warp(win, walk->ar->winrct.xmin + walk->center_mval[0], walk->ar->winrct.ymin + walk->center_mval[1]); /* remove the mouse cursor temporarily */ WM_cursor_modal_set(win, CURSOR_NONE); return 1; }
int join_mesh_shapes_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_active_object(C); Mesh *me= (Mesh *)ob->data; Mesh *selme=NULL; DerivedMesh *dm=NULL; Key *key=me->key; KeyBlock *kb; int ok=0, nonequal_verts=0; CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { if (base->object == ob) continue; if (base->object->type==OB_MESH) { selme = (Mesh *)base->object->data; if (selme->totvert==me->totvert) ok++; else nonequal_verts=1; } } CTX_DATA_END; if (!ok) { if (nonequal_verts) BKE_report(op->reports, RPT_WARNING, "Selected meshes must have equal numbers of vertices."); else BKE_report(op->reports, RPT_WARNING, "No additional selected meshes with equal vertex count to join."); return OPERATOR_CANCELLED; } if(key == NULL) { key= me->key= add_key((ID *)me); key->type= KEY_RELATIVE; /* first key added, so it was the basis. initialise it with the existing mesh */ kb= add_keyblock(key, NULL); mesh_to_key(me, kb); } /* now ready to add new keys from selected meshes */ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { if (base->object == ob) continue; if(base->object->type==OB_MESH) { selme = (Mesh *)base->object->data; if (selme->totvert==me->totvert) { dm = mesh_get_derived_deform(scene, base->object, CD_MASK_BAREMESH); if (!dm) continue; kb= add_keyblock(key, base->object->id.name+2); DM_to_meshkey(dm, me, kb); dm->release(dm); } } } CTX_DATA_END; WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; }
/* Dynamically populate an enum of Keying Sets */ EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) { Scene *scene = CTX_data_scene(C); KeyingSet *ks; EnumPropertyItem *item = NULL, item_tmp = {0}; int totitem = 0; int i = 0; if (C == NULL) { return DummyRNA_DEFAULT_items; } /* active Keying Set * - only include entry if it exists */ if (scene->active_keyingset) { /* active Keying Set */ item_tmp.identifier = "__ACTIVE__"; item_tmp.name = "Active Keying Set"; item_tmp.value = i; RNA_enum_item_add(&item, &totitem, &item_tmp); /* separator */ RNA_enum_item_add_separator(&item, &totitem); } i++; /* user-defined Keying Sets * - these are listed in the order in which they were defined for the active scene */ if (scene->keyingsets.first) { for (ks = scene->keyingsets.first; ks; ks = ks->next, i++) { if (ANIM_keyingset_context_ok_poll(C, ks)) { item_tmp.identifier = ks->idname; item_tmp.name = ks->name; item_tmp.description = ks->description; item_tmp.value = i; RNA_enum_item_add(&item, &totitem, &item_tmp); } } /* separator */ RNA_enum_item_add_separator(&item, &totitem); } /* builtin Keying Sets */ i = -1; for (ks = builtin_keyingsets.first; ks; ks = ks->next, i--) { /* only show KeyingSet if context is suitable */ if (ANIM_keyingset_context_ok_poll(C, ks)) { item_tmp.identifier = ks->idname; item_tmp.name = ks->name; item_tmp.description = ks->description; item_tmp.value = i; RNA_enum_item_add(&item, &totitem, &item_tmp); } } RNA_enum_item_end(&item, &totitem); *r_free = true; return item; }
/* Given a KeyingSet and context info (if required), modify keyframes for the channels specified * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets. * Returns the number of channels that keyframes were added to */ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra) { Scene *scene = CTX_data_scene(C); ReportList *reports = CTX_wm_reports(C); KS_Path *ksp; int kflag = 0, success = 0; const char *groupname = NULL; /* sanity checks */ if (ks == NULL) return 0; /* get flags to use */ if (mode == MODIFYKEY_MODE_INSERT) { /* use KeyingSet's flags as base */ kflag = ks->keyingflag; /* supplement with info from the context */ kflag |= ANIM_get_keyframing_flags(scene, 1); } else if (mode == MODIFYKEY_MODE_DELETE) kflag = 0; /* if relative Keying Sets, poll and build up the paths */ success = ANIM_validate_keyingset(C, dsources, ks); if (success != 0) { /* return error code if failed */ return success; } /* apply the paths as specified in the KeyingSet now */ for (ksp = ks->paths.first; ksp; ksp = ksp->next) { int arraylen, i; short kflag2; /* skip path if no ID pointer is specified */ if (ksp->id == NULL) { BKE_reportf(reports, RPT_WARNING, "Skipping path in keying set, as it has no ID (KS = '%s', path = '%s[%d]')", ks->name, ksp->rna_path, ksp->array_index); continue; } /* since keying settings can be defined on the paths too, extend the path before using it */ kflag2 = (kflag | ksp->keyingflag); /* get pointer to name of group to add channels to */ if (ksp->groupmode == KSP_GROUP_NONE) groupname = NULL; else if (ksp->groupmode == KSP_GROUP_KSNAME) groupname = ks->name; else groupname = ksp->group; /* init arraylen and i - arraylen should be greater than i so that * normal non-array entries get keyframed correctly */ i = ksp->array_index; arraylen = i; /* get length of array if whole array option is enabled */ if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) { PointerRNA id_ptr, ptr; PropertyRNA *prop; RNA_id_pointer_create(ksp->id, &id_ptr); if (RNA_path_resolve_property(&id_ptr, ksp->rna_path, &ptr, &prop)) arraylen = RNA_property_array_length(&ptr, prop); } /* we should do at least one step */ if (arraylen == i) arraylen++; /* for each possible index, perform operation * - assume that arraylen is greater than index */ for (; i < arraylen; i++) { /* action to take depends on mode */ if (mode == MODIFYKEY_MODE_INSERT) success += insert_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); else if (mode == MODIFYKEY_MODE_DELETE) success += delete_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); } /* set recalc-flags */ switch (GS(ksp->id->name)) { case ID_OB: /* Object (or Object-Related) Keyframes */ { Object *ob = (Object *)ksp->id; // XXX: only object transforms? DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; } } /* send notifiers for updates (this doesn't require context to work!) */ WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); } /* return the number of channels successfully affected */ return success; }
/* note: also check undo_history_exec() in bottom if you change notifiers */ static int ed_undo_step(bContext *C, int step, const char *undoname) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); ScrArea *sa = CTX_wm_area(C); /* undo during jobs are running can easily lead to freeing data using by jobs, * or they can just lead to freezing job in some other cases */ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) { return OPERATOR_CANCELLED; } /* grease pencil can be can be used in plenty of spaces, so check it first */ if (ED_gpencil_session_active()) { return ED_undo_gpencil_step(C, step, undoname); } if (sa && (sa->spacetype == SPACE_IMAGE)) { SpaceImage *sima = (SpaceImage *)sa->spacedata.first; if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) { if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) { if (U.uiflag & USER_GLOBALUNDO) { ED_viewport_render_kill_jobs(wm, bmain, true); BKE_undo_name(C, undoname); } } WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; } } if (sa && (sa->spacetype == SPACE_TEXT)) { ED_text_undo_step(C, step); } else if (obedit) { if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) { if (undoname) undo_editmode_name(C, undoname); else undo_editmode_step(C, step); WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } } else { /* Note: we used to do a fall-through here where if the * mode-specific undo system had no more steps to undo (or * redo), the global undo would run. * * That was inconsistent with editmode, and also makes for * unecessarily tricky interaction with the other undo * systems. */ if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) { ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname); } else if (obact && obact->mode & OB_MODE_SCULPT) { ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname); } else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { if (step == 1) PE_undo(scene); else PE_redo(scene); } else if (U.uiflag & USER_GLOBALUNDO) { // note python defines not valid here anymore. //#ifdef WITH_PYTHON // XXX BPY_scripts_clear_pyobjects(); //#endif /* for global undo/redo we should just clear the editmode stack */ /* for example, texface stores image pointers */ undo_editmode_clear(); ED_viewport_render_kill_jobs(wm, bmain, true); if (undoname) BKE_undo_name(C, undoname); else BKE_undo_step(C, step); scene = CTX_data_scene(C); WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); } } WM_event_add_notifier(C, NC_WINDOW, NULL); WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL); if (win) { win->addmousemove = true; } return OPERATOR_FINISHED; }
/* ui callbacks should call this rather than calling WM_operator_repeat() themselves */ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op) { int ret = 0; if (op) { wmWindowManager *wm = CTX_wm_manager(C); struct Scene *scene = CTX_data_scene(C); /* keep in sync with logic in view3d_panel_operator_redo() */ ARegion *ar = CTX_wm_region(C); ARegion *ar1 = BKE_area_find_region_active_win(CTX_wm_area(C)); if (ar1) CTX_wm_region_set(C, ar1); if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) && /* note, undo/redo cant run if there are jobs active, * check for screen jobs only so jobs like material/texture/world preview * (which copy their data), wont stop redo, see [#29579]], * * note, - WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this */ (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY) == 0)) { int retval; ED_viewport_render_kill_jobs(wm, CTX_data_main(C), true); if (G.debug & G_DEBUG) printf("redo_cb: operator redo %s\n", op->type->name); WM_operator_free_all_after(wm, op); ED_undo_pop_op(C, op); if (op->type->check) { if (op->type->check(C, op)) { /* check for popup and re-layout buttons */ ARegion *ar_menu = CTX_wm_menu(C); if (ar_menu) { ED_region_tag_refresh_ui(ar_menu); } } } retval = WM_operator_repeat(C, op); if ((retval & OPERATOR_FINISHED) == 0) { if (G.debug & G_DEBUG) printf("redo_cb: operator redo failed: %s, return %d\n", op->type->name, retval); ED_undo_redo(C); } else { ret = 1; } } else { if (G.debug & G_DEBUG) { printf("redo_cb: WM_operator_repeat_check returned false %s\n", op->type->name); } } /* set region back */ CTX_wm_region_set(C, ar); } else { if (G.debug & G_DEBUG) { printf("redo_cb: ED_undo_operator_repeat called with NULL 'op'\n"); } } return ret; }
static int datalayout_transfer_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob_act = ED_object_active_context(C); DataTransferModifierData *dtmd; dtmd = (DataTransferModifierData *)edit_modifier_property_get(op, ob_act, eModifierType_DataTransfer); /* If we have a modifier, we transfer data layout from this modifier's source object to active one. * Else, we transfer data layout from active object to all selected ones. */ if (dtmd) { Object *ob_src = dtmd->ob_source; Object *ob_dst = ob_act; const bool use_delete = false; /* Never when used from modifier, for now. */ if (!ob_src) { return OPERATOR_CANCELLED; } BKE_object_data_transfer_layout(scene, ob_src, ob_dst, dtmd->data_types, use_delete, dtmd->layers_select_src, dtmd->layers_select_dst); DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); } else { Object *ob_src = ob_act; ListBase ctx_objects; CollectionPointerLink *ctx_ob_dst; const int data_type = RNA_enum_get(op->ptr, "data_type"); const bool use_delete = RNA_boolean_get(op->ptr, "use_delete"); const int layers_src = RNA_enum_get(op->ptr, "layers_select_src"); const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst"); int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0}; int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0}; const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type); if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) { layers_select_src[fromto_idx] = layers_src; layers_select_dst[fromto_idx] = layers_dst; } data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false); for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) { Object *ob_dst = ctx_ob_dst->ptr.data; if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) { BKE_object_data_transfer_layout(scene, ob_src, ob_dst, data_type, use_delete, layers_select_src, layers_select_dst); } DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); } BLI_freelistN(&ctx_objects); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); return OPERATOR_FINISHED; }
/* Note: DT_layers_select_src_items enum is from rna_modifier.c */ static EnumPropertyItem *dt_layers_select_src_itemf( bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { EnumPropertyItem *item = NULL, tmp_item = {0}; int totitem = 0; const int data_type = RNA_enum_get(ptr, "data_type"); if (!C) { /* needed for docs and i18n tools */ return DT_layers_select_src_items; } RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_ACTIVE_SRC); RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_ALL_SRC); if (data_type == DT_TYPE_MDEFORMVERT) { Object *ob_src = CTX_data_active_object(C); if (BKE_object_pose_armature_get(ob_src)) { RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT); RNA_enum_items_add_value(&item, &totitem, DT_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM); } if (ob_src) { bDeformGroup *dg; int i; RNA_enum_item_add_separator(&item, &totitem); for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) { tmp_item.value = i; tmp_item.identifier = tmp_item.name = dg->name; RNA_enum_item_add(&item, &totitem, &tmp_item); } } } else if (data_type == DT_TYPE_SHAPEKEY) { /* TODO */ } else if (data_type == DT_TYPE_UV) { Object *ob_src = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); if (ob_src) { DerivedMesh *dm_src; CustomData *pdata; int num_data, i; /* XXX Is this OK? */ dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MTEXPOLY); pdata = dm_src->getPolyDataLayout(dm_src); num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY); RNA_enum_item_add_separator(&item, &totitem); for (i = 0; i < num_data; i++) { tmp_item.value = i; tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i); RNA_enum_item_add(&item, &totitem, &tmp_item); } } } else if (data_type == DT_TYPE_VCOL) { Object *ob_src = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); if (ob_src) { DerivedMesh *dm_src; CustomData *ldata; int num_data, i; /* XXX Is this OK? */ dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL); ldata = dm_src->getLoopDataLayout(dm_src); num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL); RNA_enum_item_add_separator(&item, &totitem); for (i = 0; i < num_data; i++) { tmp_item.value = i; tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i); RNA_enum_item_add(&item, &totitem, &tmp_item); } } } RNA_enum_item_end(&item, &totitem); *r_free = true; return item; }
static int data_transfer_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob_src = ED_object_active_context(C); ListBase ctx_objects; CollectionPointerLink *ctx_ob_dst; bool changed = false; const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer"); const int data_type = RNA_enum_get(op->ptr, "data_type"); const bool use_create = RNA_boolean_get(op->ptr, "use_create"); const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping"); const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping"); const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping"); const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping"); const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform"); const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform"); const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance"); const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX; const float ray_radius = RNA_float_get(op->ptr, "ray_radius"); const float islands_precision = RNA_float_get(op->ptr, "islands_precision"); const int layers_src = RNA_enum_get(op->ptr, "layers_select_src"); const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst"); int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0}; int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0}; const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type); const int mix_mode = RNA_enum_get(op->ptr, "mix_mode"); const float mix_factor = RNA_float_get(op->ptr, "mix_factor"); SpaceTransform space_transform_data; SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ? &space_transform_data : NULL; if (reverse_transfer && ((ID *)(ob_src->data))->lib) { /* Do not transfer to linked data, not supported. */ return OPERATOR_CANCELLED; } if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) { layers_select_src[fromto_idx] = layers_src; layers_select_dst[fromto_idx] = layers_dst; } data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer); for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) { Object *ob_dst = ctx_ob_dst->ptr.data; if (reverse_transfer) { SWAP(Object *, ob_src, ob_dst); } if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) { if (space_transform) { BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst, ob_src); } if (BKE_object_data_transfer_mesh( scene, ob_src, ob_dst, data_type, use_create, map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, space_transform, use_auto_transform, max_distance, ray_radius, islands_precision, layers_select_src, layers_select_dst, mix_mode, mix_factor, NULL, false, op->reports)) { changed = true; } } DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); if (reverse_transfer) { SWAP(Object *, ob_src, ob_dst); } } BLI_freelistN(&ctx_objects); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); #if 0 /* TODO */ /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED; #else (void)changed; return OPERATOR_FINISHED; #endif }
bool WM_init_game(bContext *C) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win; ScrArea *sa; ARegion *ar = NULL; Scene *scene = CTX_data_scene(C); if (!scene) { /* XXX, this should not be needed. */ Main *bmain = CTX_data_main(C); scene = bmain->scene.first; } win = wm->windows.first; /* first to get a valid window */ if (win) CTX_wm_window_set(C, win); sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0); ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); /* if we have a valid 3D view */ if (sa && ar) { ARegion *arhide; CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); /* disable quad view */ if (ar->alignment == RGN_ALIGN_QSPLIT) WM_operator_name_call(C, "SCREEN_OT_region_quadview", WM_OP_EXEC_DEFAULT, NULL); /* toolbox, properties panel and header are hidden */ for (arhide = sa->regionbase.first; arhide; arhide = arhide->next) { if (arhide->regiontype != RGN_TYPE_WINDOW) { if (!(arhide->flag & RGN_FLAG_HIDDEN)) { ED_region_toggle_hidden(C, arhide); } } } /* full screen the area */ if (!sa->full) { ED_screen_full_toggle(C, win, sa); } /* Fullscreen */ if ((scene->gm.playerflag & GAME_PLAYER_FULLSCREEN)) { WM_operator_name_call(C, "WM_OT_window_fullscreen_toggle", WM_OP_EXEC_DEFAULT, NULL); wm_get_screensize(&ar->winrct.xmax, &ar->winrct.ymax); ar->winx = ar->winrct.xmax + 1; ar->winy = ar->winrct.ymax + 1; } else { GHOST_RectangleHandle rect = GHOST_GetClientBounds(win->ghostwin); ar->winrct.ymax = GHOST_GetHeightRectangle(rect); ar->winrct.xmax = GHOST_GetWidthRectangle(rect); ar->winx = ar->winrct.xmax + 1; ar->winy = ar->winrct.ymax + 1; GHOST_DisposeRectangle(rect); } WM_operator_name_call(C, "VIEW3D_OT_game_start", WM_OP_EXEC_DEFAULT, NULL); sound_exit(); return true; } else { ReportTimerInfo *rti; BKE_report(&wm->reports, RPT_ERROR, "No valid 3D View found, game auto start is not possible"); /* After adding the report to the global list, reset the report timer. */ WM_event_remove_timer(wm, NULL, wm->reports.reporttimer); /* Records time since last report was added */ wm->reports.reporttimer = WM_event_add_timer(wm, CTX_wm_window(C), TIMER, 0.02); rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); wm->reports.reporttimer->customdata = rti; return false; } }
/* function used for WM_OT_save_mainfile too */ static int wm_collada_export_exec(bContext *C, wmOperator *op) { char filepath[FILE_MAX]; int apply_modifiers; int export_mesh_type; int selected; int include_children; int include_armatures; int include_shapekeys; int deform_bones_only; int include_uv_textures; int include_material_textures; int use_texture_copies; int active_uv_only; int triangulate; int use_object_instantiation; int sort_by_name; int export_transformation_type; int open_sim; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } RNA_string_get(op->ptr, "filepath", filepath); BLI_ensure_extension(filepath, sizeof(filepath), ".dae"); /* Avoid File write exceptions in Collada */ if (!BLI_exists(filepath)) { BLI_make_existing_file(filepath); if (!BLI_file_touch(filepath)) { BKE_report(op->reports, RPT_ERROR, "Can't create export file"); fprintf(stdout, "Collada export: Can not create: %s\n", filepath); return OPERATOR_CANCELLED; } } else if (!BLI_file_is_writable(filepath)) { BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file"); fprintf(stdout, "Collada export: Can not modify: %s\n", filepath); return OPERATOR_CANCELLED; } /* Now the exporter can create and write the export file */ /* Options panel */ apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers"); export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection"); selected = RNA_boolean_get(op->ptr, "selected"); include_children = RNA_boolean_get(op->ptr, "include_children"); include_armatures = RNA_boolean_get(op->ptr, "include_armatures"); include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys"); deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only"); include_uv_textures = RNA_boolean_get(op->ptr, "include_uv_textures"); include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures"); use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies"); active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only"); triangulate = RNA_boolean_get(op->ptr, "triangulate"); use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name"); export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection"); open_sim = RNA_boolean_get(op->ptr, "open_sim"); /* get editmode results */ ED_object_editmode_load(CTX_data_edit_object(C)); if (collada_export(CTX_data_scene(C), filepath, apply_modifiers, export_mesh_type, selected, include_children, include_armatures, include_shapekeys, deform_bones_only, active_uv_only, include_uv_textures, include_material_textures, use_texture_copies, triangulate, use_object_instantiation, sort_by_name, export_transformation_type, open_sim)) { return OPERATOR_FINISHED; } else { BKE_report(op->reports, RPT_WARNING, "Export file not created"); return OPERATOR_CANCELLED; } }
static int prefetch_get_start_frame(const bContext *C) { Scene *scene = CTX_data_scene(C); return SFRA; }
static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event) { View2D *v2d= UI_view2d_fromcontext(C); Scene *scene= CTX_data_scene(C); Editing *ed= seq_give_editing(scene, FALSE); short extend= RNA_boolean_get(op->ptr, "extend"); short linked_handle= RNA_boolean_get(op->ptr, "linked_handle"); short left_right= RNA_boolean_get(op->ptr, "left_right"); short linked_time= RNA_boolean_get(op->ptr, "linked_time"); Sequence *seq,*neighbor, *act_orig; int hand,sel_side; TimeMarker *marker; if(ed==NULL) return OPERATOR_CANCELLED; marker=find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now seq= find_nearest_seq(scene, v2d, &hand, event->mval); // XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip if(seq && linked_time && left_right) left_right= FALSE; if (marker) { int oldflag; /* select timeline marker */ if (extend) { oldflag= marker->flag; if (oldflag & SELECT) marker->flag &= ~SELECT; else marker->flag |= SELECT; } else { /* deselect_markers(0, 0); */ /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */ marker->flag |= SELECT; } } else if (left_right) { /* use different logic for this */ float x; deselect_all_seq(scene); UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, NULL); SEQP_BEGIN(ed, seq) { if (x < CFRA) { if(seq->enddisp < CFRA) { seq->flag |= SELECT; recurs_sel_seq(seq); } } else { if(seq->startdisp > CFRA) { seq->flag |= SELECT; recurs_sel_seq(seq); } } } SEQ_END { SpaceSeq *sseq= CTX_wm_space_seq(C); if (sseq && sseq->flag & SEQ_MARKER_TRANS) { TimeMarker *tmarker; for (tmarker= scene->markers.first; tmarker; tmarker= tmarker->next) { if( ((x < CFRA) && tmarker->frame < CFRA) || ((x >= CFRA) && tmarker->frame >= CFRA) ) { tmarker->flag |= SELECT; } else { tmarker->flag &= ~SELECT; } } } } } else {
static int add_keyingset_button_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); KeyingSet *ks = NULL; PropertyRNA *prop = NULL; PointerRNA ptr = {{NULL}}; char *path = NULL; short success = 0; int index = 0, pflag = 0; const bool all = RNA_boolean_get(op->ptr, "all"); /* verify the Keying Set to use: * - use the active one for now (more control over this can be added later) * - add a new one if it doesn't exist */ if (scene->active_keyingset == 0) { short flag = 0, keyingflag = 0; /* validate flags * - absolute KeyingSets should be created by default */ flag |= KEYINGSET_ABSOLUTE; keyingflag |= ANIM_get_keyframing_flags(scene, 0); if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) keyingflag |= INSERTKEY_XYZ2RGB; /* call the API func, and set the active keyingset index */ ks = BKE_keyingset_add(&scene->keyingsets, "ButtonKeyingSet", "Button Keying Set", flag, keyingflag); scene->active_keyingset = BLI_countlist(&scene->keyingsets); } else if (scene->active_keyingset < 0) { BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in keying set"); return OPERATOR_CANCELLED; } else { ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1); } /* try to add to keyingset using property retrieved from UI */ uiContextActiveProperty(C, &ptr, &prop, &index); /* check if property is able to be added */ if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { path = RNA_path_from_ID_to_property(&ptr, prop); if (path) { /* set flags */ if (all) { pflag |= KSP_FLAG_WHOLE_ARRAY; /* we need to set the index for this to 0, even though it may break in some cases, this is * necessary if we want the entire array for most cases to get included without the user * having to worry about where they clicked */ index = 0; } /* add path to this setting */ BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME); ks->active_path = BLI_countlist(&ks->paths); success = 1; /* free the temp path created */ MEM_freeN(path); } } if (success) { /* send updates */ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL); /* show notification/report header, so that users notice that something changed */ BKE_reportf(op->reports, RPT_INFO, "Property added to Keying Set: '%s'", ks->name); } return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; }
static bool screen_opengl_render_init(bContext *C, wmOperator *op) { /* new render clears all callbacks */ wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); ScrArea *prevsa = CTX_wm_area(C); ARegion *prevar = CTX_wm_region(C); GPUOffScreen *ofs; OGLRender *oglrender; int sizex, sizey; const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0; const bool full_samples = (samples != 0) && (scene->r.scemode & R_FULL_SAMPLE); bool is_view_context = RNA_boolean_get(op->ptr, "view_context"); const bool is_animation = RNA_boolean_get(op->ptr, "animation"); const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); char err_out[256] = "unknown"; if (G.background) { BKE_report(op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)"); return false; } /* only one render job at a time */ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) return false; if (is_sequencer) { is_view_context = false; } else { /* ensure we have a 3d view */ if (!ED_view3d_context_activate(C)) { RNA_boolean_set(op->ptr, "view_context", false); is_view_context = false; } if (!is_view_context && scene->camera == NULL) { BKE_report(op->reports, RPT_ERROR, "Scene has no camera"); return false; } } if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); return false; } /* stop all running jobs, except screen one. currently previews frustrate Render */ WM_jobs_kill_all_except(wm, CTX_wm_screen(C)); /* create offscreen buffer */ sizex = (scene->r.size * scene->r.xsch) / 100; sizey = (scene->r.size * scene->r.ysch) / 100; /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, GPU_HDR_NONE, GPU_OFFSCREEN_DEPTH_COMPARE, err_out); if (!ofs) { BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out); return false; } /* allocate opengl render */ oglrender = MEM_callocN(sizeof(OGLRender), "OGLRender"); op->customdata = oglrender; oglrender->ofs = ofs; oglrender->ofs_samples = samples; oglrender->ofs_full_samples = full_samples; oglrender->sizex = sizex; oglrender->sizey = sizey; oglrender->bmain = CTX_data_main(C); oglrender->scene = scene; oglrender->cfrao = scene->r.cfra; oglrender->write_still = is_write_still && !is_animation; oglrender->is_animation = is_animation; oglrender->views_len = BKE_scene_multiview_num_views_get(&scene->r); oglrender->is_sequencer = is_sequencer; if (is_sequencer) { oglrender->sseq = CTX_wm_space_seq(C); ImBuf **ibufs_arr = MEM_callocN(sizeof(*ibufs_arr) * oglrender->views_len, __func__); oglrender->seq_data.ibufs_arr = ibufs_arr; } oglrender->prevsa = prevsa; oglrender->prevar = prevar; if (is_view_context) { ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->ar); /* so quad view renders camera */ oglrender->rv3d = oglrender->ar->regiondata; /* MUST be cleared on exit */ oglrender->scene->customdata_mask_modal = ED_view3d_datamask(oglrender->scene, oglrender->v3d); /* apply immediately in case we're rendering from a script, * running notifiers again will overwrite */ oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal; if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) { oglrender->fx = GPU_fx_compositor_create(); } } /* create render */ oglrender->re = RE_NewRender(scene->id.name); /* create image and image user */ oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE); BKE_image_backup_render(oglrender->scene, oglrender->ima, true); oglrender->iuser.scene = scene; oglrender->iuser.ok = 1; /* create render result */ RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL); /* create render views */ screen_opengl_views_setup(oglrender); /* wm vars */ oglrender->wm = wm; oglrender->win = win; oglrender->totvideos = 0; oglrender->mh = NULL; oglrender->movie_ctx_arr = NULL; if (is_animation) { TaskScheduler *task_scheduler = BLI_task_scheduler_get(); if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { task_scheduler = BLI_task_scheduler_create(1); oglrender->task_scheduler = task_scheduler; oglrender->task_pool = BLI_task_pool_create_background(task_scheduler, oglrender); BLI_pool_set_num_threads(oglrender->task_pool, 1); } else { oglrender->task_scheduler = NULL; oglrender->task_pool = BLI_task_pool_create(task_scheduler, oglrender); } oglrender->pool_ok = true; BLI_spin_init(&oglrender->reports_lock); } else { oglrender->task_scheduler = NULL; oglrender->task_pool = NULL; } oglrender->num_scheduled_frames = 0; BLI_mutex_init(&oglrender->task_mutex); BLI_condition_init(&oglrender->task_condition); #ifdef DEBUG_TIME oglrender->time_start = PIL_check_seconds_timer(); #endif return true; }
/* poll callback for adding default KeyingSet */ static int keyingset_poll_default_add(bContext *C) { /* as long as there's an active Scene, it's fine */ return (CTX_data_scene(C) != NULL); }
static int wm_alembic_export_exec(bContext *C, wmOperator *op) { if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } char filename[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filename); const struct AlembicExportParams params = { .frame_start = RNA_int_get(op->ptr, "start"), .frame_end = RNA_int_get(op->ptr, "end"), .frame_step_xform = 1.0 / (double)RNA_int_get(op->ptr, "xsamples"), .frame_step_shape = 1.0 / (double)RNA_int_get(op->ptr, "gsamples"), .shutter_open = RNA_float_get(op->ptr, "sh_open"), .shutter_close = RNA_float_get(op->ptr, "sh_close"), .selected_only = RNA_boolean_get(op->ptr, "selected"), .uvs = RNA_boolean_get(op->ptr, "uvs"), .normals = RNA_boolean_get(op->ptr, "normals"), .vcolors = RNA_boolean_get(op->ptr, "vcolors"), .apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"), .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"), .visible_layers_only = RNA_boolean_get(op->ptr, "visible_layers_only"), .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"), .face_sets = RNA_boolean_get(op->ptr, "face_sets"), .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), .compression_type = RNA_enum_get(op->ptr, "compression_type"), .packuv = RNA_boolean_get(op->ptr, "packuv"), .triangulate = RNA_boolean_get(op->ptr, "triangulate"), .quad_method = RNA_enum_get(op->ptr, "quad_method"), .ngon_method = RNA_enum_get(op->ptr, "ngon_method"), .global_scale = RNA_float_get(op->ptr, "global_scale"), }; ABC_export(CTX_data_scene(C), C, filename, ¶ms); return OPERATOR_FINISHED; } static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) { uiLayout *box; uiLayout *row; #ifdef WITH_ALEMBIC_HDF5 box = uiLayoutBox(layout); row = uiLayoutRow(box, false); uiItemL(row, IFACE_("Archive Options:"), ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "compression_type", 0, NULL, ICON_NONE); #endif box = uiLayoutBox(layout); row = uiLayoutRow(box, false); uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "global_scale", 0, NULL, ICON_NONE); /* Scene Options */ box = uiLayoutBox(layout); row = uiLayoutRow(box, false); uiItemL(row, IFACE_("Scene Options:"), ICON_SCENE_DATA); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "start", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "end", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "xsamples", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "gsamples", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "sh_open", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "sh_close", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "renderable_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "visible_layers_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "flatten", 0, NULL, ICON_NONE); /* Object Data */ box = uiLayoutBox(layout); row = uiLayoutRow(box, false); uiItemL(row, IFACE_("Object Options:"), ICON_OBJECT_DATA); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "uvs", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "packuv", 0, NULL, ICON_NONE); uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "uvs")); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "normals", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "vcolors", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "face_sets", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "subdiv_schema", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "apply_subdiv", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE); const bool triangulate = RNA_boolean_get(imfptr, "triangulate"); row = uiLayoutRow(box, false); uiLayoutSetEnabled(row, triangulate); uiItemR(row, imfptr, "quad_method", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiLayoutSetEnabled(row, triangulate); uiItemR(row, imfptr, "ngon_method", 0, NULL, ICON_NONE); }
static int add_vertex_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; float co[2]; if (mask == NULL) { /* if there's no active mask, create one */ mask = ED_mask_new(C, NULL); } masklay = BKE_mask_layer_active(mask); if (masklay && masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { masklay = NULL; } RNA_float_get_array(op->ptr, "location", co); /* TODO, having an active point but no active spline is possible, why? */ if (masklay && masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) { /* cheap trick - double click for cyclic */ MaskSpline *spline = masklay->act_spline; MaskSplinePoint *point = masklay->act_point; int is_sta = (point == spline->points); int is_end = (point == &spline->points[spline->tot_point - 1]); /* then check are we overlapping the mouse */ if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) { if (spline->flag & MASK_SPLINE_CYCLIC) { /* nothing to do */ return OPERATOR_CANCELLED; } else { /* recalc the connecting point as well to make a nice even curve */ MaskSplinePoint *point_other = is_end ? spline->points : &spline->points[spline->tot_point - 1]; spline->flag |= MASK_SPLINE_CYCLIC; /* TODO, update keyframes in time */ BKE_mask_calc_handle_point_auto(spline, point, FALSE); BKE_mask_calc_handle_point_auto(spline, point_other, FALSE); /* TODO: only update this spline */ BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; } } if (!add_vertex_subdivide(C, mask, co)) { if (!add_vertex_extrude(C, mask, masklay, co)) { return OPERATOR_CANCELLED; } } } else { if (!add_vertex_subdivide(C, mask, co)) { if (!add_vertex_new(C, mask, masklay, co)) { return OPERATOR_CANCELLED; } } } /* TODO: only update this spline */ BKE_mask_update_display(mask, CFRA); return OPERATOR_FINISHED; }
static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNode *unode) { Scene *scene = CTX_data_scene(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; MVert *mvert; int *index; if (unode->maxvert) { /* regular mesh restore */ if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) { /* shape key has been changed before calling undo operator */ Key *key = BKE_key_from_object(ob); KeyBlock *kb = key ? BKE_keyblock_find_name(key, unode->shapeName) : NULL; if (kb) { ob->shapenr = BLI_findindex(&key->block, kb) + 1; BKE_sculpt_update_mesh_elements(scene, sd, ob, 0, false); WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); } else { /* key has been removed -- skip this undo node */ return 0; } } /* no need for float comparison here (memory is exactly equal or not) */ index = unode->index; mvert = ss->mvert; if (ss->kb) { float (*vertCos)[3]; vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->kb); if (unode->orig_co) { if (ss->modifiers_active) { for (int i = 0; i < unode->totvert; i++) { sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]); } } else { for (int i = 0; i < unode->totvert; i++) { swap_v3_v3(vertCos[index[i]], unode->orig_co[i]); } } } else { for (int i = 0; i < unode->totvert; i++) { swap_v3_v3(vertCos[index[i]], unode->co[i]); } } /* propagate new coords to keyblock */ sculpt_vertcos_to_key(ob, ss->kb, vertCos); /* pbvh uses it's own mvert array, so coords should be */ /* propagated to pbvh here */ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos); MEM_freeN(vertCos); } else { if (unode->orig_co) { if (ss->modifiers_active) { for (int i = 0; i < unode->totvert; i++) { if (sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co)) { mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } } else { for (int i = 0; i < unode->totvert; i++) { if (test_swap_v3_v3(mvert[index[i]].co, unode->orig_co[i])) { mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } } } else { for (int i = 0; i < unode->totvert; i++) { if (test_swap_v3_v3(mvert[index[i]].co, unode->co[i])) { mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } } } } else if (unode->maxgrid && dm->getGridData) { /* multires restore */ CCGElem **grids, *grid; CCGKey key; float (*co)[3]; int gridsize; grids = dm->getGridData(dm); gridsize = dm->getGridSize(dm); dm->getGridKey(dm, &key); co = unode->co; for (int j = 0; j < unode->totgrid; j++) { grid = grids[unode->grids[j]]; for (int i = 0; i < gridsize * gridsize; i++, co++) { swap_v3_v3(CCG_elem_offset_co(&key, grid, i), co[0]); } } } return 1; }
extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing) { /* context values */ 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(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); // 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->far, 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); } // 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 int mesh_bisect_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); /* both can be NULL, fallbacks values are used */ View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ED_view3d_context_rv3d(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm; BMOperator bmop; float plane_co[3]; float plane_no[3]; float imat[4][4]; const float thresh = RNA_float_get(op->ptr, "threshold"); const bool use_fill = RNA_boolean_get(op->ptr, "use_fill"); const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner"); const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer"); PropertyRNA *prop_plane_co; PropertyRNA *prop_plane_no; prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co"); if (RNA_property_is_set(op->ptr, prop_plane_co)) { RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co); } else { copy_v3_v3(plane_co, ED_view3d_cursor3d_get(scene, v3d)); RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co); } prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no"); if (RNA_property_is_set(op->ptr, prop_plane_no)) { RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no); } else { if (rv3d) { copy_v3_v3(plane_no, rv3d->viewinv[1]); } else { /* fallback... */ plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f; } RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no); } /* -------------------------------------------------------------------- */ /* Modal support */ /* Note: keep this isolated, exec can work wihout this */ if ((op->customdata != NULL) && mesh_bisect_interactive_calc(C, op, em, plane_co, plane_no)) { /* write back to the props */ RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no); RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co); } /* End Modal */ /* -------------------------------------------------------------------- */ bm = em->bm; invert_m4_m4(imat, obedit->obmat); mul_m4_v3(imat, plane_co); mul_mat3_m4_v3(imat, plane_no); EDBM_op_init(em, &bmop, op, "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b", BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer); BMO_op_exec(bm, &bmop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); if (use_fill) { float normal_fill[3]; BMOperator bmop_fill; BMOperator bmop_attr; normalize_v3_v3(normal_fill, plane_no); if (clear_outer == true && clear_inner == false) { negate_v3(normal_fill); } /* Fill */ BMO_op_initf( bm, &bmop_fill, op->flag, "triangle_fill edges=%S normal=%v use_dissolve=%b", &bmop, "geom_cut.out", normal_fill, true); BMO_op_exec(bm, &bmop_fill); /* Copy Attributes */ BMO_op_initf(bm, &bmop_attr, op->flag, "face_attribute_fill faces=%S use_normals=%b use_data=%b", &bmop_fill, "geom.out", false, true); BMO_op_exec(bm, &bmop_attr); BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true); BMO_op_finish(bm, &bmop_attr); BMO_op_finish(bm, &bmop_fill); } BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true); if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; } else { EDBM_update_generic(em, true, true); EDBM_selectmode_flush(em); return OPERATOR_FINISHED; } }
int join_mesh_exec(bContext *C, wmOperator *op) { Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_active_object(C); Material **matar, *ma; Mesh *me; MVert *mvert, *mv; MEdge *medge = NULL; MFace *mface = NULL; Key *key, *nkey=NULL; KeyBlock *kb, *okb, *kbn; float imat[4][4], cmat[4][4], *fp1, *fp2, curpos; int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0; int vertofs, *matmap=NULL; int i, j, index, haskey=0, edgeofs, faceofs; bDeformGroup *dg, *odg; MDeformVert *dvert; CustomData vdata, edata, fdata; if(scene->obedit) { BKE_report(op->reports, RPT_WARNING, "Cant join while in editmode"); return OPERATOR_CANCELLED; } /* ob is the object we are adding geometry to */ if(!ob || ob->type!=OB_MESH) { BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh"); return OPERATOR_CANCELLED; } /* count & check */ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { if(base->object->type==OB_MESH) { me= base->object->data; totvert+= me->totvert; totedge+= me->totedge; totface+= me->totface; totmat+= base->object->totcol; if(base->object == ob) ok= 1; /* check for shapekeys */ if(me->key) haskey++; } } CTX_DATA_END; /* that way the active object is always selected */ if(ok==0) { BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh"); return OPERATOR_CANCELLED; } /* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */ me= (Mesh *)ob->data; key= me->key; if(totvert==0 || totvert==me->totvert) { BKE_report(op->reports, RPT_WARNING, "No mesh data to join"); return OPERATOR_CANCELLED; } if(totvert > MESH_MAX_VERTS) { BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is " STRINGIFY(MESH_MAX_VERTS), totvert); return OPERATOR_CANCELLED; } /* new material indices and material array */ matar= MEM_callocN(sizeof(void*)*totmat, "join_mesh matar"); if (totmat) matmap= MEM_callocN(sizeof(int)*totmat, "join_mesh matmap"); totcol= ob->totcol; /* obact materials in new main array, is nicer start! */ for(a=0; a<ob->totcol; a++) { matar[a]= give_current_material(ob, a+1); id_us_plus((ID *)matar[a]); /* increase id->us : will be lowered later */ } /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders * with arrays that are large enough to hold shapekey data for all meshes * - if destination mesh didn't have shapekeys, but we encountered some in the meshes we're * joining, set up a new keyblock and assign to the mesh */ if(key) { /* make a duplicate copy that will only be used here... (must remember to free it!) */ nkey= copy_key(key); /* for all keys in old block, clear data-arrays */ for(kb= key->block.first; kb; kb= kb->next) { if(kb->data) MEM_freeN(kb->data); kb->data= MEM_callocN(sizeof(float)*3*totvert, "join_shapekey"); kb->totelem= totvert; kb->weights= NULL; } } else if(haskey) { /* add a new key-block and add to the mesh */ key= me->key= add_key((ID *)me); key->type = KEY_RELATIVE; } /* first pass over objects - copying materials and vertexgroups across */ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { /* only act if a mesh, and not the one we're joining to */ if((ob!=base->object) && (base->object->type==OB_MESH)) { me= base->object->data; /* Join this object's vertex groups to the base one's */ for(dg=base->object->defbase.first; dg; dg=dg->next) { /* See if this group exists in the object (if it doesn't, add it to the end) */ if(!defgroup_find_name(ob, dg->name)) { odg = MEM_callocN(sizeof(bDeformGroup), "join deformGroup"); memcpy(odg, dg, sizeof(bDeformGroup)); BLI_addtail(&ob->defbase, odg); } } if(ob->defbase.first && ob->actdef==0) ob->actdef=1; if(me->totvert) { /* Add this object's materials to the base one's if they don't exist already (but only if limits not exceeded yet) */ if(totcol < MAXMAT-1) { for(a=1; a<=base->object->totcol; a++) { ma= give_current_material(base->object, a); for(b=0; b<totcol; b++) { if(ma == matar[b]) break; } if(b==totcol) { matar[b]= ma; if(ma) ma->id.us++; totcol++; } if(totcol>=MAXMAT-1) break; } } /* if this mesh has shapekeys, check if destination mesh already has matching entries too */ if(me->key && key) { for(kb= me->key->block.first; kb; kb= kb->next) { /* if key doesn't exist in destination mesh, add it */ if(key_get_named_keyblock(key, kb->name) == NULL) { /* copy this existing one over to the new shapekey block */ kbn= MEM_dupallocN(kb); kbn->prev= kbn->next= NULL; /* adjust adrcode and other settings to fit (allocate a new data-array) */ kbn->data= MEM_callocN(sizeof(float)*3*totvert, "joined_shapekey"); kbn->totelem= totvert; kbn->weights= NULL; okb= key->block.last; curpos= (okb) ? okb->pos : -0.1f; if(key->type == KEY_RELATIVE) kbn->pos= curpos + 0.1f; else kbn->pos= curpos; BLI_addtail(&key->block, kbn); kbn->adrcode= key->totkey; key->totkey++; if(key->totkey==1) key->refkey= kbn; // XXX 2.5 Animato #if 0 /* also, copy corresponding ipo-curve to ipo-block if applicable */ if(me->key->ipo && key->ipo) { // FIXME... this is a luxury item! puts("FIXME: ignoring IPO's when joining shapekeys on Meshes for now..."); } #endif } } } } } } CTX_DATA_END; /* setup new data for destination mesh */ memset(&vdata, 0, sizeof(vdata)); memset(&edata, 0, sizeof(edata)); memset(&fdata, 0, sizeof(fdata)); mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface); vertofs= 0; edgeofs= 0; faceofs= 0; /* inverse transform for all selected meshes in this object */ invert_m4_m4(imat, ob->obmat); CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { /* only join if this is a mesh */ if(base->object->type==OB_MESH) { me= base->object->data; if(me->totvert) { /* standard data */ CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert); /* vertex groups */ dvert= CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); /* NB: vertex groups here are new version */ if(dvert) { for(i=0; i<me->totvert; i++) { for(j=0; j<dvert[i].totweight; j++) { /* Find the old vertex group */ odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr); if(odg) { /* Search for a match in the new object, and set new index */ for(dg=ob->defbase.first, index=0; dg; dg=dg->next, index++) { if(!strcmp(dg->name, odg->name)) { dvert[i].dw[j].def_nr = index; break; } } } } } } /* if this is the object we're merging into, no need to do anything */ if(base->object != ob) { /* watch this: switch matmul order really goes wrong */ mul_m4_m4m4(cmat, base->object->obmat, imat); /* transform vertex coordinates into new space */ for(a=0, mv=mvert; a < me->totvert; a++, mv++) { mul_m4_v3(cmat, mv->co); } /* for each shapekey in destination mesh: * - if there's a matching one, copy it across (will need to transform vertices into new space...) * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) */ if(key) { /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ for(kb= key->block.first; kb; kb= kb->next) { /* get pointer to where to write data for this mesh in shapekey's data array */ fp1= ((float *)kb->data) + (vertofs*3); /* check if this mesh has such a shapekey */ okb= key_get_named_keyblock(me->key, kb->name); if(okb) { /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ fp2= ((float *)(okb->data)); for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) { VECCOPY(fp1, fp2); mul_m4_v3(cmat, fp1); } } else { /* copy this mesh's vertex coordinates to the destination shapekey */ mv= mvert; for(a=0; a < me->totvert; a++, fp1+=3, mv++) { VECCOPY(fp1, mv->co); } } } } } else { /* for each shapekey in destination mesh: * - if it was an 'original', copy the appropriate data from nkey * - otherwise, copy across plain coordinates (no need to transform coordinates) */ if(key) { for(kb= key->block.first; kb; kb= kb->next) { /* get pointer to where to write data for this mesh in shapekey's data array */ fp1= ((float *)kb->data) + (vertofs*3); /* check if this was one of the original shapekeys */ okb= key_get_named_keyblock(nkey, kb->name); if(okb) { /* copy this mesh's shapekey to the destination shapekey */ fp2= ((float *)(okb->data)); for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) { VECCOPY(fp1, fp2); } } else { /* copy base-coordinates to the destination shapekey */ mv= mvert; for(a=0; a < me->totvert; a++, fp1+=3, mv++) { VECCOPY(fp1, mv->co); } } } } } /* advance mvert pointer to end of base mesh's data */ mvert+= me->totvert; } if(me->totface) { /* make mapping for materials */ for(a=1; a<=base->object->totcol; a++) { ma= give_current_material(base->object, a); for(b=0; b<totcol; b++) { if(ma == matar[b]) { matmap[a-1]= b; break; } } } if(base->object!=ob) multiresModifier_prepare_join(scene, base->object, ob); CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface); CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface); for(a=0; a<me->totface; a++, mface++) { mface->v1+= vertofs; mface->v2+= vertofs; mface->v3+= vertofs; if(mface->v4) mface->v4+= vertofs; if (matmap) mface->mat_nr= matmap[(int)mface->mat_nr]; else mface->mat_nr= 0; } faceofs += me->totface; } if(me->totedge) { CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge); for(a=0; a<me->totedge; a++, medge++) { medge->v1+= vertofs; medge->v2+= vertofs; } edgeofs += me->totedge; } /* vertofs is used to help newly added verts be reattached to their edge/face * (cannot be set earlier, or else reattaching goes wrong) */ vertofs += me->totvert; /* free base, now that data is merged */ if(base->object != ob) ED_base_object_free_and_unlink(bmain, scene, base); } } CTX_DATA_END; /* return to mesh we're merging to */ me= ob->data; CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); me->totvert= totvert; me->totedge= totedge; me->totface= totface; me->vdata= vdata; me->edata= edata; me->fdata= fdata; mesh_update_customdata_pointers(me); /* old material array */ for(a=1; a<=ob->totcol; a++) { ma= ob->mat[a-1]; if(ma) ma->id.us--; } for(a=1; a<=me->totcol; a++) { ma= me->mat[a-1]; if(ma) ma->id.us--; } if(ob->mat) MEM_freeN(ob->mat); if(ob->matbits) MEM_freeN(ob->matbits); if(me->mat) MEM_freeN(me->mat); ob->mat= me->mat= NULL; ob->matbits= NULL; if(totcol) { me->mat= matar; ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar"); ob->matbits= MEM_callocN(sizeof(char)*totcol, "join obmatbits"); } else MEM_freeN(matar); ob->totcol= me->totcol= totcol; ob->colbits= 0; if (matmap) MEM_freeN(matmap); /* other mesh users */ test_object_materials((ID *)me); /* free temp copy of destination shapekeys (if applicable) */ if(nkey) { // XXX 2.5 Animato #if 0 /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */ if(nkey->ipo) { free_ipo(nkey->ipo); BLI_remlink(&bmain->ipo, nkey->ipo); MEM_freeN(nkey->ipo); } #endif free_key(nkey); BLI_remlink(&bmain->key, nkey); MEM_freeN(nkey); } DAG_scene_sort(bmain, scene); // removed objects, need to rebuild dag before editmode call #if 0 ED_object_enter_editmode(C, EM_WAITCURSOR); ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR|EM_DO_UNDO); #else /* toggle editmode using lower level functions so this can be called from python */ make_editMesh(scene, ob); load_editMesh(scene, ob); free_editMesh(me->edit_mesh); MEM_freeN(me->edit_mesh); me->edit_mesh= NULL; DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA); #endif WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; }
int fluidsimBake(bContext *C, ReportList *reports, Object *ob) { Scene *scene= CTX_data_scene(C); FILE *fileCfg; int i; Object *fsDomain = NULL; FluidsimSettings *domainSettings; Object *obit = NULL; /* object iterator */ Base *base; int origFrame = scene->r.cfra; char debugStrBuffer[256]; int dirExist = 0; int gridlevels = 0; int simAborted = 0; // was the simulation aborted by user? int doExportOnly = 0; char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY"; const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp //char *channelNames[3] = { "translation","rotation","scale" }; char *suffixConfig = "fluidsim.cfg"; char *suffixSurface = "fluidsurface"; char newSurfdataPath[FILE_MAXDIR+FILE_MAXFILE]; // modified output settings 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 int haveSomeFluid = 0; // check if any fluid objects are set // config vars, inited before either export or run... double calcViscosity = 0.0; int noFrames; double aniFrameTime; float aniFrlen; int channelObjCount; float *bbStart = NULL; float *bbSize = NULL; float domainMat[4][4]; float invDomMat[4][4]; // channel data int allchannelSize; // fixed by no. of frames int startFrame = 1; // dont use scene->r.sfra here, always start with frame 1 // easy frame -> sim time calc float *timeAtFrame=NULL, *timeAtIndex=NULL; // domain float *channelDomainTime = NULL; float *channelDomainViscosity = NULL; float *channelDomainGravity = NULL; // objects (currently max. 256 objs) float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale float *channelObjInivel[256]; // initial velocities float *channelObjActive[256]; // obj active channel /* fluid control channels */ float *channelAttractforceStrength[256]; float *channelAttractforceRadius[256]; float *channelVelocityforceStrength[256]; float *channelVelocityforceRadius[256]; FluidsimModifierData *fluidmd = NULL; Mesh *mesh = NULL; 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); } if(getenv(exportEnvStr)) { doExportOnly = atoi(getenv(exportEnvStr)); snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr); 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."); return 0; } /* no object pointer, find in selected ones.. */ if(!ob) { for(base=scene->base.first; base; base= base->next) { if ((base)->flag & SELECT) { FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); if(fluidmdtmp && (base->object->type==OB_MESH)) { if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) { ob = base->object; break; } } } } // no domains found? if(!ob) return 0; } channelObjCount = 0; for(base=scene->base.first; base; base= base->next) { FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); obit = base->object; if( fluidmdtmp && (obit->type==OB_MESH) && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) { channelObjCount++; } } if (channelObjCount>=255) { BKE_report(reports, RPT_ERROR, "Cannot bake with more then 256 objects."); return 0; } /* check if there's another domain... */ for(base=scene->base.first; base; base= base->next) { FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); obit = base->object; if( fluidmdtmp &&(obit->type==OB_MESH)) { if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) { if(obit != ob) { BKE_report(reports, RPT_ERROR, "There should be only one domain object."); return 0; } } } } // check if theres any fluid // abort baking if not... for(base=scene->base.first; base; base= base->next) { FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); obit = base->object; if( fluidmdtmp && (obit->type==OB_MESH) && ((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) || (fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) )) { haveSomeFluid = 1; break; } } if(!haveSomeFluid) { BKE_report(reports, RPT_ERROR, "No fluid objects in scene."); return 0; } /* these both have to be valid, otherwise we wouldnt be here */ /* dont use ob here after...*/ fsDomain = ob; fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); domainSettings = fluidmd->fss; ob = NULL; mesh = fsDomain->data; // 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 names... strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no strcpy(targetFile, targetDir); strcat(targetFile, suffixConfig); if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file // 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 if(!doExportOnly) { BLI_delete(targetFile, 0,0); } } if((strlen(targetDir)<1) || (!dirExist)) { char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE]; // invalid dir, reset to current/previous strcpy(blendDir, G.sce); BLI_splitdirstring(blendDir, blendFile); if(strlen(blendFile)>6){ int len = strlen(blendFile); if( (blendFile[len-6]=='.')&& (blendFile[len-5]=='b')&& (blendFile[len-4]=='l')&& (blendFile[len-3]=='e')&& (blendFile[len-2]=='n')&& (blendFile[len-1]=='d') ){ blendFile[len-6] = '\0'; } } // todo... strip .blend ? snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name); snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath); elbeemDebugOut(debugStrBuffer); outStringsChanged=1; } // check if modified output dir is ok if(outStringsChanged) { char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256]; int selection=0; strcpy(dispmsg,"Output settings set to: '"); 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 strcpy(targetDir, newSurfdataPath); strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no } // -------------------------------------------------------------------------------------------- // dump data for start frame // CHECK more reasonable to number frames according to blender? // dump data for frame 0 scene->r.cfra = startFrame; ED_update_for_newframe(C, 1); // init common export vars for both file export and run for(i=0; i<256; i++) { channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL; channelObjInivel[i] = NULL; channelObjActive[i] = NULL; channelAttractforceStrength[i] = NULL; channelAttractforceRadius[i] = NULL; channelVelocityforceStrength[i] = NULL; channelVelocityforceRadius[i] = NULL; } allchannelSize = scene->r.efra; // always use till last frame aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames; // blender specific - scale according to map old/new settings in anim panel: aniFrlen = scene->r.framelen; if(domainSettings->viscosityMode==1) { /* manual mode, visc=value/(10^-vexp) */ calcViscosity = (1.0/pow(10.0,domainSettings->viscosityExponent)) * domainSettings->viscosityValue; } else { calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ]; } bbStart = domainSettings->bbStart; bbSize = domainSettings->bbSize; // always init { int timeIcu[1] = { FLUIDSIM_TIME }; float timeDef[1] = { 1. }; int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z }; float gravDef[3]; int viscIcu[1] = { FLUIDSIM_VISC }; float viscDef[1] = { 1. }; gravDef[0] = domainSettings->gravx; gravDef[1] = domainSettings->gravy; gravDef[2] = domainSettings->gravz; // 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 aniFrameTime 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]; } } else { for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; } } fluidsimInitChannel(scene, &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB if(channelDomainViscosity) { for(i=0; i<allchannelSize; i++) { channelDomainViscosity[i*2+0] = calcViscosity * channelDomainViscosity[i*2+0]; } } fluidsimInitChannel(scene, &channelDomainGravity, allchannelSize, timeAtFrame, gravIcu,gravDef, domainSettings->ipo, CHANNEL_VEC ); } // domain channel init // init obj movement channels channelObjCount=0; for(base=scene->base.first; base; base= base->next) { FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); obit = base->object; if( fluidmdtmp && (obit->type==OB_MESH) && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) { // cant use fluidsimInitChannel for obj channels right now, due // to the special DXXX channels, and the rotation specialities IpoCurve *icuex[3][3]; //IpoCurve *par_icuex[3][3]; #if 0 int icuIds[3][3] = { {OB_LOC_X, OB_LOC_Y, OB_LOC_Z}, {OB_ROT_X, OB_ROT_Y, OB_ROT_Z}, {OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z} }; int icudIds[3][3] = { {OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z}, {OB_DROT_X, OB_DROT_Y, OB_DROT_Z}, {OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z} }; #endif // relative ipos IpoCurve *icudex[3][3]; //IpoCurve *par_icudex[3][3]; int j,k; float vals[3] = {0.0,0.0,0.0}; int o = channelObjCount; int inivelIcu[3] = { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z }; float inivelDefs[3]; int activeIcu[1] = { FLUIDSIM_ACTIVE }; float activeDefs[1] = { 1 }; // default to on inivelDefs[0] = fluidmdtmp->fss->iniVelx; inivelDefs[1] = fluidmdtmp->fss->iniVely; inivelDefs[2] = fluidmdtmp->fss->iniVelz; // check & init loc,rot,size for(j=0; j<3; j++) { for(k=0; k<3; k++) { // XXX prevent invalid memory access until this works icuex[j][k]= NULL; icudex[j][k]= NULL; // XXX icuex[j][k] = find_ipocurve(obit->ipo, icuIds[j][k] ); // XXX icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] ); // XXX lines below were already disabled! //if(obit->parent) { //par_icuex[j][k] = find_ipocurve(obit->parent->ipo, icuIds[j][k] ); //par_icudex[j][k] = find_ipocurve(obit->parent->ipo, icudIds[j][k] ); //} } } for(j=0; j<3; j++) { channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel"); for(i=1; i<=allchannelSize; i++) { for(k=0; k<3; k++) { if(icuex[j][k]) { // IPO exists, use it ... // XXX calc_icu(icuex[j][k], aniFrlen*((float)i) ); vals[k] = icuex[j][k]->curval; if(obit->parent) { // add parent transform, multiply scaling, add trafo&rot //calc_icu(par_icuex[j][k], aniFrlen*((float)i) ); //if(j==2) { vals[k] *= par_icuex[j][k]->curval; } //else { vals[k] += par_icuex[j][k]->curval; } } } else { // use defaults from static values float setval=0.0; if(j==0) { setval = obit->loc[k]; if(obit->parent){ setval += obit->parent->loc[k]; } } else if(j==1) { setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI ); if(obit->parent){ setval = ( 180.0*(obit->rot[k]+obit->parent->rot[k]) )/( 10.0*M_PI ); } } else { setval = obit->size[k]; if(obit->parent){ setval *= obit->parent->size[k]; } } vals[k] = setval; } if(icudex[j][k]) { // XXX calc_icu(icudex[j][k], aniFrlen*((float)i) ); //vals[k] += icudex[j][k]->curval; // add transform, multiply scaling, add trafo&rot if(j==2) { vals[k] *= icudex[j][k]->curval; } else { vals[k] += icudex[j][k]->curval; } if(obit->parent) { // add parent transform, multiply scaling, add trafo&rot //calc_icu(par_icuex[j][k], aniFrlen*((float)i) ); //if(j==2) { vals[k] *= par_icudex[j][k]->curval; } //else { vals[k] += par_icudex[j][k]->curval; } } } } // k for(k=0; k<3; k++) { float set = vals[k]; if(j==1) { // rot is downscaled by 10 for ipo !? set = 360.0 - (10.0*set); } channelObjMove[o][j][(i-1)*4 + k] = set; } // k channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i]; } } { int attrFSIcu[1] = { FLUIDSIM_ATTR_FORCE_STR }; int attrFRIcu[1] = { FLUIDSIM_ATTR_FORCE_RADIUS }; int velFSIcu[1] = { FLUIDSIM_VEL_FORCE_STR }; int velFRIcu[1] = { FLUIDSIM_VEL_FORCE_RADIUS }; float attrFSDefs[1]; float attrFRDefs[1]; float velFSDefs[1]; float velFRDefs[1]; attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength; attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius; velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength; velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius; fluidsimInitChannel(scene, &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); fluidsimInitChannel(scene, &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); fluidsimInitChannel(scene, &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); fluidsimInitChannel(scene, &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); } fluidsimInitChannel(scene, &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC ); fluidsimInitChannel(scene, &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); channelObjCount++; } } // init trafo matrix Mat4CpyMat4(domainMat, fsDomain->obmat); if(!Mat4Invert(invDomMat, domainMat)) { snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); elbeemDebugOut(debugStrBuffer); BKE_report(reports, RPT_ERROR, "Invalid object matrix."); // FIXME add fatal msg FS_FREE_CHANNELS; return 0; } // -------------------------------------------------------------------------------------------- // start writing / exporting strcpy(targetFile, targetDir); strcat(targetFile, suffixConfig); if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file // make sure these directories exist as well if(outStringsChanged) { BLI_make_existing_file(targetFile); } if(!doExportOnly) { ListBase threads; // perform simulation with El'Beem api and threads elbeemSimulationSettings fsset; elbeemResetSettings(&fsset); fsset.version = 1; // setup global settings for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i]; for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i]; // simulate with 50^3 fsset.resolutionxyz = (int)domainSettings->resolutionxyz; fsset.previewresxyz = (int)domainSettings->previewresxyz; // 10cm water domain fsset.realsize = domainSettings->realsize; fsset.viscosity = calcViscosity; // earth gravity fsset.gravity[0] = domainSettings->gravx; fsset.gravity[1] = domainSettings->gravy; fsset.gravity[2] = domainSettings->gravz; // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz fsset.animStart = domainSettings->animStart; fsset.aniFrameTime = aniFrameTime; fsset.noOfFrames = noFrames; // is otherwise subtracted in parser strcpy(targetFile, targetDir); strcat(targetFile, 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; strcpy( fsset.outputPath, targetFile); // domain channels fsset.channelSizeFrameTime = fsset.channelSizeViscosity = fsset.channelSizeGravity = allchannelSize; fsset.channelFrameTime = channelDomainTime; fsset.channelViscosity = channelDomainViscosity; fsset.channelGravity = channelDomainGravity; fsset.runsimCallback = &runSimulationCallback; fsset.runsimUserData = &fsset; 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 trafo matrix // fprintf(stderr,"elbeemInit - mpTrafo:\n"); { int j; for(i=0; i<4; i++) { for(j=0; j<4; j++) { fsset.surfaceTrafo[i*4+j] = invDomMat[j][i]; // fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) ); } } } // init solver with settings elbeemInit(); elbeemAddDomain(&fsset); // init objects channelObjCount = 0; for(base=scene->base.first; base; base= base->next) { FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); obit = base->object; //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG if( fluidmdtmp && // if has to match 3 places! // CHECKMATCH (obit->type==OB_MESH) && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE)) { float *verts=NULL; int *tris=NULL; int numVerts=0, numTris=0; int o = channelObjCount; int deform = (fluidmdtmp->fss->domainNovecgen); // misused value // todo - use blenderInitElbeemMesh int modifierIndex = modifiers_indexInObject(obit, (ModifierData *)fluidmdtmp); elbeemMesh fsmesh; elbeemResetMesh( &fsmesh ); fsmesh.type = fluidmdtmp->fss->type; // get name of object for debugging solver fsmesh.name = obit->id.name; initElbeemMesh(scene, obit, &numVerts, &verts, &numTris, &tris, 0, modifierIndex); fsmesh.numVertices = numVerts; fsmesh.numTriangles = numTris; fsmesh.vertices = verts; fsmesh.triangles = tris; fsmesh.channelSizeTranslation = fsmesh.channelSizeRotation = fsmesh.channelSizeScale = fsmesh.channelSizeInitialVel = fsmesh.channelSizeActive = allchannelSize; fsmesh.channelTranslation = channelObjMove[o][0]; fsmesh.channelRotation = channelObjMove[o][1]; fsmesh.channelScale = channelObjMove[o][2]; fsmesh.channelActive = channelObjActive[o]; if( (fsmesh.type == OB_FLUIDSIM_FLUID) || (fsmesh.type == OB_FLUIDSIM_INFLOW)) { fsmesh.channelInitialVel = channelObjInivel[o]; fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0); } if( (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP; else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP; fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue; fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType; fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value if(fsmesh.type == OB_FLUIDSIM_CONTROL) { // control fluids will get exported as whole deform = 1; fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart; fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd; fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality; fsmesh.obstacleType = (fluidmdtmp->fss->flag & OB_FLUIDSIM_REVERSE); fsmesh.channelSizeAttractforceRadius = fsmesh.channelSizeVelocityforceStrength = fsmesh.channelSizeVelocityforceRadius = fsmesh.channelSizeAttractforceStrength = allchannelSize; fsmesh.channelAttractforceStrength = channelAttractforceStrength[o]; fsmesh.channelAttractforceRadius = channelAttractforceRadius[o]; fsmesh.channelVelocityforceStrength = channelVelocityforceStrength[o]; fsmesh.channelVelocityforceRadius = channelVelocityforceRadius[o]; } else { // set channels to 0 fsmesh.channelAttractforceStrength = fsmesh.channelAttractforceRadius = fsmesh.channelVelocityforceStrength = fsmesh.channelVelocityforceRadius = NULL; } // animated meshes if(deform) { fsmesh.channelSizeVertices = allchannelSize; fluidsimInitMeshChannel(C, &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame, modifierIndex); scene->r.cfra = startFrame; ED_update_for_newframe(C, 1); // remove channels fsmesh.channelTranslation = fsmesh.channelRotation = fsmesh.channelScale = NULL; } elbeemAddMesh(&fsmesh); if(verts) MEM_freeN(verts); if(tris) MEM_freeN(tris); if(fsmesh.channelVertices) MEM_freeN(fsmesh.channelVertices); channelObjCount++; } // valid mesh } // objects //domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again // set to neutral, -1 means user abort, -2 means init error globalBakeState = 0; globalBakeFrame = 0; BLI_init_threads(&threads, fluidsimSimulateThread, 1); BLI_insert_thread(&threads, targetFile); { int done = 0; float noFramesf = (float)noFrames; float percentdone = 0.0; int lastRedraw = -1; g_break= 0; G.afbreek= 0; /* blender_test_break uses this global */ start_progress_bar(); while(done==0) { char busy_mess[80]; waitcursor(1); // lukep we add progress bar as an interim mesure percentdone = globalBakeFrame / noFramesf; sprintf(busy_mess, "baking fluids %d / %d |||", globalBakeFrame, (int) noFramesf); progress_bar(percentdone, busy_mess ); // longer delay to prevent frequent redrawing PIL_sleep_ms(2000); BLI_lock_thread(LOCK_CUSTOM1); if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort BLI_unlock_thread(LOCK_CUSTOM1); if (!G.background) { g_break= blender_test_break(); if(g_break) { // abort... BLI_lock_thread(LOCK_CUSTOM1); if(domainSettings) domainSettings->lastgoodframe = startFrame+globalBakeFrame; done = -1; globalBakeFrame = 0; globalBakeState = -1; simAborted = 1; BLI_unlock_thread(LOCK_CUSTOM1); break; } } // redraw the 3D for showing progress once in a while... if(lastRedraw!=globalBakeFrame) { #if 0 ScrArea *sa; scene->r.cfra = startFrame+globalBakeFrame; lastRedraw = globalBakeFrame; ED_update_for_newframe(C, 1); sa= G.curscreen->areabase.first; while(sa) { if(sa->spacetype == SPACE_VIEW3D) { scrarea_do_windraw(sa); } sa= sa->next; } screen_swapbuffers(); #endif } // redraw } end_progress_bar(); } BLI_end_threads(&threads); } // El'Beem API init, thread creation // -------------------------------------------------------------------------------------------- else { // write config file to be run with command line simulator BKE_report(reports, RPT_WARNING, "Config file export not supported."); } // config file export done! // -------------------------------------------------------------------------------------------- FS_FREE_CHANNELS; // go back to "current" blender time waitcursor(0); if(globalBakeState >= 0) { if(domainSettings) domainSettings->lastgoodframe = startFrame+globalBakeFrame; } scene->r.cfra = origFrame; ED_update_for_newframe(C, 1); if(!simAborted) { char elbeemerr[256]; // check if some error occurred if(globalBakeState==-2) { elbeemGetErrorString(elbeemerr); BKE_reportf(reports, RPT_ERROR, "Failed to initialize [Msg: %s]", elbeemerr); return 0; } // init error } // elbeemFree(); return 1; }
static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { View2D *v2d = UI_view2d_fromcontext(C); Scene *scene = CTX_data_scene(C); Editing *ed = BKE_sequencer_editing_get(scene, false); const bool extend = RNA_boolean_get(op->ptr, "extend"); const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle"); const bool linked_time = RNA_boolean_get(op->ptr, "linked_time"); int left_right = RNA_enum_get(op->ptr, "left_right"); Sequence *seq, *neighbor, *act_orig; int hand, sel_side; TimeMarker *marker; if (ed == NULL) return OPERATOR_CANCELLED; marker = find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now seq = find_nearest_seq(scene, v2d, &hand, event->mval); // XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip if (seq && linked_time && (left_right == SEQ_SELECT_LR_MOUSE)) left_right = SEQ_SELECT_LR_NONE; if (marker) { int oldflag; /* select timeline marker */ if (extend) { oldflag = marker->flag; if (oldflag & SELECT) marker->flag &= ~SELECT; else marker->flag |= SELECT; } else { /* deselect_markers(0, 0); */ /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */ marker->flag |= SELECT; } } else if (left_right != SEQ_SELECT_LR_NONE) { /* use different logic for this */ float x; ED_sequencer_deselect_all(scene); switch (left_right) { case SEQ_SELECT_LR_MOUSE: x = UI_view2d_region_to_view_x(v2d, event->mval[0]); break; case SEQ_SELECT_LR_LEFT: x = CFRA - 1.0f; break; case SEQ_SELECT_LR_RIGHT: default: x = CFRA; break; } SEQP_BEGIN (ed, seq) { if (((x < CFRA) && (seq->enddisp <= CFRA)) || ((x >= CFRA) && (seq->startdisp >= CFRA))) { seq->flag |= SELECT; recurs_sel_seq(seq); } } SEQ_END { SpaceSeq *sseq = CTX_wm_space_seq(C); if (sseq && sseq->flag & SEQ_MARKER_TRANS) { TimeMarker *tmarker; for (tmarker = scene->markers.first; tmarker; tmarker = tmarker->next) { if (((x < CFRA) && (tmarker->frame <= CFRA)) || ((x >= CFRA) && (tmarker->frame >= CFRA))) { tmarker->flag |= SELECT; } else { tmarker->flag &= ~SELECT; } } } } }
static int bake_exec(bContext *C, wmOperator *op) { Render *re; int result = OPERATOR_CANCELLED; BakeAPIRender bkr = {NULL}; Scene *scene = CTX_data_scene(C); G.is_break = false; G.is_rendering = true; bake_set_props(op, scene); bake_init_api_data(op, C, &bkr); re = bkr.render; /* setup new render */ RE_test_break_cb(re, NULL, bake_break); if (!bake_pass_filter_check(bkr.pass_type, bkr.pass_filter, bkr.reports)) { goto finally; } if (!bake_objects_check(bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) { goto finally; } if (bkr.is_clear) { const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) && (bkr.normal_space == R_BAKE_SPACE_TANGENT)); bake_images_clear(bkr.main, is_tangent); } RE_SetReports(re, bkr.reports); if (bkr.is_selected_to_active) { result = bake( bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode, bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage, bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa, bkr.uv_layer); } else { CollectionPointerLink *link; const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects); for (link = bkr.selected_objects.first; link; link = link->next) { Object *ob_iter = link->ptr.data; result = bake( bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports, bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode, is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage, bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa, bkr.uv_layer); } } RE_SetReports(re, NULL); finally: G.is_rendering = false; BLI_freelistN(&bkr.selected_objects); return result; }
static int request_qtcodec_settings(bContext *C, wmOperator *op) { OSErr err = noErr; Scene *scene = CTX_data_scene(C); RenderData *rd = &scene->r; // erase any existing codecsetting if(qtdata) { if(qtdata->theComponent) CloseComponent(qtdata->theComponent); free_qtcomponentdata(); } // allocate new qtdata = MEM_callocN(sizeof(QuicktimeComponentData), "QuicktimeComponentData"); qtdata->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); // get previous selected codecsetting, from qtatom or detailed settings if(rd->qtcodecdata && rd->qtcodecdata->cdParms) { QT_GetCodecSettingsFromScene(rd, op->reports); } else { SCGetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); SCGetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); qtdata->gSpatialSettings.codecType = rd->qtcodecsettings.codecType; qtdata->gSpatialSettings.codec = (CodecComponent)rd->qtcodecsettings.codec; qtdata->gSpatialSettings.spatialQuality = (rd->qtcodecsettings.codecSpatialQuality * codecLosslessQuality) /100; qtdata->gTemporalSettings.temporalQuality = (rd->qtcodecsettings.codecTemporalQuality * codecLosslessQuality) /100; qtdata->gTemporalSettings.keyFrameRate = rd->qtcodecsettings.keyFrameRate; qtdata->gTemporalSettings.frameRate = ((float)(rd->frs_sec << 16) / rd->frs_sec_base); qtdata->aDataRateSetting.dataRate = rd->qtcodecsettings.bitRate; qtdata->gSpatialSettings.depth = rd->qtcodecsettings.colorDepth; qtdata->aDataRateSetting.minSpatialQuality = (rd->qtcodecsettings.minSpatialQuality * codecLosslessQuality) / 100; qtdata->aDataRateSetting.minTemporalQuality = (rd->qtcodecsettings.minTemporalQuality * codecLosslessQuality) / 100; qtdata->aDataRateSetting.frameDuration = rd->frs_sec; err = SCSetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); CheckError(err, "SCSetInfo1 error", op->reports); err = SCSetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); CheckError(err, "SCSetInfo2 error", op->reports); err = SCSetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); CheckError(err, "SCSetInfo3 error", op->reports); } // put up the dialog box - it needs to be called from the main thread err = SCRequestSequenceSettings(qtdata->theComponent); if (err == scUserCancelled) { return OPERATOR_FINISHED; } // update runtime codecsettings for use with the codec dialog SCGetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); SCGetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); //Fill the render QuicktimeCodecSettings struct rd->qtcodecsettings.codecTemporalQuality = (qtdata->gTemporalSettings.temporalQuality * 100) / codecLosslessQuality; //Do not override scene frame rate (qtdata->gTemporalSettings.framerate) rd->qtcodecsettings.keyFrameRate = qtdata->gTemporalSettings.keyFrameRate; rd->qtcodecsettings.codecType = qtdata->gSpatialSettings.codecType; rd->qtcodecsettings.codec = (int)qtdata->gSpatialSettings.codec; rd->qtcodecsettings.colorDepth = qtdata->gSpatialSettings.depth; rd->qtcodecsettings.codecSpatialQuality = (qtdata->gSpatialSettings.spatialQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.bitRate = qtdata->aDataRateSetting.dataRate; rd->qtcodecsettings.minSpatialQuality = (qtdata->aDataRateSetting.minSpatialQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.minTemporalQuality = (qtdata->aDataRateSetting.minTemporalQuality * 100) / codecLosslessQuality; //Frame duration is already known (qtdata->aDataRateSetting.frameDuration) QT_SaveCodecSettingsToScene(rd, op->reports); // framerate jugglin' if(qtdata->gTemporalSettings.frameRate == 1571553) { // 23.98 fps qtdata->kVideoTimeScale = 24000; qtdata->duration = 1001; rd->frs_sec = 24; rd->frs_sec_base = 1.001; } else if (qtdata->gTemporalSettings.frameRate == 1964113) { // 29.97 fps qtdata->kVideoTimeScale = 30000; qtdata->duration = 1001; rd->frs_sec = 30; rd->frs_sec_base = 1.001; } else if (qtdata->gTemporalSettings.frameRate == 3928227) { // 59.94 fps qtdata->kVideoTimeScale = 60000; qtdata->duration = 1001; rd->frs_sec = 60; rd->frs_sec_base = 1.001; } else { double fps = qtdata->gTemporalSettings.frameRate; qtdata->kVideoTimeScale = 60000; qtdata->duration = qtdata->kVideoTimeScale / (qtdata->gTemporalSettings.frameRate / 65536); if ((qtdata->gTemporalSettings.frameRate & 0xffff) == 0) { rd->frs_sec = fps / 65536; rd->frs_sec_base = 1.0; } else { /* we do our very best... */ rd->frs_sec = fps / 65536; rd->frs_sec_base = 1.0; } } return OPERATOR_FINISHED; }
static int ED_rigidbody_world_add_poll(bContext *C) { Scene *scene = CTX_data_scene(C); return (scene && scene->rigidbody_world == NULL); }