Example #1
0
static void object_add_generic_invoke_options(bContext *C, wmOperator *op)
{
	if(RNA_struct_find_property(op->ptr, "enter_editmode")) /* optional */
		if (!RNA_property_is_set(op->ptr, "enter_editmode"))
			RNA_boolean_set(op->ptr, "enter_editmode", U.flag & USER_ADD_EDITMODE);
	
	if(!RNA_property_is_set(op->ptr, "location")) {
		float loc[3];
		
		ED_object_location_from_view(C, loc);
		RNA_float_set_array(op->ptr, "location", loc);
	}
	 
	if(!RNA_property_is_set(op->ptr, "layers")) {
		View3D *v3d = CTX_wm_view3d(C);
		Scene *scene = CTX_data_scene(C);
		int a, values[20], layer;
		
		if(v3d) {
			layer = (v3d->scenelock && !v3d->localvd)? scene->layact: v3d->layact;

			for(a=0; a<20; a++)
				values[a]= (layer & (1<<a));
		}
		else {
			layer = scene->layact;

			for(a=0; a<20; a++)
				values[a]= (layer & (1<<a));
		}
		
		RNA_boolean_set_array(op->ptr, "layers", values);
	}
}
Example #2
0
int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float *loc, float *rot, int *enter_editmode, unsigned int *layer)
{
	View3D *v3d = CTX_wm_view3d(C);
	int a, layer_values[20];
	int view_align;
	
	*enter_editmode = FALSE;
	if(RNA_struct_find_property(op->ptr, "enter_editmode") && RNA_boolean_get(op->ptr, "enter_editmode")) {
		*enter_editmode = TRUE;
	}

	if(RNA_property_is_set(op->ptr, "layers")) {
		RNA_boolean_get_array(op->ptr, "layers", layer_values);
		*layer= 0;
		for(a=0; a<20; a++) {
			if(layer_values[a])
				*layer |= (1 << a);
			else
				*layer &= ~(1 << a);
		}
	}
	else {
		/* not set, use the scenes layers */
		Scene *scene = CTX_data_scene(C);
		*layer = scene->layact;
	}

	/* in local view we additionally add local view layers,
	   not part of operator properties */
	if(v3d && v3d->localvd)
		*layer |= v3d->lay;

	if(RNA_property_is_set(op->ptr, "rotation"))
		view_align = FALSE;
	else if (RNA_property_is_set(op->ptr, "view_align"))
		view_align = RNA_boolean_get(op->ptr, "view_align");
	else {
		view_align = U.flag & USER_ADD_VIEWALIGNED;
		RNA_boolean_set(op->ptr, "view_align", view_align);
	}
	
	if (view_align)
		ED_object_rotation_from_view(C, rot);
	else
		RNA_float_get_array(op->ptr, "rotation", rot);
	

	RNA_float_get_array(op->ptr, "location", loc);

	if(*layer == 0) {
		BKE_report(op->reports, RPT_ERROR, "Property 'layer' has no values set");
		return 0;
	}

	return 1;
}
Example #3
0
int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
	const bool from_memory = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
	char filepath_buf[FILE_MAX];
	const char *filepath = NULL;

	if (!from_memory) {
		PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");

		/* This can be used when loading of a start-up file should only change
		 * the scene content but keep the blender UI as it is. */
		wm_open_init_load_ui(op, true);
		BKE_BIT_TEST_SET(G.fileflags, !RNA_boolean_get(op->ptr, "load_ui"), G_FILE_NO_UI);

		if (RNA_property_is_set(op->ptr, prop)) {
			RNA_property_string_get(op->ptr, prop, filepath_buf);
			filepath = filepath_buf;
			if (BLI_access(filepath, R_OK)) {
				BKE_reportf(op->reports, RPT_ERROR, "Can't read alternative start-up file: '%s'", filepath);
				return OPERATOR_CANCELLED;
			}
		}
	}
	else {
		/* always load UI for factory settings (prefs will re-init) */
		G.fileflags &= ~G_FILE_NO_UI;
	}

	return wm_homefile_read(C, op->reports, from_memory, filepath) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
