static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value) { wmOperatorType *ot; PointerRNA ptr; const char *opname = _PyUnicode_AsString(value); BPy_StructRNA *pyrna = NULL; if (opname == NULL) { PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_rna() expects a string argument"); return NULL; } ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_KeyError, "_bpy.ops.get_rna(\"%s\") not found", opname); return NULL; } /* type */ //RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr); /* XXX - should call WM_operator_properties_free */ WM_operator_properties_create_ptr(&ptr, ot); WM_operator_properties_sanitize(&ptr, 0); pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); #ifdef PYRNA_FREE_SUPPORT pyrna->freeptr = true; #endif return (PyObject *)pyrna; }
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; }
static PointerRNA rna_uiItemO( uiLayout *layout, const char *opname, const char *name, const char *text_ctxt, bool translate, int icon, bool emboss, bool depress, int icon_value) { wmOperatorType *ot; ot = WM_operatortype_find(opname, 0); /* print error next */ if (!ot || !ot->srna) { RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname); return PointerRNA_NULL; } /* Get translated name (label). */ name = rna_translate_ui_text(name, text_ctxt, ot->srna, NULL, translate); if (icon_value && !icon) { icon = icon_value; } int flag = (emboss) ? 0 : UI_ITEM_R_NO_BG; flag |= (depress) ? UI_ITEM_O_DEPRESS : 0; PointerRNA opptr; uiItemFullO_ptr(layout, ot, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag, &opptr); return opptr; }
static void poselib_add_menu_invoke__replacemenu (bContext *C, uiLayout *layout, void *UNUSED(arg)) { Object *ob= get_poselib_object(C); bAction *act= ob->poselib; /* never NULL */ TimeMarker *marker; wmOperatorType *ot = WM_operatortype_find("POSELIB_OT_pose_add", 1); BLI_assert(ot != NULL); /* set the operator execution context correctly */ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); /* add each marker to this menu */ for (marker= act->markers.first; marker; marker= marker->next) { PointerRNA props_ptr; props_ptr = uiItemFullO_ptr(layout, ot, marker->name, ICON_ARMATURE_DATA, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_int_set(&props_ptr, "frame", marker->frame); RNA_string_set(&props_ptr, "name", marker->name); } }
static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; PointerRNA ptr; char *opname; PyObject *kw = NULL; /* optional args */ int all_args = 1; int macro_args = 1; int error_val = 0; char *buf = NULL; PyObject *pybuf; bContext *C = (bContext *)BPy_GetContext(); if (C == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context is None, cant get the string representation of this object."); return NULL; } if (!PyArg_ParseTuple(args, "s|O!ii:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args, ¯o_args)) return NULL; ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_AttributeError, "_bpy.ops.as_string: operator \"%.200s\" " "could not be found", opname); return NULL; } /* WM_operator_properties_create(&ptr, opname); */ /* Save another lookup */ RNA_pointer_create(NULL, ot->srna, NULL, &ptr); if (kw && PyDict_Size(kw)) error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: "); if (error_val == 0) buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr); WM_operator_properties_free(&ptr); if (error_val == -1) { return NULL; } if (buf) { pybuf = PyUnicode_FromString(buf); MEM_freeN(buf); } else { pybuf = PyUnicode_FromString(""); } return pybuf; }
static wmKeyMap *rna_keymap_find_modal(wmKeyConfig *UNUSED(keyconf), const char *idname) { wmOperatorType *ot = WM_operatortype_find(idname, 0); if (!ot) return NULL; else return ot->modalkeymap; }
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname) { wmOperatorType *ot= WM_operatortype_find(opname, 0); if(ot) ot->modalkeymap= km; else printf("error: modalkeymap_assign, unknown operator %s\n", opname); }
static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v) { Main *bmain = CTX_data_main(C); const char *app_template = template_v; bool has_startup_items = false; wmOperatorType *ot_append = WM_operatortype_find("WORKSPACE_OT_append_activate", true); WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template); WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template); if (startup_config) { for (WorkSpace *workspace = startup_config->workspaces.first; workspace; workspace = workspace->id.next) { uiLayout *row = uiLayoutRow(layout, false); if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) { uiLayoutSetActive(row, false); } workspace_append_button(row, ot_append, workspace, startup_config->main); has_startup_items = true; } } if (builtin_config) { bool has_title = false; for (WorkSpace *workspace = builtin_config->workspaces.first; workspace; workspace = workspace->id.next) { if (startup_config && BLI_findstring(&startup_config->workspaces, workspace->id.name, offsetof(ID, name))) { continue; } if (!has_title) { if (has_startup_items) { uiItemS(layout); } has_title = true; } uiLayout *row = uiLayoutRow(layout, false); if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) { uiLayoutSetActive(row, false); } workspace_append_button(row, ot_append, workspace, builtin_config->main); } } if (startup_config) { BKE_blendfile_workspace_config_data_free(startup_config); } if (builtin_config) { BKE_blendfile_workspace_config_data_free(builtin_config); } }
static PointerRNA rna_WindoManager_operator_properties_last(const char *idname) { wmOperatorType *ot = WM_operatortype_find(idname, true); if (ot != NULL) { PointerRNA ptr; WM_operator_last_properties_ensure(ot, &ptr); return ptr; } return PointerRNA_NULL; }
static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) { int exit_code; TransInfo *t = op->customdata; const enum TfmMode mode_prev = t->mode; #if 0 // stable 2D mouse coords map to different 3D coords while the 3D mouse is active // in other words, 2D deltas are no longer good enough! // disable until individual 'transformers' behave better if (event->type == NDOF_MOTION) return OPERATOR_PASS_THROUGH; #endif /* XXX insert keys are called here, and require context */ t->context = C; exit_code = transformEvent(t, event); t->context = NULL; transformApply(C, t); exit_code |= transformEnd(C, t); if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) { transformops_exit(C, op); exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */ } else { if (mode_prev != t->mode) { /* WARNING: this is not normal to switch operator types * normally it would not be supported but transform happens * to share callbacks between differernt operators. */ wmOperatorType *ot_new = NULL; TransformModeItem *item = transform_modes; while (item->idname) { if (item->mode == t->mode) { ot_new = WM_operatortype_find(item->idname, false); break; } item++; } BLI_assert(ot_new != NULL); if (ot_new) { WM_operator_type_set(op, ot_new); } /* end suspicious code */ } } return exit_code; }
PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; wmOperatorTypeMacro *otmacro; PyObject *macro; PointerRNA ptr_otmacro; StructRNA *srna; char *opname; const char *macroname; if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", ¯o, &opname)) return NULL; if (WM_operatortype_find(opname, TRUE) == NULL) { PyErr_Format(PyExc_ValueError, "Macro Define: '%s' is not a valid operator id", opname); return NULL; } /* identifiers */ srna = srna_from_self(macro, "Macro Define:"); macroname = RNA_struct_identifier(srna); ot = WM_operatortype_find(macroname, TRUE); if (!ot) { PyErr_Format(PyExc_ValueError, "Macro Define: '%s' is not a valid macro or hasn't been registered yet", macroname); return NULL; } otmacro = WM_operatortype_macro_define(ot, opname); RNA_pointer_create(NULL, &RNA_OperatorMacro, otmacro, &ptr_otmacro); return pyrna_struct_CreatePyObject(&ptr_otmacro); }
static void rna_uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opname, const char *propname, const char *name, const char *text_ctxt, int translate, int icon) { wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */ if (!ot || !ot->srna) { RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname); return; } /* Get translated name (label). */ name = rna_translate_ui_text(name, text_ctxt, ot->srna, NULL, translate); /* XXX This will search operator again :( */ uiItemMenuEnumO(layout, C, opname, propname, name, icon); }
static int workspace_append(bContext *C, const char *directory, const char *idname) { wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false); PointerRNA opptr; int retval; WM_operator_properties_create_ptr(&opptr, ot); RNA_string_set(&opptr, "directory", directory); RNA_string_set(&opptr, "filename", idname); RNA_boolean_set(&opptr, "autoselect", false); retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr); WM_operator_properties_free(&opptr); return retval; }
static int add_driver_button_exec(bContext *C, wmOperator *op) { short mapping_type = RNA_enum_get(op->ptr, "mapping_type"); if (ELEM(mapping_type, CREATEDRIVER_MAPPING_NONE, CREATEDRIVER_MAPPING_NONE_ALL)) { /* Just create driver with no targets */ return add_driver_button_none(C, op, mapping_type); } else { /* Create Driver using Eyedropper */ wmOperatorType *ot = WM_operatortype_find("UI_OT_eyedropper_driver", true); /* XXX: We assume that it's fine to use the same set of properties, since they're actually the same... */ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr); return OPERATOR_FINISHED; } }
/** * Sets the mode to a compatible state (use before entering the mode). * * This is so each mode's exec function can call */ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, ReportList *reports) { bool ok; if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) { const char *opstring = object_mode_op_string(ob->mode); WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL); ok = ELEM(ob->mode, mode, OB_MODE_OBJECT); if (!ok) { wmOperatorType *ot = WM_operatortype_find(opstring, false); BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name); } } else { ok = true; } return ok; }
static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *name, const char *text_ctxt, int translate, int icon, int emboss) { wmOperatorType *ot; int flag; ot = WM_operatortype_find(opname, 0); /* print error next */ if (!ot || !ot->srna) { RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname); return PointerRNA_NULL; } /* Get translated name (label). */ name = rna_translate_ui_text(name, text_ctxt, ot->srna, NULL, translate); flag = UI_ITEM_O_RETURN_PROPS; flag |= (emboss) ? 0 : UI_ITEM_R_NO_BG; return uiItemFullO_ptr(layout, ot, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag); }
wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, wmEvent *), void (*copy)(wmDrag *, wmDropBox *)) { wmDropBox *drop= MEM_callocN(sizeof(wmDropBox), "wmDropBox"); drop->poll= poll; drop->copy= copy; drop->ot= WM_operatortype_find(idname, 0); drop->opcontext= WM_OP_INVOKE_DEFAULT; if(drop->ot==NULL) { MEM_freeN(drop); printf("Error: dropbox with unknown operator: %s\n", idname); return NULL; } WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname); BLI_addtail(lb, drop); return drop; }
static PyObject *pyop_getinstance(PyObject *UNUSED(self), PyObject *value) { wmOperatorType *ot; wmOperator *op; PointerRNA ptr; const char *opname = _PyUnicode_AsString(value); BPy_StructRNA *pyrna = NULL; if (opname == NULL) { PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_instance() expects a string argument"); return NULL; } ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_KeyError, "_bpy.ops.get_instance(\"%s\") not found", opname); return NULL; } #ifdef PYRNA_FREE_SUPPORT op = MEM_callocN(sizeof(wmOperator), __func__); #else op = PyMem_MALLOC(sizeof(wmOperator)); memset(op, 0, sizeof(wmOperator)); #endif BLI_strncpy(op->idname, op->idname, sizeof(op->idname)); /* in case its needed */ op->type = ot; RNA_pointer_create(NULL, &RNA_Operator, op, &ptr); pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); #ifdef PYRNA_FREE_SUPPORT pyrna->freeptr = true; #endif op->ptr = &pyrna->ptr; return (PyObject *)pyrna; }
static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) { int exit_code; TransInfo *t = op->customdata; const enum TfmMode mode_prev = t->mode; #if 0 // stable 2D mouse coords map to different 3D coords while the 3D mouse is active // in other words, 2D deltas are no longer good enough! // disable until individual 'transformers' behave better if (event->type == NDOF_MOTION) return OPERATOR_PASS_THROUGH; #endif /* XXX insert keys are called here, and require context */ t->context = C; exit_code = transformEvent(t, event); t->context = NULL; /* XXX, workaround: active needs to be calculated before transforming, * since we're not reading from 'td->center' in this case. see: T40241 */ if (t->tsnap.target == SCE_SNAP_TARGET_ACTIVE) { /* In camera view, tsnap callback is not set (see initSnappingMode() in transfrom_snap.c, and T40348). */ if (t->tsnap.targetSnap && ((t->tsnap.status & TARGET_INIT) == 0)) { t->tsnap.targetSnap(t); } } transformApply(C, t); exit_code |= transformEnd(C, t); if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) { transformops_exit(C, op); exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */ } else { if (mode_prev != t->mode) { /* WARNING: this is not normal to switch operator types * normally it would not be supported but transform happens * to share callbacks between different operators. */ wmOperatorType *ot_new = NULL; TransformModeItem *item = transform_modes; while (item->idname) { if (item->mode == t->mode) { ot_new = WM_operatortype_find(item->idname, false); break; } item++; } BLI_assert(ot_new != NULL); if (ot_new) { WM_operator_type_set(op, ot_new); } /* end suspicious code */ } } return exit_code; }
static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; char *opname; PyObject *context_dict = NULL; /* optional args */ PyObject *context_dict_back; char *context_str = NULL; PyObject *ret; int context = WM_OP_EXEC_DEFAULT; /* XXX Todo, work out a better solution for passing on context, * could make a tuple from self and pack the name and Context into it... */ bContext *C = (bContext *)BPy_GetContext(); if (C == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); return NULL; } if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str)) return NULL; ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_AttributeError, "Polling operator \"bpy.ops.%s\" error, " "could not be found", opname); return NULL; } if (context_str) { if (RNA_enum_value_from_id(operator_context_items, context_str, &context) == 0) { char *enum_str = BPy_enum_as_string(operator_context_items); PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, " "expected a string enum in (%.200s)", opname, enum_str); MEM_freeN(enum_str); return NULL; } } if (context_dict == NULL || context_dict == Py_None) { context_dict = NULL; } else if (!PyDict_Check(context_dict)) { PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, " "custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name); return NULL; } context_dict_back = CTX_py_dict_get(C); CTX_py_dict_set(C, (void *)context_dict); Py_XINCREF(context_dict); /* so we done loose it */ /* main purpose of thsi function */ ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False; /* restore with original context dict, probably NULL but need this for nested operator calls */ Py_XDECREF(context_dict); CTX_py_dict_set(C, (void *)context_dict_back); Py_INCREF(ret); return ret; }
static bool workspace_append_activate_poll(bContext *C) { wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false); return WM_operator_poll(C, ot); }
/* mouse coordinate converversion happens here */ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr) { bContext *C = C_void_ptr; wmWindowManager *wm = CTX_wm_manager(C); GHOST_TEventType type = GHOST_GetEventType(evt); int time = GHOST_GetEventTime(evt); if (type == GHOST_kEventQuit) { WM_exit(C); } else { GHOST_WindowHandle ghostwin = GHOST_GetEventWindow(evt); GHOST_TEventDataPtr data = GHOST_GetEventData(evt); wmWindow *win; /* Ghost now can call this function for life resizes, but it should return if WM didn't initialize yet. * Can happen on file read (especially full size window) */ if ((wm->initialized & WM_INIT_WINDOW) == 0) { return 1; } if (!ghostwin) { /* XXX - should be checked, why are we getting an event here, and */ /* what is it? */ puts("<!> event has no window"); return 1; } else if (!GHOST_ValidWindow(g_system, ghostwin)) { /* XXX - should be checked, why are we getting an event here, and */ /* what is it? */ puts("<!> event has invalid window"); return 1; } else { win = GHOST_GetWindowUserData(ghostwin); } switch (type) { case GHOST_kEventWindowDeactivate: wm_event_add_ghostevent(wm, win, type, time, data); win->active = 0; /* XXX */ /* clear modifiers for inactive windows */ win->eventstate->alt = 0; win->eventstate->ctrl = 0; win->eventstate->shift = 0; win->eventstate->oskey = 0; win->eventstate->keymodifier = 0; break; case GHOST_kEventWindowActivate: { GHOST_TEventKeyData kdata; wmEvent event; int wx, wy; const int keymodifier = ((query_qual(SHIFT) ? KM_SHIFT : 0) | (query_qual(CONTROL) ? KM_CTRL : 0) | (query_qual(ALT) ? KM_ALT : 0) | (query_qual(OS) ? KM_OSKEY : 0)); /* Win23/GHOST modifier bug, see T40317 */ #ifndef WIN32 //# define USE_WIN_ACTIVATE #endif wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */ win->active = 1; // window_handle(win, INPUTCHANGE, win->active); /* bad ghost support for modifier keys... so on activate we set the modifiers again */ /* TODO: This is not correct since a modifier may be held when a window is activated... * better solve this at ghost level. attempted fix r54450 but it caused bug [#34255] * * For now don't send GHOST_kEventKeyDown events, just set the 'eventstate'. */ kdata.ascii = '\0'; kdata.utf8_buf[0] = '\0'; if (win->eventstate->shift) { if ((keymodifier & KM_SHIFT) == 0) { kdata.key = GHOST_kKeyLeftShift; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } } #ifdef USE_WIN_ACTIVATE else { if (keymodifier & KM_SHIFT) { win->eventstate->shift = KM_MOD_FIRST; } } #endif if (win->eventstate->ctrl) { if ((keymodifier & KM_CTRL) == 0) { kdata.key = GHOST_kKeyLeftControl; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } } #ifdef USE_WIN_ACTIVATE else { if (keymodifier & KM_CTRL) { win->eventstate->ctrl = KM_MOD_FIRST; } } #endif if (win->eventstate->alt) { if ((keymodifier & KM_ALT) == 0) { kdata.key = GHOST_kKeyLeftAlt; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } } #ifdef USE_WIN_ACTIVATE else { if (keymodifier & KM_ALT) { win->eventstate->alt = KM_MOD_FIRST; } } #endif if (win->eventstate->oskey) { if ((keymodifier & KM_OSKEY) == 0) { kdata.key = GHOST_kKeyOS; wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, time, &kdata); } } #ifdef USE_WIN_ACTIVATE else { if (keymodifier & KM_OSKEY) { win->eventstate->oskey = KM_MOD_FIRST; } } #endif #undef USE_WIN_ACTIVATE /* keymodifier zero, it hangs on hotkeys that open windows otherwise */ win->eventstate->keymodifier = 0; /* entering window, update mouse pos. but no event */ wm_get_cursor_position(win, &wx, &wy); win->eventstate->x = wx; win->eventstate->y = wy; win->addmousemove = 1; /* enables highlighted buttons */ wm_window_make_drawable(wm, win); /* window might be focused by mouse click in configuration of window manager * when focus is not following mouse * click could have been done on a button and depending on window manager settings * click would be passed to blender or not, but in any case button under cursor * should be activated, so at max next click on button without moving mouse * would trigger it's handle function * currently it seems to be common practice to generate new event for, but probably * we'll need utility function for this? (sergey) */ wm_event_init_from_window(win, &event); event.type = MOUSEMOVE; event.prevx = event.x; event.prevy = event.y; wm_event_add(win, &event); break; } case GHOST_kEventWindowClose: { wm_window_close(C, wm, win); break; } case GHOST_kEventWindowUpdate: { if (G.debug & G_DEBUG_EVENTS) { printf("%s: ghost redraw %d\n", __func__, win->winid); } wm_window_make_drawable(wm, win); WM_event_add_notifier(C, NC_WINDOW, NULL); break; } case GHOST_kEventWindowSize: case GHOST_kEventWindowMove: { GHOST_TWindowState state; state = GHOST_GetWindowState(win->ghostwin); win->windowstate = state; /* stop screencast if resize */ if (type == GHOST_kEventWindowSize) { WM_jobs_stop(wm, win->screen, NULL); } /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; int l, t, r, b, scr_w, scr_h; int sizex, sizey, posx, posy; client_rect = GHOST_GetClientBounds(win->ghostwin); GHOST_GetRectangle(client_rect, &l, &t, &r, &b); GHOST_DisposeRectangle(client_rect); wm_get_desktopsize(&scr_w, &scr_h); sizex = r - l; sizey = b - t; posx = l; posy = scr_h - t - win->sizey; /* * Ghost sometimes send size or move events when the window hasn't changed. * One case of this is using compiz on linux. To alleviate the problem * we ignore all such event here. * * It might be good to eventually do that at Ghost level, but that is for * another time. */ if (win->sizex != sizex || win->sizey != sizey || win->posx != posx || win->posy != posy) { win->sizex = sizex; win->sizey = sizey; win->posx = posx; win->posy = posy; /* debug prints */ if (G.debug & G_DEBUG_EVENTS) { const char *state_str; state = GHOST_GetWindowState(win->ghostwin); if (state == GHOST_kWindowStateNormal) { state_str = "normal"; } else if (state == GHOST_kWindowStateMinimized) { state_str = "minimized"; } else if (state == GHOST_kWindowStateMaximized) { state_str = "maximized"; } else if (state == GHOST_kWindowStateFullScreen) { state_str = "fullscreen"; } else { state_str = "<unknown>"; } printf("%s: window %d state = %s\n", __func__, win->winid, state_str); if (type != GHOST_kEventWindowSize) { printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey); } } wm_window_make_drawable(wm, win); wm_draw_window_clear(win); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); #if defined(__APPLE__) || defined(WIN32) /* OSX and Win32 don't return to the mainloop while resize */ wm_event_do_handlers(C); wm_event_do_notifiers(C); wm_draw_update(C); #endif } } break; } case GHOST_kEventOpenMainFile: { PointerRNA props_ptr; wmWindow *oldWindow; const char *path = GHOST_GetEventData(evt); if (path) { wmOperatorType *ot = WM_operatortype_find("WM_OT_open_mainfile", false); /* operator needs a valid window in context, ensures * it is correctly set */ oldWindow = CTX_wm_window(C); CTX_wm_window_set(C, win); WM_operator_properties_create_ptr(&props_ptr, ot); RNA_string_set(&props_ptr, "filepath", path); WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); CTX_wm_window_set(C, oldWindow); } break; } case GHOST_kEventDraggingDropDone: { wmEvent event; GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); int wx, wy; /* entering window, update mouse pos */ wm_get_cursor_position(win, &wx, &wy); win->eventstate->x = wx; win->eventstate->y = wy; wm_event_init_from_window(win, &event); /* copy last state, like mouse coords */ /* activate region */ event.type = MOUSEMOVE; event.prevx = event.x; event.prevy = event.y; wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */ win->active = 1; wm_event_add(win, &event); /* make blender drop event with custom data pointing to wm drags */ event.type = EVT_DROP; event.val = KM_RELEASE; event.custom = EVT_DATA_DRAGDROP; event.customdata = &wm->drags; event.customdatafree = 1; wm_event_add(win, &event); /* printf("Drop detected\n"); */ /* add drag data to wm for paths: */ if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { GHOST_TStringArray *stra = ddd->data; int a, icon; for (a = 0; a < stra->count; a++) { printf("drop file %s\n", stra->strings[a]); /* try to get icon type from extension */ icon = ED_file_extension_icon((char *)stra->strings[a]); WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0, WM_DRAG_NOP); /* void poin should point to string, it makes a copy */ break; /* only one drop element supported now */ } } break; } case GHOST_kEventNativeResolutionChange: // printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin)); U.pixelsize = wm_window_pixelsize(win); BKE_userdef_state(); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); break; case GHOST_kEventTrackpad: { GHOST_TEventTrackpadData *pd = data; wm_convert_cursor_position(win, &pd->x, &pd->y); wm_event_add_ghostevent(wm, win, type, time, data); break; } case GHOST_kEventCursorMove: { GHOST_TEventCursorData *cd = data; wm_convert_cursor_position(win, &cd->x, &cd->y); wm_event_add_ghostevent(wm, win, type, time, data); break; } default: wm_event_add_ghostevent(wm, win, type, time, data); break; } } return 1; }
static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; int error_val = 0; PointerRNA ptr; int operator_ret = OPERATOR_CANCELLED; char *opname; char *context_str = NULL; PyObject *kw = NULL; /* optional args */ PyObject *context_dict = NULL; /* optional args */ PyObject *context_dict_back; /* note that context is an int, python does the conversion in this case */ int context = WM_OP_EXEC_DEFAULT; int is_undo = false; /* XXX Todo, work out a better solution for passing on context, * could make a tuple from self and pack the name and Context into it... */ bContext *C = (bContext *)BPy_GetContext(); if (C == NULL) { PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); return NULL; } if (!PyArg_ParseTuple(args, "sO|O!si:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str, &is_undo)) { return NULL; } ot = WM_operatortype_find(opname, true); if (ot == NULL) { PyErr_Format(PyExc_AttributeError, "Calling operator \"bpy.ops.%s\" error, " "could not be found", opname); return NULL; } if (!pyrna_write_check()) { PyErr_Format(PyExc_RuntimeError, "Calling operator \"bpy.ops.%s\" error, " "can't modify blend data in this state (drawing/rendering)", opname); return NULL; } if (context_str) { if (RNA_enum_value_from_id(operator_context_items, context_str, &context) == 0) { char *enum_str = BPy_enum_as_string(operator_context_items); PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, " "expected a string enum in (%.200s)", opname, enum_str); MEM_freeN(enum_str); return NULL; } } if (context_dict == NULL || context_dict == Py_None) { context_dict = NULL; } else if (!PyDict_Check(context_dict)) { PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, " "custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name); return NULL; } context_dict_back = CTX_py_dict_get(C); CTX_py_dict_set(C, (void *)context_dict); Py_XINCREF(context_dict); /* so we done loose it */ if (WM_operator_poll_context((bContext *)C, ot, context) == false) { const char *msg = CTX_wm_operator_poll_msg_get(C); PyErr_Format(PyExc_RuntimeError, "Operator bpy.ops.%.200s.poll() %.200s", opname, msg ? msg : "failed, context is incorrect"); CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */ error_val = -1; } else { WM_operator_properties_create_ptr(&ptr, ot); WM_operator_properties_sanitize(&ptr, 0); if (kw && PyDict_Size(kw)) error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: "); if (error_val == 0) { ReportList *reports; reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these don't move into global reports */ #ifdef BPY_RELEASE_GIL /* release GIL, since a thread could be started from an operator * that updates a driver */ /* note: I have not seen any examples of code that does this * so it may not be officially supported but seems to work ok. */ { PyThreadState *ts = PyEval_SaveThread(); #endif operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports, is_undo); #ifdef BPY_RELEASE_GIL /* regain GIL */ PyEval_RestoreThread(ts); } #endif error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false); /* operator output is nice to have in the terminal/console too */ if (reports->list.first) { char *report_str = BKE_reports_string(reports, 0); /* all reports */ if (report_str) { PySys_WriteStdout("%s\n", report_str); MEM_freeN(report_str); } } BKE_reports_clear(reports); if ((reports->flag & RPT_FREE) == 0) { MEM_freeN(reports); } } WM_operator_properties_free(&ptr); #if 0 /* if there is some way to know an operator takes args we should use this */ { /* no props */ if (kw != NULL) { PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname); return NULL; } WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL); } #endif } /* restore with original context dict, probably NULL but need this for nested operator calls */ Py_XDECREF(context_dict); CTX_py_dict_set(C, (void *)context_dict_back); if (error_val == -1) { return NULL; } /* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(), * further access will crash blender. setting context is not needed in this case, only calling because this * function corrects bpy.data (internal Main pointer) */ BPY_modules_update(C); /* needed for when WM_OT_read_factory_settings us called from within a script */ bpy_import_main_set(CTX_data_main(C)); /* return operator_ret as a bpy enum */ return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret); }
void unpack_menu(bContext *C, const char *opname, const char *id_name, const char *abs_name, const char *folder, struct PackedFile *pf) { PointerRNA props_ptr; uiPopupMenu *pup; uiLayout *layout; char line[FILE_MAX + 100]; wmOperatorType *ot = WM_operatortype_find(opname, 1); pup = uiPupMenuBegin(C, IFACE_("Unpack File"), ICON_NONE); layout = uiPupMenuLayout(pup); props_ptr = uiItemFullO_ptr(layout, ot, IFACE_("Remove Pack"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_REMOVE); RNA_string_set(&props_ptr, "id", id_name); if (G.relbase_valid) { char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; BLI_split_file_part(abs_name, fi, sizeof(fi)); BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi); if (strcmp(abs_name, local_name) != 0) { switch (checkPackedFile(local_name, pf)) { case PF_NOFILE: BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), local_name); props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL); RNA_string_set(&props_ptr, "id", id_name); break; case PF_EQUAL: BLI_snprintf(line, sizeof(line), IFACE_("Use %s (identical)"), local_name); //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL); props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_USE_LOCAL); RNA_string_set(&props_ptr, "id", id_name); break; case PF_DIFFERS: BLI_snprintf(line, sizeof(line), IFACE_("Use %s (differs)"), local_name); //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL); props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_USE_LOCAL); RNA_string_set(&props_ptr, "id", id_name); BLI_snprintf(line, sizeof(line), IFACE_("Overwrite %s"), local_name); //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_LOCAL); props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL); RNA_string_set(&props_ptr, "id", id_name); break; } } } switch (checkPackedFile(abs_name, pf)) { case PF_NOFILE: BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), abs_name); //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL); props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL); RNA_string_set(&props_ptr, "id", id_name); break; case PF_EQUAL: BLI_snprintf(line, sizeof(line), IFACE_("Use %s (identical)"), abs_name); //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL); props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL); RNA_string_set(&props_ptr, "id", id_name); break; case PF_DIFFERS: BLI_snprintf(line, sizeof(line), IFACE_("Use %s (differs)"), abs_name); //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL); props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL); RNA_string_set(&props_ptr, "id", id_name); BLI_snprintf(line, sizeof(line), IFACE_("Overwrite %s"), abs_name); //uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL); props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL); RNA_string_set(&props_ptr, "id", id_name); break; } uiPupMenuEnd(C, pup); }
static int edittranslation_exec(bContext *C, wmOperator *op) { uiBut *but = uiContextActiveButton(C); int ret = OPERATOR_CANCELLED; if (but) { PointerRNA ptr; char popath[FILE_MAX]; const char *root = U.i18ndir; const char *uilng = BLF_lang_get(); uiStringInfo but_label = {BUT_GET_LABEL, NULL}; uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL}; uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL}; uiStringInfo but_tip = {BUT_GET_TIP, NULL}; uiStringInfo rna_tip = {BUT_GET_RNA_TIP, NULL}; uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL}; uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL}; uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL}; uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, NULL}; uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL}; if (!BLI_is_dir(root)) { BKE_report(op->reports, RPT_ERROR, "Please set your User Preferences' 'Translation Branches " "Directory' path to a valid directory"); return OPERATOR_CANCELLED; } if (!WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0)) { BKE_reportf(op->reports, RPT_ERROR, "Could not find operator '%s'! Please enable ui_translate addon " "in the User Preferences", EDTSRC_I18N_OP_NAME); return OPERATOR_CANCELLED; } /* Try to find a valid po file for current language... */ edittranslation_find_po_file(root, uilng, popath, FILE_MAX); /* printf("po path: %s\n", popath);*/ if (popath[0] == '\0') { BKE_reportf(op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root); return OPERATOR_CANCELLED; } uiButGetStrInfo(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip, &rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL); WM_operator_properties_create(&ptr, EDTSRC_I18N_OP_NAME); RNA_string_set(&ptr, "lang", uilng); RNA_string_set(&ptr, "po_file", popath); RNA_string_set(&ptr, "but_label", but_label.strinfo); RNA_string_set(&ptr, "rna_label", rna_label.strinfo); RNA_string_set(&ptr, "enum_label", enum_label.strinfo); RNA_string_set(&ptr, "but_tip", but_tip.strinfo); RNA_string_set(&ptr, "rna_tip", rna_tip.strinfo); RNA_string_set(&ptr, "enum_tip", enum_tip.strinfo); RNA_string_set(&ptr, "rna_struct", rna_struct.strinfo); RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo); RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo); RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo); ret = WM_operator_name_call(C, EDTSRC_I18N_OP_NAME, WM_OP_INVOKE_DEFAULT, &ptr); /* Clean up */ if (but_label.strinfo) MEM_freeN(but_label.strinfo); if (rna_label.strinfo) MEM_freeN(rna_label.strinfo); if (enum_label.strinfo) MEM_freeN(enum_label.strinfo); if (but_tip.strinfo) MEM_freeN(but_tip.strinfo); if (rna_tip.strinfo) MEM_freeN(rna_tip.strinfo); if (enum_tip.strinfo) MEM_freeN(enum_tip.strinfo); if (rna_struct.strinfo) MEM_freeN(rna_struct.strinfo); if (rna_prop.strinfo) MEM_freeN(rna_prop.strinfo); if (rna_enum.strinfo) MEM_freeN(rna_enum.strinfo); if (rna_ctxt.strinfo) MEM_freeN(rna_ctxt.strinfo); return ret; } else { BKE_report(op->reports, RPT_ERROR, "Active button not found"); return OPERATOR_CANCELLED; } }
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; } }