Exemple #1
0
/* 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);
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
/* 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;
}
Exemple #7
0
/* 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;
}
Exemple #8
0
/* 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;
}
Exemple #9
0
/* 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
}
Exemple #13
0
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;
	}
}
Exemple #14
0
/* 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;
	}
}
Exemple #15
0
static int prefetch_get_start_frame(const bContext *C)
{
	Scene *scene = CTX_data_scene(C);

	return SFRA;
}
Exemple #16
0
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 {
Exemple #17
0
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;
}
Exemple #18
0
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;
}
Exemple #19
0
/* 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);
}
Exemple #20
0
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, &params);

	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);
}
Exemple #21
0
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;
	}
}
Exemple #25
0
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;
}
Exemple #26
0
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;
}
Exemple #27
0
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;
					}
				}
			}
		}
	}
Exemple #28
0
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;
}
Exemple #29
0
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);
}