Example #4
0
static int poselib_remove_exec(bContext *C, wmOperator *op)
{
	Object *ob = get_poselib_object(C);
	bAction *act = (ob) ? ob->poselib : NULL;
	TimeMarker *marker;
	int marker_index;
	FCurve *fcu;
	PropertyRNA *prop;

	/* check if valid poselib */
	if (act == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
		return OPERATOR_CANCELLED;
	}

	prop = RNA_struct_find_property(op->ptr, "pose");
	if (RNA_property_is_set(op->ptr, prop)) {
		marker_index = RNA_property_enum_get(op->ptr, prop);
	}
	else {
		marker_index = act->active_marker - 1;
	}

	/* get index (and pointer) of pose to remove */
	marker = BLI_findlink(&act->markers, marker_index);
	if (marker == NULL) {
		BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
		return OPERATOR_CANCELLED;
	}
	
	/* remove relevant keyframes */
	for (fcu = act->curves.first; fcu; fcu = fcu->next) {
		BezTriple *bezt;
		unsigned int i;
		
		if (fcu->bezt) {
			for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
				/* check if remove */
				if (IS_EQF(bezt->vec[1][0], (float)marker->frame)) {
					delete_fcurve_key(fcu, i, 1);
					break;
				}
			}
		}
	}
	
	/* remove poselib from list */
	BLI_freelinkN(&act->markers, marker);
	
	/* fix active pose number */
	act->active_marker = 0;
	
	/* send notifiers for this - using keyframe editing notifiers, since action 
	 * may be being shown in anim editors as active action 
	 */
	WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
	
	/* done */
	return OPERATOR_FINISHED;
}
Example #5
0
static wmKeyMapItem *wm_keymap_item_find(
        const bContext *C, const char *opname, int opcontext,
        IDProperty *properties, const short hotkey, const bool strict, wmKeyMap **keymap_r)
{
	wmKeyMapItem *found = wm_keymap_item_find_props(C, opname, opcontext, properties, strict, hotkey, keymap_r);

	if (!found && properties) {
		wmOperatorType *ot = WM_operatortype_find(opname, TRUE);
		if (ot) {
			/* make a copy of the properties and set any unset props
			 * to their default values, so the ID property compare function succeeds */
			PointerRNA opptr;
			IDProperty *properties_default = IDP_CopyProperty(properties);

			RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);

			if (WM_operator_properties_default(&opptr, true) ||
			    (!strict && ot->prop && RNA_property_is_set(&opptr, ot->prop)))
			{
				/* for operator that has enum menu, unset it so it always matches */
				if (!strict && ot->prop) {
					RNA_property_unset(&opptr, ot->prop);
				}

				found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, false, hotkey, keymap_r);
			}

			IDP_FreeProperty(properties_default);
			MEM_freeN(properties_default);
		}
	}

	return found;
}
Example #6
0
static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
{
	Object *ob = ED_object_active_context(C);
	MultiresModifierData *mmd;
	Mesh *me= ob->data;
	char path[FILE_MAX];

	if (!edit_modifier_invoke_properties(C, op))
		return OPERATOR_CANCELLED;
	
	mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
	
	if (!mmd)
		return OPERATOR_CANCELLED;
	
	if(CustomData_external_test(&me->fdata, CD_MDISPS))
		return OPERATOR_CANCELLED;

	if(RNA_property_is_set(op->ptr, "filepath"))
		return multires_external_save_exec(C, op);
	
	op->customdata= me;

	BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name+2);
	RNA_string_set(op->ptr, "filepath", path);
	
	WM_event_add_fileselect(C, op);

	return OPERATOR_RUNNING_MODAL;
}
Example #7
0
/**
 * Special hack for MESH_OT_loopcut_slide so we get back to the selection mode
 */
static void transformops_loopsel_hack(bContext *C, wmOperator *op)
{
	if (op->type->idname == OP_EDGE_SLIDE) {
		if (op->opm && op->opm->opm && op->opm->opm->prev) {
			wmOperator *op_prev = op->opm->opm->prev;
			Scene *scene = CTX_data_scene(C);
			int mesh_select_mode[3];
			PropertyRNA *prop = RNA_struct_find_property(op_prev->ptr, "mesh_select_mode_init");

			if (prop && RNA_property_is_set(op_prev->ptr, prop)) {
				ToolSettings *ts = scene->toolsettings;
				short selectmode_orig;

				RNA_property_boolean_get_array(op_prev->ptr, prop, mesh_select_mode);
				selectmode_orig = ((mesh_select_mode[0] ? SCE_SELECT_VERTEX : 0) |
				                   (mesh_select_mode[1] ? SCE_SELECT_EDGE   : 0) |
				                   (mesh_select_mode[2] ? SCE_SELECT_FACE   : 0));

				/* still switch if we were originally in face select mode */
				if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) {
					BMEditMesh *em = BKE_editmesh_from_object(scene->obedit);
					em->selectmode = ts->selectmode = selectmode_orig;
					EDBM_selectmode_set(em);
				}
			}
		}
	}
}
Example #8
0
static bool wm_stereo3d_set_properties(bContext *UNUSED(C), wmOperator *op)
{
	Stereo3dData *s3dd = op->customdata;
	Stereo3dFormat *s3d = &s3dd->stereo3d_format;
	PropertyRNA *prop;
	bool is_set = false;

	prop = RNA_struct_find_property(op->ptr, "display_mode");
	if (RNA_property_is_set(op->ptr, prop)) {
		s3d->display_mode = RNA_property_enum_get(op->ptr, prop);
		is_set = true;
	}

	prop = RNA_struct_find_property(op->ptr, "anaglyph_type");
	if (RNA_property_is_set(op->ptr, prop)) {
		s3d->anaglyph_type = RNA_property_enum_get(op->ptr, prop);
		is_set = true;
	}

	prop = RNA_struct_find_property(op->ptr, "interlace_type");
	if (RNA_property_is_set(op->ptr, prop)) {
		s3d->interlace_type = RNA_property_enum_get(op->ptr, prop);
		is_set = true;
	}

	prop = RNA_struct_find_property(op->ptr, "use_interlace_swap");
	if (RNA_property_is_set(op->ptr, prop)) {
		if (RNA_property_boolean_get(op->ptr, prop))
			s3d->flag |= S3D_INTERLACE_SWAP;
		else
			s3d->flag &= ~S3D_INTERLACE_SWAP;
		is_set = true;
	}

	prop = RNA_struct_find_property(op->ptr, "use_sidebyside_crosseyed");
	if (RNA_property_is_set(op->ptr, prop)) {
		if (RNA_property_boolean_get(op->ptr, prop))
			s3d->flag |= S3D_SIDEBYSIDE_CROSSEYED;
		else
			s3d->flag &= ~S3D_SIDEBYSIDE_CROSSEYED;
		is_set = true;
	}

	return is_set;
}
Example #9
0
static int edit_sensor_invoke_properties(bContext *C, wmOperator *op)
{
	PointerRNA ptr= CTX_data_pointer_get_type(C, "sensor", &RNA_Sensor);
	
	if (RNA_property_is_set(op->ptr, "sensor") && RNA_property_is_set(op->ptr, "object") )
		return 1;
	
	if (ptr.data) {
		bSensor *sens = ptr.data;
		Object *ob = ptr.id.data;
		
		RNA_string_set(op->ptr, "sensor", sens->name);
		RNA_string_set(op->ptr, "object", ob->id.name+2);
		return 1;
	}
	
	return 0;
}
Example #10
0
/* invoke callback which presents a list of bone-groups for the user to choose from */
static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
	Object *ob = ED_pose_object_from_context(C);
	bPose *pose;
	PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");

	uiPopupMenu *pup;
	uiLayout *layout;
	bActionGroup *grp;
	int i;

	/* only continue if there's an object, and a pose there too */
	if (ELEM(NULL, ob, ob->pose))
		return OPERATOR_CANCELLED;
	pose = ob->pose;

	/* If group index is set, try to use it! */
	if (RNA_property_is_set(op->ptr, prop)) {
		const int num_groups = BLI_listbase_count(&pose->agroups);
		const int group = RNA_property_int_get(op->ptr, prop);

		/* just use the active group index, and call the exec callback for the calling operator */
		if (group > 0 && group <= num_groups) {
			return op->type->exec(C, op);
		}
	}

	/* if there's no active group (or active is invalid), create a new menu to find it */
	if (pose->active_group <= 0) {
		/* create a new menu, and start populating it with group names */
		pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
		layout = UI_popup_menu_layout(pup);

		/* special entry - allow to create new group, then use that
		 *	(not to be used for removing though)
		 */
		if (strstr(op->idname, "assign")) {
			uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0);
			uiItemS(layout);
		}

		/* add entries for each group */
		for (grp = pose->agroups.first, i = 1; grp; grp = grp->next, i++)
			uiItemIntO(layout, grp->name, ICON_NONE, op->idname, "type", i);

		/* finish building the menu, and process it (should result in calling self again) */
		UI_popup_menu_end(C, pup);

		return OPERATOR_INTERFACE;
	}
	else {
		/* just use the active group index, and call the exec callback for the calling operator */
		RNA_int_set(op->ptr, "type", pose->active_group);
		return op->type->exec(C, op);
	}
}
Example #11
0
static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
	PointerRNA ptr;
	PropertyRNA *prop;
	FileBrowseOp *fbo;
	char *str;

	uiFileBrowseContextProperty(C, &ptr, &prop);

	if(!prop)
		return OPERATOR_CANCELLED;

	str= RNA_property_string_get_alloc(&ptr, prop, NULL, 0);

	/* useful yet irritating feature, Shift+Click to open the file
	 * Alt+Click to browse a folder in the OS's browser */
	if(event->shift || event->alt) {
		PointerRNA props_ptr;

		if(event->alt) {
			char *lslash= BLI_last_slash(str);
			if(lslash)
				*lslash= '\0';
		}


		WM_operator_properties_create(&props_ptr, "WM_OT_path_open");
		RNA_string_set(&props_ptr, "filepath", str);
		WM_operator_name_call(C, "WM_OT_path_open", WM_OP_EXEC_DEFAULT, &props_ptr);
		WM_operator_properties_free(&props_ptr);

		MEM_freeN(str);
		return OPERATOR_CANCELLED;
	}
	else {
		const char *path_prop= RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath";
		fbo= MEM_callocN(sizeof(FileBrowseOp), "FileBrowseOp");
		fbo->ptr= ptr;
		fbo->prop= prop;
		op->customdata= fbo;

		RNA_string_set(op->ptr, path_prop, str);
		MEM_freeN(str);

		if(RNA_struct_find_property(op->ptr, "relative_path")) {
			if(!RNA_property_is_set(op->ptr, "relative_path")) {
				/* annoying exception!, if were dealign with the user prefs, default relative to be off */
				RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS && (ptr.data != &U));
			}
		}
		WM_event_add_fileselect(C, op);

		return OPERATOR_RUNNING_MODAL;
	}
}
Example #12
0
void wm_open_init_load_ui(wmOperator *op, bool use_prefs)
{
	PropertyRNA *prop = RNA_struct_find_property(op->ptr, "load_ui");
	if (!RNA_property_is_set(op->ptr, prop)) {
		bool value = use_prefs ?
		             ((U.flag & USER_FILENOUI) == 0) :
		             ((G.fileflags & G_FILE_NO_UI) == 0);

		RNA_property_boolean_set(op->ptr, prop, value);
	}
}
Example #13
0
void wm_open_init_use_scripts(wmOperator *op, bool use_prefs)
{
	PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_scripts");
	if (!RNA_property_is_set(op->ptr, prop)) {
		/* use G_SCRIPT_AUTOEXEC rather than the userpref because this means if
		 * the flag has been disabled from the command line, then opening
		 * from the menu wont enable this setting. */
		bool value = use_prefs ?
		             ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) :
		             ((G.f & G_SCRIPT_AUTOEXEC) != 0);

		RNA_property_boolean_set(op->ptr, prop, value);
	}
}
Example #14
0
static int file_browse_exec(bContext *C, wmOperator *op)
{
	FileBrowseOp *fbo= op->customdata;
	ID *id;
	char *base, *str, path[FILE_MAX];
	const char *path_prop= RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath";
	
	if (RNA_property_is_set(op->ptr, path_prop)==0 || fbo==NULL)
		return OPERATOR_CANCELLED;
	
	str= RNA_string_get_alloc(op->ptr, path_prop, NULL, 0);

	/* add slash for directories, important for some properties */
	if(RNA_property_subtype(fbo->prop) == PROP_DIRPATH) {
		char name[FILE_MAX];
		
		id = fbo->ptr.id.data;
		base = (id && id->lib)? id->lib->filepath: G.main->name;

		BLI_strncpy(path, str, FILE_MAX);
		BLI_path_abs(path, base);
		
		if(BLI_is_dir(path)) {
			str = MEM_reallocN(str, strlen(str)+2);
			BLI_add_slash(str);
		}
		else
			BLI_splitdirstring(str, name);
	}

	RNA_property_string_set(&fbo->ptr, fbo->prop, str);
	RNA_property_update(C, &fbo->ptr, fbo->prop);
	MEM_freeN(str);


	/* special, annoying exception, filesel on redo panel [#26618] */
	{
		wmOperator *redo_op= WM_operator_last_redo(C);
		if(redo_op) {
			if(fbo->ptr.data == redo_op->ptr->data) {
				ED_undo_operator_repeat(C, redo_op);
			}
		}
	}

	MEM_freeN(op->customdata);

	return OPERATOR_FINISHED;
}
Example #15
0
/* Show menu or create drivers */
static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
	PropertyRNA *prop;
	
	if ((prop = RNA_struct_find_property(op->ptr, "mapping_type")) && RNA_property_is_set(op->ptr, prop)) {
		/* Mapping Type is Set - Directly go into creating drivers */
		return add_driver_button_exec(C, op);
	}
	else {
		/* Show menu */
		// TODO: This should get filtered by the enum filter
		/* important to execute in the region we're currently in */
		return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
	}
}
Example #16
0
static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
	PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
	ModifierData *md;
	
	if (RNA_property_is_set(op->ptr, "modifier"))
		return 1;
	
	if (ptr.data) {
		md = ptr.data;
		RNA_string_set(op->ptr, "modifier", md->name);
		return 1;
	}
	
	return 0;
}
Example #17
0
static int transform_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
	if (!transformops_data(C, op, event))
	{
		G.moving = 0;
		return OPERATOR_CANCELLED;
	}

	if(RNA_property_is_set(op->ptr, "value")) {
		return transform_exec(C, op);
	}
	else {
		/* add temp handler */
		WM_event_add_modal_handler(C, op);

		op->flag |= OP_GRAB_POINTER; // XXX maybe we want this with the manipulator only?
		return OPERATOR_RUNNING_MODAL;
	}
}
Example #18
0
static int unset_property_button_exec(bContext *C, wmOperator *UNUSED(op))
{
  PointerRNA ptr;
  PropertyRNA *prop;
  int index;

  /* try to unset the nominated property */
  UI_context_active_but_prop_get(C, &ptr, &prop, &index);

  /* if there is a valid property that is editable... */
  if (ptr.data && prop && RNA_property_editable(&ptr, prop) &&
      /* RNA_property_is_idprop(prop) && */
      RNA_property_is_set(&ptr, prop)) {
    RNA_property_unset(&ptr, prop);
    return operator_button_property_finish(C, &ptr, prop);
  }

  return OPERATOR_CANCELLED;
}
Example #19
0
int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
	const bool from_memory = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
	char filepath_buf[FILE_MAX];
	const char *filepath = NULL;

	if (!from_memory) {
		PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
		if (RNA_property_is_set(op->ptr, prop)) {
			RNA_property_string_get(op->ptr, prop, filepath_buf);
			filepath = filepath_buf;
			if (BLI_access(filepath, R_OK)) {
				BKE_reportf(op->reports, RPT_ERROR, "Can't read alternative start-up file: '%s'", filepath);
				return OPERATOR_CANCELLED;
			}
		}
	}

	return wm_homefile_read(C, op->reports, from_memory, filepath) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
	PropertyRNA *prop_other;

	const char *prop_id = RNA_property_identifier(prop);
	const int data_type = RNA_enum_get(ptr, "data_type");
	bool use_auto_transform = false;
	bool use_max_distance = false;
	bool use_modifier = false;

	if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
		use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
	}
	if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
		use_max_distance = RNA_property_boolean_get(ptr, prop_other);
	}
	if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
		use_modifier = RNA_property_is_set(ptr, prop_other);
	}

	if (STREQ(prop_id, "modifier")) {
		return use_modifier;
	}

	if (use_modifier) {
		/* Hide everything but 'modifier' property, if set. */
		return false;
	}

	if (STREQ(prop_id, "use_object_transform") && use_auto_transform) {
		return false;
	}
	if (STREQ(prop_id, "max_distance") && !use_max_distance) {
		return false;
	}
	if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) {
		return false;
	}

	if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) {
		return false;
	}
	if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) {
		return false;
	}
	if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) {
		return false;
	}
	if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) {
		return false;
	}

	if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) &&
	    !DT_DATATYPE_IS_MULTILAYERS(data_type))
	{
		return false;
	}

	/* Else, show it! */
	return true;
}
static int gp_convert_layer_exec(bContext *C, wmOperator *op)
{
	PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data");
	bGPdata *gpd = ED_gpencil_data_get_active(C);
	bGPDlayer *gpl = gpencil_layer_getactive(gpd);
	Scene *scene = CTX_data_scene(C);
	const int mode = RNA_enum_get(op->ptr, "type");
	const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights");
	const float rad_fac = RNA_float_get(op->ptr, "radius_multiplier");
	const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes");
	bool valid_timing;
	tGpTimingData gtd;
	
	/* check if there's data to work with */
	if (gpd == NULL) {
		BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on");
		return OPERATOR_CANCELLED;
	}
	
	if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) {
		BKE_report(op->reports, RPT_WARNING,
		           "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!");
	}
	valid_timing = RNA_property_boolean_get(op->ptr, prop);
	
	gtd.mode = RNA_enum_get(op->ptr, "timing_mode");
	/* Check for illegal timing mode! */
	if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) {
		gtd.mode = GP_STROKECONVERT_TIMING_LINEAR;
		RNA_enum_set(op->ptr, "timing_mode", gtd.mode);
	}
	if (!link_strokes) {
		gtd.mode = GP_STROKECONVERT_TIMING_NONE;
	}
	
	/* grab all relevant settings */
	gtd.frame_range = RNA_int_get(op->ptr, "frame_range");
	gtd.start_frame = RNA_int_get(op->ptr, "start_frame");
	gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : false;
	gtd.end_frame = RNA_int_get(op->ptr, "end_frame");
	gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration");
	gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness");
	gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration);
	gtd.seed = RNA_int_get(op->ptr, "seed");
	gtd.num_points = gtd.cur_point = 0;
	gtd.dists = gtd.times = NULL;
	gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f;
	gtd.inittime = 0.0;
	gtd.offset_time = 0.0f;
	
	/* perform conversion */
	gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, &gtd);
	
	/* free temp memory */
	if (gtd.dists) {
		MEM_freeN(gtd.dists);
		gtd.dists = NULL;
	}
	if (gtd.times) {
		MEM_freeN(gtd.times);
		gtd.times = NULL;
	}
	
	/* notifiers */
	WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
	WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
	
	/* done */
	return OPERATOR_FINISHED;
}
Example #22
0
short ED_fileselect_set_params(SpaceFile *sfile)
{
	char name[FILE_MAX], dir[FILE_MAX], file[FILE_MAX];
	FileSelectParams *params;
	wmOperator *op = sfile->op;

	/* create new parameters if necessary */
	if (!sfile->params) {
		sfile->params= MEM_callocN(sizeof(FileSelectParams), "fileselparams");
		/* set path to most recently opened .blend */
		BLI_strncpy(sfile->params->dir, G.sce, sizeof(sfile->params->dir));
		BLI_split_dirfile(G.sce, dir, file);
		BLI_strncpy(sfile->params->file, file, sizeof(sfile->params->file));
		BLI_make_file_string(G.sce, sfile->params->dir, dir, ""); /* XXX needed ? - also solve G.sce */
	}

	params = sfile->params;

	/* set the parameters from the operator, if it exists */
	if (op) {
		BLI_strncpy(params->title, op->type->name, sizeof(params->title));

		if(RNA_struct_find_property(op->ptr, "filename"))
			params->type = RNA_int_get(op->ptr, "filemode");
		else
			params->type = FILE_SPECIAL;

		if (RNA_property_is_set(op->ptr, "path")) {
			RNA_string_get(op->ptr, "path", name);
			if (params->type == FILE_LOADLIB) {
				BLI_strncpy(params->dir, name, sizeof(params->dir));
				BLI_cleanup_dir(G.sce, params->dir);	
			} else { 
				/* if operator has path set, use it, otherwise keep the last */
				BLI_convertstringcode(name, G.sce);
				BLI_split_dirfile(name, dir, file);
				BLI_strncpy(params->file, file, sizeof(params->file));
				BLI_make_file_string(G.sce, params->dir, dir, ""); /* XXX needed ? - also solve G.sce */
			}
		}
		params->filter = 0;
		if(RNA_struct_find_property(op->ptr, "filter_blender"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_blender") ? BLENDERFILE : 0;
		if(RNA_struct_find_property(op->ptr, "filter_image"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_image") ? IMAGEFILE : 0;
		if(RNA_struct_find_property(op->ptr, "filter_movie"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_movie") ? MOVIEFILE : 0;
		if(RNA_struct_find_property(op->ptr, "filter_text"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_text") ? TEXTFILE : 0;
		if(RNA_struct_find_property(op->ptr, "filter_python"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_python") ? PYSCRIPTFILE : 0;
		if(RNA_struct_find_property(op->ptr, "filter_font"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_font") ? FTFONTFILE : 0;
		if(RNA_struct_find_property(op->ptr, "filter_sound"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_sound") ? SOUNDFILE : 0;
		if(RNA_struct_find_property(op->ptr, "filter_text"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_text") ? TEXTFILE : 0;
		if(RNA_struct_find_property(op->ptr, "filter_folder"))
			params->filter |= RNA_boolean_get(op->ptr, "filter_folder") ? FOLDERFILE : 0;
		if (params->filter != 0)
			params->flag |= FILE_FILTER;

		params->flag |= FILE_HIDE_DOT;

		if (params->type == FILE_LOADLIB) {
			params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0;
			params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0;
			params->flag |= RNA_boolean_get(op->ptr, "active_layer") ? FILE_ACTIVELAY : 0;
		}

		if(params->filter & (IMAGEFILE|MOVIEFILE))
			params->display= FILE_IMGDISPLAY;
		else
			params->display= FILE_SHORTDISPLAY;
		
	} else {
		/* default values, if no operator */
		params->type = FILE_UNIX;
		params->flag |= FILE_HIDE_DOT;
		params->display = FILE_SHORTDISPLAY;
		params->filter = 0;
		params->sort = FILE_SORT_ALPHA;
	}

	return 1;
}
Example #23
0
static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	PointerRNA ptr;
	PropertyRNA *prop;
	bool is_undo;
	FileBrowseOp *fbo;
	char *str;

	if (CTX_wm_space_file(C)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot activate a file selector, one already open");
		return OPERATOR_CANCELLED;
	}

	UI_context_active_but_prop_get_filebrowser(C, &ptr, &prop, &is_undo);

	if (!prop)
		return OPERATOR_CANCELLED;

	str = RNA_property_string_get_alloc(&ptr, prop, NULL, 0, NULL);

	/* useful yet irritating feature, Shift+Click to open the file
	 * Alt+Click to browse a folder in the OS's browser */
	if (event->shift || event->alt) {
		wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
		PointerRNA props_ptr;

		if (event->alt) {
			char *lslash = (char *)BLI_last_slash(str);
			if (lslash)
				*lslash = '\0';
		}


		WM_operator_properties_create_ptr(&props_ptr, ot);
		RNA_string_set(&props_ptr, "filepath", str);
		WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr);
		WM_operator_properties_free(&props_ptr);

		MEM_freeN(str);
		return OPERATOR_CANCELLED;
	}
	else {
		PropertyRNA *prop_relpath;
		const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath";
		fbo = MEM_callocN(sizeof(FileBrowseOp), "FileBrowseOp");
		fbo->ptr = ptr;
		fbo->prop = prop;
		fbo->is_undo = is_undo;
		op->customdata = fbo;

		RNA_string_set(op->ptr, path_prop, str);
		MEM_freeN(str);

		/* normally ED_fileselect_get_params would handle this but we need to because of stupid
		 * user-prefs exception - campbell */
		if ((prop_relpath = RNA_struct_find_property(op->ptr, "relative_path"))) {
			if (!RNA_property_is_set(op->ptr, prop_relpath)) {
				/* annoying exception!, if were dealing with the user prefs, default relative to be off */
				RNA_property_boolean_set(op->ptr, prop_relpath, U.flag & USER_RELPATHS && (ptr.data != &U));
			}
		}
		WM_event_add_fileselect(C, op);

		return OPERATOR_RUNNING_MODAL;
	}
}
Example #24
0
static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
	Scene *scene= CTX_data_scene(C);
	View3D *v3d= CTX_wm_view3d(C);
	Base *base= ED_view3d_give_base_under_cursor(C, event->mval);
	Image *ima= NULL;
	Mesh *me;
	Object *obedit;
	int exitmode= 0;
	char name[32];
	
	/* Check context */
	if(base==NULL || base->object->type!=OB_MESH) {
		BKE_report(op->reports, RPT_ERROR, "Not an Object or Mesh");
		return OPERATOR_CANCELLED;
	}
	
	/* check input variables */
	if(RNA_property_is_set(op->ptr, "filepath")) {
		char path[FILE_MAX];
		
		RNA_string_get(op->ptr, "filepath", path);
		ima= BKE_add_image_file(path);
	}
	else {
		RNA_string_get(op->ptr, "name", name);
		ima= (Image *)find_id("IM", name);
	}
	
	if(!ima) {
		BKE_report(op->reports, RPT_ERROR, "Not an Image.");
		return OPERATOR_CANCELLED;
	}
	
	/* turn mesh in editmode */
	/* BKE_mesh_get/end_editmesh: ED_uvedit_assign_image also calls this */

	obedit= base->object;
	me= obedit->data;
	if(me->edit_mesh==NULL) {
		make_editMesh(scene, obedit);
		exitmode= 1;
	}
	if(me->edit_mesh==NULL)
		return OPERATOR_CANCELLED;
	
	ED_uvedit_assign_image(scene, obedit, ima, NULL);

	if(exitmode) {
		load_editMesh(scene, obedit);
		free_editMesh(me->edit_mesh);
		MEM_freeN(me->edit_mesh);
		me->edit_mesh= NULL;
	}

	/* dummie drop support; ensure view shows a result :) */
	if(v3d)
		v3d->flag2 |= V3D_SOLID_TEX;
	
	WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
	
	return OPERATOR_FINISHED;
}
Example #25
0
static int object_warp_verts_exec(bContext *C, wmOperator *op)
{
	const float warp_angle = RNA_float_get(op->ptr, "warp_angle");
	const float offset_angle = RNA_float_get(op->ptr, "offset_angle");

	TransVertStore tvs = {NULL};
	Object *obedit = CTX_data_edit_object(C);

	/* typically from 'rv3d' and 3d cursor */
	float viewmat[4][4];
	float center[3];

	/* 'viewmat' relative vars */
	float mat_view[4][4];
	float center_view[3];

	float min, max;


	ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
	if (tvs.transverts == NULL) {
		return OPERATOR_CANCELLED;
	}


	/* get viewmatrix */
	{
		PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat");
		if (RNA_property_is_set(op->ptr, prop_viewmat)) {
			RNA_property_float_get_array(op->ptr, prop_viewmat, (float *)viewmat);
		}
		else {
			RegionView3D *rv3d = CTX_wm_region_view3d(C);

			if (rv3d) {
				copy_m4_m4(viewmat, rv3d->viewmat);
			}
			else {
				unit_m4(viewmat);
			}

			RNA_property_float_set_array(op->ptr, prop_viewmat, (float *)viewmat);
		}
	}


	/* get center */
	{
		PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
		if (RNA_property_is_set(op->ptr, prop_center)) {
			RNA_property_float_get_array(op->ptr, prop_center, center);
		}
		else {
			Scene *scene = CTX_data_scene(C);
			View3D *v3d = CTX_wm_view3d(C);
			const float *cursor;

			cursor = ED_view3d_cursor3d_get(scene, v3d);
			copy_v3_v3(center, cursor);

			RNA_property_float_set_array(op->ptr, prop_center, center);
		}
	}


	object_warp_calc_view_matrix(mat_view, center_view, obedit, viewmat, center, offset_angle);


	/* get minmax */
	{
		PropertyRNA *prop_min = RNA_struct_find_property(op->ptr, "min");
		PropertyRNA *prop_max = RNA_struct_find_property(op->ptr, "max");

		if (RNA_property_is_set(op->ptr, prop_min) ||
		    RNA_property_is_set(op->ptr, prop_max))
		{
			min = RNA_property_float_get(op->ptr, prop_min);
			max = RNA_property_float_get(op->ptr, prop_max);
		}
		else {
			/* handy to set the bounds of the mesh */
			object_warp_transverts_minmax_x(&tvs, mat_view, center_view, &min, &max);

			RNA_property_float_set(op->ptr, prop_min, min);
			RNA_property_float_set(op->ptr, prop_max, max);
		}

		if (min > max) {
			SWAP(float, min, max);
		}
	}

	if (min != max) {
		object_warp_transverts(&tvs, mat_view, center_view, warp_angle, min, max);
	}

	ED_transverts_update_obedit(&tvs, obedit);
	ED_transverts_free(&tvs);

	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);

	return OPERATOR_FINISHED;
}
Example #26
0
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
	/* new render clears all callbacks */
	Main *mainp;
	Scene *scene= CTX_data_scene(C);
	SceneRenderLayer *srl=NULL;
	bScreen *screen= CTX_wm_screen(C);
	View3D *v3d= CTX_wm_view3d(C);
	Render *re;
	wmJob *steve;
	RenderJob *rj;
	Image *ima;
	int jobflag;
	const short is_animation= RNA_boolean_get(op->ptr, "animation");
	const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
	struct Object *camera_override= v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
	
	/* only one render job at a time */
	if(WM_jobs_test(CTX_wm_manager(C), scene))
		return OPERATOR_CANCELLED;

	if(!RE_is_rendering_allowed(scene, camera_override, op->reports)) {
		return OPERATOR_CANCELLED;
	}

	if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
		BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
		return OPERATOR_CANCELLED;
	}	
	
	/* stop all running jobs, currently previews frustrate Render */
	WM_jobs_stop_all(CTX_wm_manager(C));

	/* get main */
	if(G.rt == 101) {
		/* thread-safety experiment, copy main from the undo buffer */
		mainp= BKE_undo_get_main(&scene);
	}
	else
		mainp= CTX_data_main(C);

	/* cancel animation playback */
	if (screen->animtimer)
		ED_screen_animation_play(C, 0, 0);
	
	/* handle UI stuff */
	WM_cursor_wait(1);

	/* flush multires changes (for sculpt) */
	multires_force_render_update(CTX_data_active_object(C));

	/* cleanup sequencer caches before starting user triggered render.
	   otherwise, invalidated cache entries can make their way into
	   the output rendering. We can't put that into RE_BlenderFrame,
	   since sequence rendering can call that recursively... (peter) */
	seq_stripelem_cache_cleanup();

	/* get editmode results */
	ED_object_exit_editmode(C, 0);	/* 0 = does not exit editmode */

	// store spare
	// get view3d layer, local layer, make this nice api call to render
	// store spare

	/* ensure at least 1 area shows result */
	render_view_open(C, event->x, event->y);

	jobflag= WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS;
	
	/* single layer re-render */
	if(RNA_property_is_set(op->ptr, "layer")) {
		SceneRenderLayer *rl;
		Scene *scn;
		char scene_name[MAX_ID_NAME-2], rl_name[RE_MAXNAME];

		RNA_string_get(op->ptr, "layer", rl_name);
		RNA_string_get(op->ptr, "scene", scene_name);

		scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
		rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
		
		if (scn && rl) {
			/* camera switch wont have updated */
			scn->r.cfra= scene->r.cfra;
			scene_camera_switch_update(scn);

			scene = scn;
			srl = rl;
		}
		jobflag |= WM_JOB_SUSPEND;
	}

	/* job custom data */
	rj= MEM_callocN(sizeof(RenderJob), "render job");
	rj->main= mainp;
	rj->scene= scene;
	rj->win= CTX_wm_window(C);
	rj->srl = srl;
	rj->camera_override = camera_override;
	rj->lay = (v3d)? v3d->lay: scene->lay;
	rj->anim= is_animation;
	rj->write_still= is_write_still && !is_animation;
	rj->iuser.scene= scene;
	rj->iuser.ok= 1;
	rj->reports= op->reports;

	/* setup job */
	steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", jobflag);
	WM_jobs_customdata(steve, rj, render_freejob);
	WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
	WM_jobs_callbacks(steve, render_startjob, NULL, NULL, render_endjob);

	/* get a render result image, and make sure it is empty */
	ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
	BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
	BKE_image_backup_render(rj->scene, ima);
	rj->image= ima;

	/* setup new render */
	re= RE_NewRender(scene->id.name);
	RE_test_break_cb(re, rj, render_breakjob);
	RE_draw_lock_cb(re, rj, render_drawlock);
	RE_display_draw_cb(re, rj, image_rect_update);
	RE_stats_draw_cb(re, rj, image_renderinfo_cb);
	RE_progress_cb(re, rj, render_progress_update);

	rj->re= re;
	G.afbreek= 0;

	WM_jobs_start(CTX_wm_manager(C), steve);

	WM_cursor_wait(0);
	WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);

	/* we set G.rendering here already instead of only in the job, this ensure
	   main loop or other scene updates are disabled in time, since they may
	   have started before the job thread */
	G.rendering = 1;

	/* add modal handler for ESC */
	WM_event_add_modal_handler(C, op);

	return OPERATOR_RUNNING_MODAL;
}
Example #27
0
static void bake_set_props(wmOperator *op, Scene *scene)
{
	PropertyRNA *prop;
	BakeData *bake = &scene->r.bake;

	prop = RNA_struct_find_property(op->ptr, "filepath");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_string_set(op->ptr, prop, bake->filepath);
	}

	prop =  RNA_struct_find_property(op->ptr, "width");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_int_set(op->ptr, prop, bake->width);
	}

	prop =  RNA_struct_find_property(op->ptr, "height");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_int_set(op->ptr, prop, bake->width);
	}

	prop = RNA_struct_find_property(op->ptr, "margin");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_int_set(op->ptr, prop, bake->margin);
	}

	prop = RNA_struct_find_property(op->ptr, "use_selected_to_active");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE) != 0);
	}

	prop = RNA_struct_find_property(op->ptr, "cage_extrusion");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_float_set(op->ptr, prop, bake->cage_extrusion);
	}

	prop = RNA_struct_find_property(op->ptr, "cage_object");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_string_set(op->ptr, prop, bake->cage);
	}

	prop = RNA_struct_find_property(op->ptr, "normal_space");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_enum_set(op->ptr, prop, bake->normal_space);
	}

	prop = RNA_struct_find_property(op->ptr, "normal_r");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[0]);
	}

	prop = RNA_struct_find_property(op->ptr, "normal_g");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[1]);
	}

	prop = RNA_struct_find_property(op->ptr, "normal_b");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[2]);
	}

	prop = RNA_struct_find_property(op->ptr, "save_mode");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_enum_set(op->ptr, prop, bake->save_mode);
	}

	prop = RNA_struct_find_property(op->ptr, "use_clear");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR) != 0);
	}

	prop = RNA_struct_find_property(op->ptr, "use_cage");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE) != 0);
	}

	prop = RNA_struct_find_property(op->ptr, "use_split_materials");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT) != 0);
	}

	prop = RNA_struct_find_property(op->ptr, "use_automatic_name");
	if (!RNA_property_is_set(op->ptr, prop)) {
		RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0);
	}
}
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;
	}
}