Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/CMakeLists.txt8
-rw-r--r--source/blender/windowmanager/SConscript5
-rw-r--r--source/blender/windowmanager/WM_api.h10
-rw-r--r--source/blender/windowmanager/WM_types.h41
-rw-r--r--source/blender/windowmanager/intern/wm.c19
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c45
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c153
-rw-r--r--source/blender/windowmanager/intern/wm_files.c69
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c1
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c22
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c27
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c153
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c787
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c9
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c3
-rw-r--r--source/blender/windowmanager/intern/wm_window.c29
-rw-r--r--source/blender/windowmanager/wm_event_system.h3
-rw-r--r--source/blender/windowmanager/wm_event_types.h48
-rw-r--r--source/blender/windowmanager/wm_window.h5
19 files changed, 974 insertions, 463 deletions
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 088bddc8a76..78b5d499644 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -130,10 +130,10 @@ if(WITH_BUILDINFO)
add_definitions(-DWITH_BUILDINFO)
endif()
-if(WIN322)
- list(APPEND INC
- ../../../intern/utfconv
- )
+if(WIN32)
+ if(WITH_INPUT_IME)
+ add_definitions(-DWITH_INPUT_IME)
+ endif()
endif()
if(WITH_COMPOSITOR)
diff --git a/source/blender/windowmanager/SConscript b/source/blender/windowmanager/SConscript
index b93192d5067..a6f64f7cdae 100644
--- a/source/blender/windowmanager/SConscript
+++ b/source/blender/windowmanager/SConscript
@@ -65,11 +65,14 @@ if env['WITH_BF_COLLADA']:
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
- incs += ' ../../intern/utfconv'
if env['BF_BUILDINFO']:
defs.append('WITH_BUILDINFO')
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'win64-mingw'):
+ if env['WITH_BF_IME']:
+ defs.append('WITH_INPUT_IME')
+
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index e1cd334637a..d2abfd419d1 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -47,6 +47,7 @@ extern "C" {
#endif
struct bContext;
+struct GHashIterator;
struct IDProperty;
struct wmEvent;
struct wmEventHandler;
@@ -223,12 +224,13 @@ void WM_operator_stack_clear(struct wmWindowManager *wm);
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot);
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet);
-struct GHashIterator *WM_operatortype_iter(void);
+void WM_operatortype_iter(struct GHashIterator *ghi);
void WM_operatortype_append(void (*opfunc)(struct wmOperatorType *));
void WM_operatortype_append_ptr(void (*opfunc)(struct wmOperatorType *, void *), void *userdata);
void WM_operatortype_append_macro_ptr(void (*opfunc)(struct wmOperatorType *, void *), void *userdata);
void WM_operatortype_remove_ptr(struct wmOperatorType *ot);
bool WM_operatortype_remove(const char *idname);
+void WM_operatortype_last_properties_clear_all(void);
struct wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag);
struct wmOperatorTypeMacro *WM_operatortype_macro_define(struct wmOperatorType *ot, const char *idname);
@@ -266,6 +268,7 @@ void WM_operator_properties_select_action_simple(struct wmOperatorType *ot, int
bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
wmOperator *WM_operator_last_redo(const struct bContext *C);
+ID *WM_operator_drop_load_path(struct bContext *C, struct wmOperator *op, const short idcode);
bool WM_operator_last_properties_init(struct wmOperator *op);
bool WM_operator_last_properties_store(struct wmOperator *op);
@@ -395,6 +398,7 @@ enum {
WM_JOB_TYPE_CLIP_SOLVE_CAMERA,
WM_JOB_TYPE_CLIP_PREFETCH,
WM_JOB_TYPE_SEQ_BUILD_PROXY,
+ WM_JOB_TYPE_SEQ_BUILD_PREVIEW,
/* add as needed, screencast, seq proxy build
* if having hard coded values is a problem */
};
@@ -458,6 +462,10 @@ void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4
float WM_event_tablet_data(const struct wmEvent *event, int *pen_flip, float tilt[2]);
bool WM_event_is_tablet(const struct wmEvent *event);
+#ifdef WITH_INPUT_IME
+bool WM_event_is_ime_switch(const struct wmEvent *event);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index ff252f0fc20..0e3e65d2e21 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -94,12 +94,12 @@
* </pre>
*
* A common way to get the space from the ScrArea:
- * <pre>
- * if (sa->spacetype == SPACE_VIEW3D) {
- * View3D *v3d = sa->spacedata.first;
- * ...
- * }
- * </pre>
+ * \code{.c}
+ * if (sa->spacetype == SPACE_VIEW3D) {
+ * View3D *v3d = sa->spacedata.first;
+ * ...
+ * }
+ * \endcode
*/
#ifdef __cplusplus
@@ -169,7 +169,7 @@ enum {
#define KM_OSKEY2 128
/* KM_MOD_ flags for wmKeyMapItem and wmEvent.alt/shift/oskey/ctrl */
-/* note that KM_ANY and false are used with these defines too */
+/* note that KM_ANY and KM_NOTHING are used with these defines too */
#define KM_MOD_FIRST 1
#define KM_MOD_SECOND 2
@@ -239,6 +239,7 @@ typedef struct wmNotifier {
#define NC_MASK (21<<24)
#define NC_GPENCIL (22<<24)
#define NC_LINESTYLE (23<<24)
+#define NC_CAMERA (24<<24)
/* data type, 256 entries is enough, it can overlap */
#define NOTE_DATA 0x00FF0000
@@ -297,6 +298,7 @@ typedef struct wmNotifier {
#define ND_POINTCACHE (28<<16)
#define ND_PARENT (29<<16)
#define ND_LOD (30<<16)
+#define ND_DRAW_RENDER_VIEWPORT (31<<16) /* for camera & sequencer viewport update, also /w NC_SCENE */
/* NC_MATERIAL Material */
#define ND_SHADING (30<<16)
@@ -324,6 +326,9 @@ typedef struct wmNotifier {
#define ND_NLA_ACTCHANGE (74<<16)
#define ND_FCURVES_ORDER (75<<16)
+ /* NC_GPENCIL */
+#define ND_GPENCIL_EDITMODE (85<<16)
+
/* NC_GEOM Geometry */
/* Mesh, Curve, MetaBall, Armature, .. */
#define ND_SELECT (90<<16)
@@ -554,9 +559,7 @@ typedef struct wmOperatorType {
/* pointer to modal keymap, do not free! */
struct wmKeyMap *modalkeymap;
- /* only used for operators defined with python
- * use to store pointers to python functions */
- void *pyop_data;
+ /* python needs the operator type as well */
int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) ATTR_WARN_UNUSED_RESULT;
/* RNA integration */
@@ -567,6 +570,24 @@ typedef struct wmOperatorType {
} wmOperatorType;
+#ifdef WITH_INPUT_IME
+/* *********** Input Method Editor (IME) *********** */
+
+/* similar to GHOST_TEventImeData */
+typedef struct wmIMEData {
+ size_t result_len, composite_len;
+
+ char *str_result; /* utf8 encoding */
+ char *str_composite; /* utf8 encoding */
+
+ int cursor_pos; /* cursor position in the IME composition. */
+ int sel_start; /* beginning of the selection */
+ int sel_end; /* end of the selection */
+
+ bool is_ime_composing;
+} wmIMEData;
+#endif
+
/* **************** Paint Cursor ******************* */
typedef void (*wmPaintCursorDraw)(struct bContext *C, int, int, void *customdata);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index d05cc572c45..34069e0b873 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -39,8 +39,6 @@
#include "DNA_windowmanager_types.h"
-#include "GHOST_C-api.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -59,7 +57,6 @@
#include "WM_types.h"
#include "wm_window.h"
#include "wm_event_system.h"
-#include "wm_event_types.h"
#include "wm_draw.h"
#include "wm.h"
@@ -155,7 +152,7 @@ void wm_operator_register(bContext *C, wmOperator *op)
int tot;
BLI_addtail(&wm->operators, op);
- tot = BLI_countlist(&wm->operators);
+ tot = BLI_listbase_count(&wm->operators);
while (tot > MAX_OP_REGISTERED) {
wmOperator *opt = wm->operators.first;
@@ -253,15 +250,14 @@ void WM_uilisttype_init(void)
void WM_uilisttype_free(void)
{
- GHashIterator *iter = BLI_ghashIterator_new(uilisttypes_hash);
+ GHashIterator gh_iter;
- for (; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- uiListType *ult = BLI_ghashIterator_getValue(iter);
+ GHASH_ITER (gh_iter, uilisttypes_hash) {
+ uiListType *ult = BLI_ghashIterator_getValue(&gh_iter);
if (ult->ext.free) {
ult->ext.free(ult->ext.data);
}
}
- BLI_ghashIterator_free(iter);
BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN);
uilisttypes_hash = NULL;
@@ -312,15 +308,14 @@ void WM_menutype_init(void)
void WM_menutype_free(void)
{
- GHashIterator *iter = BLI_ghashIterator_new(menutypes_hash);
+ GHashIterator gh_iter;
- for (; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- MenuType *mt = BLI_ghashIterator_getValue(iter);
+ GHASH_ITER (gh_iter, menutypes_hash) {
+ MenuType *mt = BLI_ghashIterator_getValue(&gh_iter);
if (mt->ext.free) {
mt->ext.free(mt->ext.data);
}
}
- BLI_ghashIterator_free(iter);
BLI_ghash_free(menutypes_hash, NULL, MEM_freeN);
menutypes_hash = NULL;
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index e5bba9285b4..cdc3c9eaaff 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -45,10 +45,8 @@
#include "BIF_glutil.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -58,8 +56,6 @@
#include "WM_api.h"
#include "WM_types.h"
#include "wm_event_system.h"
-#include "wm.h"
-
/* ****************************************************** */
@@ -85,7 +81,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
for (dm = dropboxes.first; dm; dm = dm->next)
if (dm->spaceid == spaceid && dm->regionid == regionid)
- if (0 == strncmp(idname, dm->idname, KMAP_MAX_NAME))
+ if (STREQLEN(idname, dm->idname, KMAP_MAX_NAME))
return &dm->dropboxes;
dm = MEM_callocN(sizeof(struct wmDropBoxMap), "dropmap list");
@@ -271,16 +267,11 @@ void wm_drags_check_ops(bContext *C, wmEvent *event)
static void wm_drop_operator_draw(const char *name, int x, int y)
{
- int width = UI_GetStringWidth(name);
- int padding = 4 * UI_DPI_FAC;
-
- glColor4ub(0, 0, 0, 50);
-
- uiSetRoundBox(UI_CNR_ALL | UI_RB_ALPHA);
- uiRoundBox(x, y, x + width + 2 * padding, y + 4 * padding, padding);
-
- glColor4ub(255, 255, 255, 255);
- UI_DrawString(x + padding, y + padding, name);
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ const unsigned char fg[4] = {255, 255, 255, 255};
+ const unsigned char bg[4] = {0, 0, 0, 50};
+
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg);
}
static const char *wm_drag_name(wmDrag *drag)
@@ -288,13 +279,12 @@ static const char *wm_drag_name(wmDrag *drag)
switch (drag->type) {
case WM_DRAG_ID:
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
return id->name + 2;
}
case WM_DRAG_PATH:
- return drag->path;
case WM_DRAG_NAME:
- return (char *)drag->path;
+ return drag->path;
}
return "";
}
@@ -315,6 +305,7 @@ static void drag_rect_minmax(rcti *rect, int x1, int y1, int x2, int y2)
/* if rect set, do not draw */
void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
wmWindowManager *wm = CTX_wm_manager(C);
wmDrag *drag;
const int winsize_y = WM_window_pixels_y(win);
@@ -330,7 +321,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
/* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */
glEnable(GL_BLEND);
for (drag = wm->drags.first; drag; drag = drag->next) {
- int iconsize = 16 * UI_DPI_FAC; /* assumed to be 16 pixels */
+ int iconsize = UI_DPI_ICON_SIZE;
int padding = 4 * UI_DPI_FAC;
/* image or icon */
@@ -366,12 +357,12 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
}
if (rect) {
- int w = UI_GetStringWidth(wm_drag_name(drag));
+ int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag));
drag_rect_minmax(rect, x, y, x + w, y + iconsize);
}
else {
glColor4ub(255, 255, 255, 255);
- UI_DrawString(x, y, wm_drag_name(drag));
+ UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag));
}
/* operator name with roundbox */
@@ -387,14 +378,16 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
else {
x = cursorx - 2 * padding;
- if (cursory + iconsize + iconsize < winsize_y)
- y = cursory + iconsize;
- else
- y = cursory - iconsize - 2 * UI_DPI_FAC;
+ if (cursory + iconsize + iconsize < winsize_y) {
+ y = (cursory + iconsize) + padding;
+ }
+ else {
+ y = (cursory - iconsize) - padding;
+ }
}
if (rect) {
- int w = UI_GetStringWidth(wm_drag_name(drag));
+ int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag));
drag_rect_minmax(rect, x, y, x + w, y + iconsize);
}
else
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 793908ec44b..f1a46826435 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -71,6 +71,8 @@
#include "BIF_gl.h"
+#include "GPU_debug.h"
+
#include "UI_interface.h"
#include "PIL_time.h"
@@ -81,7 +83,6 @@
#include "wm_window.h"
#include "wm_event_system.h"
#include "wm_event_types.h"
-#include "wm_draw.h"
#ifndef NDEBUG
# include "RNA_enum_types.h"
@@ -269,7 +270,7 @@ void wm_event_do_notifiers(bContext *C)
if (note->category == NC_SCREEN) {
if (note->data == ND_SCREENBROWSE) {
/* free popup handlers only [#35434] */
- UI_remove_popup_handlers_all(C, &win->modalhandlers);
+ UI_popup_handlers_remove_all(C, &win->modalhandlers);
ED_screen_set(C, note->reference); // XXX hrms, think this over!
@@ -542,7 +543,7 @@ void WM_event_print(const wmEvent *event)
event->shift, event->ctrl, event->alt, event->oskey, event->keymodifier,
event->x, event->y, event->ascii,
BLI_str_utf8_size(event->utf8_buf), event->utf8_buf,
- event->keymap_idname, (void *)event);
+ event->keymap_idname, (const void *)event);
if (ISNDOF(event->type)) {
const wmNDOFMotionData *ndof = event->customdata;
@@ -621,7 +622,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
{
if (caller_owns_reports == false) { /* popup */
if (op->reports->list.first) {
- /* FIXME, temp setting window, see other call to uiPupMenuReports for why */
+ /* FIXME, temp setting window, see other call to UI_popup_menu_reports for why */
wmWindow *win_prev = CTX_wm_window(C);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *ar_prev = CTX_wm_region(C);
@@ -629,7 +630,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
if (win_prev == NULL)
CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
- uiPupMenuReports(C, op->reports);
+ UI_popup_menu_reports(C, op->reports);
CTX_wm_window_set(C, win_prev);
CTX_wm_area_set(C, area_prev);
@@ -730,7 +731,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons
/* XXX Disabled the repeat check to address part 2 of #31840.
* Carefully checked all calls to wm_operator_exec and WM_operator_repeat, don't see any reason
* why this was needed, but worth to note it in case something turns bad. (mont29) */
- if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)/* && repeat == 0 */)
+ if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED) /* && repeat == 0 */)
wm_operator_reports(C, op, retval, false);
if (retval & OPERATOR_FINISHED) {
@@ -871,7 +872,7 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot,
break;
/* skip invalid properties */
- if (strcmp(RNA_property_identifier(prop), otmacro->idname) == 0) {
+ if (STREQ(RNA_property_identifier(prop), otmacro->idname)) {
wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0);
PointerRNA someptr = RNA_property_pointer_get(properties, prop);
wmOperator *opm = wm_operator_create(wm, otm, &someptr, NULL);
@@ -1663,7 +1664,6 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
int action = WM_HANDLER_CONTINUE;
switch (val) {
- case EVT_FILESELECT_OPEN:
case EVT_FILESELECT_FULL_OPEN:
{
ScrArea *sa;
@@ -1677,9 +1677,16 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
else {
sa = handler->op_area;
}
-
- if (val == EVT_FILESELECT_OPEN) {
+
+ if (sa->full) {
+ /* ensure the first area becomes the file browser, because the second one is the small
+ * top (info-)area which might be too small (in fullscreens we have max two areas) */
+ if (sa->prev) {
+ sa = sa->prev;
+ }
ED_area_newspace(C, sa, SPACE_FILE); /* 'sa' is modified in-place */
+ /* we already had a fullscreen here -> mark new space as a stacked fullscreen */
+ sa->flag |= AREA_FLAG_STACKED_FULLSCREEN;
}
else {
sa = ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */
@@ -1703,24 +1710,16 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
case EVT_FILESELECT_CANCEL:
case EVT_FILESELECT_EXTERNAL_CANCEL:
{
- /* XXX validate area and region? */
- bScreen *screen = CTX_wm_screen(C);
-
/* remlink now, for load file case before removing*/
BLI_remlink(handlers, handler);
-
+
if (val != EVT_FILESELECT_EXTERNAL_CANCEL) {
- if (screen != handler->filescreen) {
- ED_screen_full_prevspace(C, CTX_wm_area(C));
- }
- else {
- ED_area_prevspace(C, CTX_wm_area(C));
- }
+ ED_screen_full_prevspace(C, CTX_wm_area(C));
}
-
+
wm_handler_op_context(C, handler);
- /* needed for uiPupMenuReports */
+ /* needed for UI_popup_menu_reports */
if (val == EVT_FILESELECT_EXEC) {
int retval;
@@ -1752,7 +1751,7 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
BKE_report_print_level_set(handler->op->reports, RPT_WARNING);
- uiPupMenuReports(C, handler->op->reports);
+ UI_popup_menu_reports(C, handler->op->reports);
/* XXX - copied from 'wm_operator_finished()' */
/* add reports to the global list, otherwise they are not seen */
@@ -1955,7 +1954,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
event->customdata = NULL;
event->custom = 0;
- WM_operator_name_call(C, drop->ot->idname, drop->opcontext, drop->ptr);
+ WM_operator_name_call_ptr(C, drop->ot, drop->opcontext, drop->ptr);
action |= WM_HANDLER_BREAK;
/* XXX fileread case */
@@ -2323,6 +2322,14 @@ void wm_event_do_handlers(bContext *C)
}
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ /* after restoring a screen from SCREENMAXIMIZED we have to wait
+ * with the screen handling till the region coordinates are updated */
+ if (win->screen->skip_handling == true) {
+ /* restore for the next iteration of wm_event_do_handlers */
+ win->screen->skip_handling = false;
+ break;
+ }
+
if (wm_event_inside_i(event, &sa->totrct)) {
CTX_wm_area_set(C, sa);
@@ -2417,12 +2424,7 @@ void wm_event_do_handlers(bContext *C)
/* update key configuration after handling events */
WM_keyconfig_update(wm);
- if (G.debug) {
- GLenum error = glGetError();
- if (error != GL_NO_ERROR) {
- printf("GL error: %s\n", gluErrorString(error));
- }
- }
+ GPU_ASSERT_NO_GL_ERRORS("wm_event_do_handlers");
}
/* ********** filesector handling ************ */
@@ -2456,7 +2458,6 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
wmEventHandler *handler, *handlernext;
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- int full = 1; // XXX preset?
/* only allow 1 file selector open per window */
for (handler = win->modalhandlers.first; handler; handler = handlernext) {
@@ -2491,7 +2492,6 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
handler->op = op;
handler->op_area = CTX_wm_area(C);
handler->op_region = CTX_wm_region(C);
- handler->filescreen = CTX_wm_screen(C);
BLI_addhead(&win->modalhandlers, handler);
@@ -2501,7 +2501,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
op->type->check(C, op); /* ignore return value */
}
- WM_event_fileselect_event(wm, op, full ? EVT_FILESELECT_FULL_OPEN : EVT_FILESELECT_OPEN);
+ WM_event_fileselect_event(wm, op, EVT_FILESELECT_FULL_OPEN);
}
#if 0
@@ -3050,6 +3050,13 @@ static void wm_event_add_mousemove(wmWindow *win, const wmEvent *event)
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int UNUSED(time), void *customdata)
{
wmWindow *owin;
+
+ /* Having both, event and evt, can be highly confusing to work with, but is necessary for
+ * our current event system, so let's clear things up a bit:
+ * - data added to event only will be handled immediately, but will not be copied to the next event
+ * - data added to evt only stays, but is handled with the next event -> execution delay
+ * - data added to event and evt stays and is handled immediately
+ */
wmEvent event, *evt = win->eventstate;
/* initialize and copy state (only mouse x y and modifiers) */
@@ -3190,6 +3197,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
case GHOST_kEventKeyUp:
{
GHOST_TEventKeyData *kd = customdata;
+ short keymodifier = KM_NOTHING;
event.type = convert_key(kd->key);
event.ascii = kd->ascii;
memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/
@@ -3230,28 +3238,38 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
}
}
- /* modifiers assign to eventstate, so next event gets the modifer (makes modifier key events work) */
/* assigning both first and second is strange - campbell */
switch (event.type) {
- case LEFTSHIFTKEY: case RIGHTSHIFTKEY:
- evt->shift = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->alt || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.shift = evt->shift = keymodifier;
break;
- case LEFTCTRLKEY: case RIGHTCTRLKEY:
- evt->ctrl = (event.val == KM_PRESS) ?
- ((evt->shift || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->shift || evt->alt || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.ctrl = evt->ctrl = keymodifier;
break;
- case LEFTALTKEY: case RIGHTALTKEY:
- evt->alt = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->shift || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->shift || evt->oskey) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.alt = evt->alt = keymodifier;
break;
case OSKEY:
- evt->oskey = (event.val == KM_PRESS) ?
- ((evt->ctrl || evt->alt || evt->shift) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) :
- false;
+ if (event.val == KM_PRESS) {
+ if (evt->ctrl || evt->alt || evt->shift) keymodifier = (KM_MOD_FIRST | KM_MOD_SECOND);
+ else keymodifier = KM_MOD_FIRST;
+ }
+ event.oskey = evt->oskey = keymodifier;
break;
default:
if (event.val == KM_PRESS && event.keymodifier == 0)
@@ -3374,6 +3392,35 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
break;
}
+#ifdef WITH_INPUT_IME
+ case GHOST_kEventImeCompositionStart:
+ {
+ event.val = KM_PRESS;
+ win->ime_data = customdata;
+ win->ime_data->is_ime_composing = true;
+ event.type = WM_IME_COMPOSITE_START;
+ wm_event_add(win, &event);
+ break;
+ }
+ case GHOST_kEventImeComposition:
+ {
+ event.val = KM_PRESS;
+ event.type = WM_IME_COMPOSITE_EVENT;
+ wm_event_add(win, &event);
+ break;
+ }
+ case GHOST_kEventImeCompositionEnd:
+ {
+ event.val = KM_PRESS;
+ if (win->ime_data) {
+ win->ime_data->is_ime_composing = false;
+ }
+ event.type = WM_IME_COMPOSITE_END;
+ wm_event_add(win, &event);
+ break;
+ }
+#endif /* WITH_INPUT_IME */
+
}
#if 0
@@ -3480,5 +3527,13 @@ bool WM_event_is_tablet(const struct wmEvent *event)
return (event->tablet_data) ? true : false;
}
+#ifdef WITH_INPUT_IME
+/* most os using ctrl/oskey + space to switch ime, avoid added space */
+bool WM_event_is_ime_switch(const struct wmEvent *event)
+{
+ return event->val == KM_PRESS && event->type == SPACEKEY &&
+ (event->ctrl || event->oskey || event->shift || event->alt);
+}
+#endif
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 7865e09cbe2..f5a7ad164d6 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -69,6 +69,7 @@
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
+#include "BKE_appdir.h"
#include "BKE_utildefines.h"
#include "BKE_autoexec.h"
#include "BKE_blender.h"
@@ -96,8 +97,6 @@
#include "ED_view3d.h"
#include "ED_util.h"
-#include "RE_pipeline.h" /* only to report missing engine */
-
#include "GHOST_C-api.h"
#include "GHOST_Path-api.h"
@@ -319,7 +318,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
}
/* update tempdir from user preferences */
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
BKE_userdef_state();
}
@@ -356,7 +355,7 @@ static int wm_read_exotic(Scene *UNUSED(scene), const char *name)
else {
len = gzread(gzfile, header, sizeof(header));
gzclose(gzfile);
- if (len == sizeof(header) && strncmp(header, "BLENDER", 7) == 0) {
+ if (len == sizeof(header) && STREQLEN(header, "BLENDER", 7)) {
retval = BKE_READ_EXOTIC_OK_BLEND;
}
else {
@@ -476,6 +475,8 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
BPY_python_reset(C);
#endif
+ WM_operatortype_last_properties_clear_all();
+
/* important to do before NULL'ing the context */
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
@@ -534,11 +535,13 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
-/* called on startup, (context entirely filled with NULLs) */
-/* or called for 'New File' */
-/* both startup.blend and userpref.blend are checked */
-/* the optional paramater custom_file points to an alterntive startup page */
-/* custom_file can be NULL */
+/**
+ * called on startup, (context entirely filled with NULLs)
+ * or called for 'New File'
+ * both startup.blend and userpref.blend are checked
+ * the optional parameter custom_file points to an alternative startup page
+ * custom_file can be NULL
+ */
int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file)
{
ListBase wmbase;
@@ -560,13 +563,17 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
/* options exclude eachother */
BLI_assert((from_memory && custom_file) == 0);
+ if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) {
+ BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC);
+ }
+
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
UI_view2d_zoom_cache_reset();
G.relbase_valid = 0;
if (!from_memory) {
- const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
if (custom_file) {
BLI_strncpy(startstr, custom_file, FILE_MAX);
@@ -612,7 +619,7 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
if (BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);
}
- BLI_temp_dir_init(U.tempdir);
+ BKE_tempdir_init(U.tempdir);
#ifdef WITH_PYTHON_SECURITY
/* use alternative setting for security nuts
@@ -668,6 +675,8 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
}
#endif
+ WM_operatortype_last_properties_clear_all();
+
/* important to do before NULL'ing the context */
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
@@ -723,7 +732,7 @@ void wm_read_history(void)
struct RecentFile *recent;
const char *line;
int num;
- const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
if (!cfgdir) return;
@@ -760,7 +769,7 @@ static void write_history(void)
return;
/* will be NULL in background mode */
- user_config_dir = BLI_get_folder_create(BLENDER_USER_CONFIG, NULL);
+ user_config_dir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL);
if (!user_config_dir)
return;
@@ -837,11 +846,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, OB_SOLID, false, false, R_ADDSKY, err_out);
+ IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, false, R_ADDSKY, err_out);
+ IB_rect, false, R_ALPHAPREMUL, err_out);
}
if (ibuf) {
@@ -1011,6 +1020,8 @@ int wm_homefile_write_exec(bContext *C, wmOperator *op)
char filepath[FILE_MAX];
int fileflags;
+ BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
+
/* check current window and close it if temp */
if (win && win->screen->temp)
wm_window_close(C, wm, win);
@@ -1018,7 +1029,7 @@ int wm_homefile_write_exec(bContext *C, wmOperator *op)
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
+ BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
printf("trying to save homefile at %s ", filepath);
ED_editors_flush_edits(C, false);
@@ -1035,6 +1046,8 @@ int wm_homefile_write_exec(bContext *C, wmOperator *op)
G.save_over = 0;
+ BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_POST);
+
return OPERATOR_FINISHED;
}
@@ -1047,7 +1060,7 @@ int wm_userpref_write_exec(bContext *C, wmOperator *op)
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
+ BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
printf("trying to save userpref at %s ", filepath);
if (BKE_write_file_userdef(filepath, op->reports) == 0) {
@@ -1064,12 +1077,20 @@ int wm_userpref_write_exec(bContext *C, wmOperator *op)
void wm_autosave_location(char *filepath)
{
- char pidstr[32];
+ const int pid = abs(getpid());
+ char path[1024];
#ifdef WIN32
const char *savedir;
#endif
- BLI_snprintf(pidstr, sizeof(pidstr), "%d.blend", abs(getpid()));
+ if (G.main && G.relbase_valid) {
+ const char *basename = BLI_path_basename(G.main->name);
+ int len = strlen(basename) - 6;
+ BLI_snprintf(path, sizeof(path), "%.*s-%d.blend", len, basename, pid);
+ }
+ else {
+ BLI_snprintf(path, sizeof(path), "%d.blend", pid);
+ }
#ifdef WIN32
/* XXX Need to investigate how to handle default location of '/tmp/'
@@ -1080,14 +1101,14 @@ void wm_autosave_location(char *filepath)
* BLI_make_file_string will create string that has it most likely on C:\
* through get_default_root().
* If there is no C:\tmp autosave fails. */
- if (!BLI_exists(BLI_temp_dir_base())) {
- savedir = BLI_get_folder_create(BLENDER_USER_AUTOSAVE, NULL);
- BLI_make_file_string("/", filepath, savedir, pidstr);
+ if (!BLI_exists(BKE_tempdir_base())) {
+ savedir = BKE_appdir_folder_id_create(BLENDER_USER_AUTOSAVE, NULL);
+ BLI_make_file_string("/", filepath, savedir, path);
return;
}
#endif
- BLI_make_file_string("/", filepath, BLI_temp_dir_base(), pidstr);
+ BLI_make_file_string("/", filepath, BKE_tempdir_base(), path);
}
void WM_autosave_init(wmWindowManager *wm)
@@ -1151,7 +1172,7 @@ void wm_autosave_delete(void)
if (BLI_exists(filename)) {
char str[FILE_MAX];
- BLI_make_file_string("/", str, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ BLI_make_file_string("/", str, BKE_tempdir_base(), BLENDER_QUIT_FILE);
/* if global undo; remove tempsave, otherwise rename */
if (U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, false, false);
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 3e287a3907b..46c3909f7bf 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -49,7 +49,6 @@
#include "WM_types.h"
#include "wm.h"
-#include "wm_event_system.h"
#include "wm_subwindow.h"
#include "wm_draw.h"
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index f762e19c969..9778f1651de 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -40,9 +40,6 @@
#include "MEM_guardedalloc.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
@@ -68,6 +65,7 @@
#include "BKE_report.h"
#include "BKE_addon.h"
+#include "BKE_appdir.h"
#include "BKE_sequencer.h" /* free seq clipboard */
#include "BKE_material.h" /* clear_matcopybuf */
#include "BKE_tracking.h" /* free tracking clipboard */
@@ -98,6 +96,7 @@
#include "wm_window.h"
#include "ED_armature.h"
+#include "ED_gpencil.h"
#include "ED_keyframing.h"
#include "ED_node.h"
#include "ED_render.h"
@@ -110,7 +109,6 @@
#include "BLF_translation.h"
#include "GPU_buffers.h"
-#include "GPU_extensions.h"
#include "GPU_draw.h"
#include "GPU_init_exit.h"
@@ -172,6 +170,8 @@ void WM_init(bContext *C, int argc, const char **argv)
BLF_lang_set(NULL);
+ ED_spacemacros_init();
+
/* note: there is a bug where python needs initializing before loading the
* startup.blend because it may contain PyDrivers. It also needs to be after
* initializing space types and other internal data.
@@ -190,8 +190,6 @@ void WM_init(bContext *C, int argc, const char **argv)
(void)argv; /* unused */
#endif
- ED_spacemacros_init();
-
if (!G.background && !wm_start_with_console)
GHOST_toggleConsole(3);
@@ -219,7 +217,7 @@ void WM_init(bContext *C, int argc, const char **argv)
/* allow a path of "", this is what happens when making a new file */
#if 0
if (G.main->name[0] == 0)
- BLI_make_file_string("/", G.main->name, BLI_getDefaultDocumentFolder(), "untitled.blend");
+ BLI_make_file_string("/", G.main->name, BKE_appdir_folder_default(), "untitled.blend");
#endif
BLI_strncpy(G.lib, G.main->name, FILE_MAX);
@@ -414,7 +412,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
bool has_edited;
int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY);
- BLI_make_file_string("/", filename, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ BLI_make_file_string("/", filename, BKE_tempdir_base(), BLENDER_QUIT_FILE);
has_edited = ED_editors_flush_edits(C, false);
@@ -478,6 +476,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
free_anim_copybuf();
free_anim_drivers_copybuf();
free_fmodifiers_copybuf();
+ ED_gpencil_strokes_copybuf_free();
ED_clipboard_posebuf_free();
BKE_node_clipboard_clear();
@@ -538,12 +537,15 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLI_threadapi_exit();
if (MEM_get_memory_blocks_in_use() != 0) {
- printf("Error: Not freed memory blocks: %d\n", MEM_get_memory_blocks_in_use());
+ size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use();
+ printf("Error: Not freed memory blocks: %d, total unfreed memory %f MB\n",
+ MEM_get_memory_blocks_in_use(),
+ (double)mem_in_use / 1024 / 1024);
MEM_printmemlist();
}
wm_autosave_delete();
- BLI_temp_dir_session_purge();
+ BKE_tempdir_session_purge();
}
void WM_exit(bContext *C)
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 74c504050ae..6bc858e861a 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -45,8 +45,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_window.h"
-#include "wm_event_system.h"
#include "wm_event_types.h"
#include "wm.h"
@@ -630,17 +628,22 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
}
}
- /* on file load 'winactive' can be NULL, possibly it should not happen but for now do a NULL check - campbell */
- if (wm->winactive) {
- /* if there are running jobs, set the global progress indicator */
- if (jobs_progress > 0) {
- float progress = total_progress / (float)jobs_progress;
- WM_progress_set(wm->winactive, progress);
- }
- else {
- WM_progress_clear(wm->winactive);
- }
+
+ /* if there are running jobs, set the global progress indicator */
+ if (jobs_progress > 0) {
+ wmWindow *win;
+ float progress = total_progress / (float)jobs_progress;
+
+ for (win = wm->windows.first; win; win = win->next)
+ WM_progress_set(win, progress);
}
+ else {
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next)
+ WM_progress_clear(win);
+ }
+
}
bool WM_jobs_has_running(wmWindowManager *wm)
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index ff90de4b3c6..82e46c1b333 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -56,7 +56,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "wm_window.h"
#include "wm_event_system.h"
#include "wm_event_types.h"
@@ -146,21 +145,15 @@ static void wm_keyconfig_properties_update_ot(ListBase *km_lb)
}
}
-static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
+static bool wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
{
- if (strcmp(a->idname, b->idname) != 0)
- return 0;
-
- if (!RNA_struct_equals(a->ptr, b->ptr, RNA_EQ_UNSET_MATCH_NONE))
- return 0;
-
- if ((a->flag & KMI_INACTIVE) != (b->flag & KMI_INACTIVE))
- return 0;
-
- return (a->propvalue == b->propvalue);
+ return (STREQ(a->idname, b->idname) &&
+ RNA_struct_equals(a->ptr, b->ptr, RNA_EQ_UNSET_MATCH_NONE) &&
+ (a->flag & KMI_INACTIVE) == (b->flag & KMI_INACTIVE) &&
+ a->propvalue == b->propvalue);
}
-static int wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
+static bool wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
{
return (wm_keymap_item_equals_result(a, b) &&
a->type == b->type &&
@@ -267,7 +260,7 @@ wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
{
if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) {
- if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) {
+ if (STREQLEN(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr))) {
BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
WM_keyconfig_update_tag(NULL, NULL);
}
@@ -422,7 +415,7 @@ wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int ty
wmKeyMapItem *kmi;
for (kmi = keymap->items.first; kmi; kmi = kmi->next)
- if (strncmp(kmi->idname, idname, OP_MAX_TYPENAME) == 0)
+ if (STREQLEN(kmi->idname, idname, OP_MAX_TYPENAME))
break;
if (kmi == NULL) {
kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
@@ -729,7 +722,7 @@ wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int
for (km = lb->first; km; km = km->next)
if (km->spaceid == spaceid && km->regionid == regionid)
- if (0 == strncmp(idname, km->idname, KMAP_MAX_NAME))
+ if (STREQLEN(idname, km->idname, KMAP_MAX_NAME))
return km;
return NULL;
@@ -788,7 +781,7 @@ wmKeyMap *WM_modalkeymap_get(wmKeyConfig *keyconf, const char *idname)
for (km = keyconf->keymaps.first; km; km = km->next)
if (km->flag & KEYMAP_MODAL)
- if (0 == strncmp(idname, km->idname, KMAP_MAX_NAME))
+ if (STREQLEN(idname, km->idname, KMAP_MAX_NAME))
break;
return km;
@@ -953,18 +946,17 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(
if (kmi->flag & KMI_INACTIVE)
continue;
- if (strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) {
+ if (STREQ(kmi->idname, opname) && WM_key_event_string(kmi->type)[0]) {
if (is_hotkey) {
if (!ISHOTKEY(kmi->type))
continue;
}
if (properties) {
-
/* example of debugging keymaps */
#if 0
if (kmi->ptr) {
- if (strcmp("MESH_OT_rip_move", opname) == 0) {
+ if (STREQ("MESH_OT_rip_move", opname)) {
printf("OPERATOR\n");
IDP_spit(properties);
printf("KEYMAP\n");
@@ -977,6 +969,39 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(
if (keymap_r) *keymap_r = keymap;
return kmi;
}
+ /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
+ else if (G.debug & G_DEBUG_WM) {
+ if (is_strict && kmi->ptr) {
+ wmOperatorType *ot = WM_operatortype_find(opname, true);
+ if (ot) {
+ /* make a copy of the properties and set unset ones to their default values. */
+ PointerRNA opptr;
+ IDProperty *properties_default = IDP_CopyProperty(kmi->ptr->data);
+
+ RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
+ WM_operator_properties_default(&opptr, true);
+
+ if (IDP_EqualsProperties_ex(properties, properties_default, is_strict)) {
+ char kmi_str[128];
+ WM_keymap_item_to_string(kmi, kmi_str, sizeof(kmi_str));
+ /* Note gievn properties could come from other things than menu entry... */
+ printf("%s: Some set values in menu entry match default op values, "
+ "this might not be desired!\n", opname);
+ printf("\tkm: '%s', kmi: '%s'\n", keymap->idname, kmi_str);
+#ifndef NDEBUG
+ printf("OPERATOR\n");
+ IDP_spit(properties);
+ printf("KEYMAP\n");
+ IDP_spit(kmi->ptr->data);
+#endif
+ printf("\n");
+ }
+
+ IDP_FreeProperty(properties_default);
+ MEM_freeN(properties_default);
+ }
+ }
+ }
}
else {
if (keymap_r) *keymap_r = keymap;
@@ -1043,33 +1068,83 @@ static wmKeyMapItem *wm_keymap_item_find_props(
static wmKeyMapItem *wm_keymap_item_find(
const bContext *C, const char *opname, int opcontext,
- IDProperty *properties, const bool is_hotkey, const bool is_strict, wmKeyMap **keymap_r)
+ IDProperty *properties, const bool is_hotkey, bool is_strict, wmKeyMap **keymap_r)
{
- wmKeyMapItem *found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+ wmKeyMapItem *found;
+ /* XXX Hack! Macro operators in menu entry have their whole props defined, which is not the case for
+ * relevant keymap entries. Could be good to check and harmonize this, but for now always
+ * compare non-strict in this case.
+ */
+ wmOperatorType *ot = WM_operatortype_find(opname, true);
+ if (ot) {
+ is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0);
+ }
+
+ found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
+
+ /* This block is *only* useful in one case: when op uses an enum menu in its prop member
+ * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle,
+ * since now any enum prop may be used in UI (specified by name), ot->prop is not so much used...
+ * Otherwise:
+ * * If non-strict, unset properties always match set ones in IDP_EqualsProperties_ex.
+ * * If strict, unset properties never match set ones in IDP_EqualsProperties_ex,
+ * and we do not want that to change (else we get things like T41757)!
+ * ...so in either case, re-running a comparison with unset props set to default is useless.
+ */
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 */
+ if (ot && ot->prop) { /* XXX Shall we also check ot->prop is actually an enum? */
+ /* make a copy of the properties and unset the 'ot->prop' one if set. */
PointerRNA opptr;
- IDProperty *properties_default = IDP_CopyProperty(properties);
+ IDProperty *properties_temp = IDP_CopyProperty(properties);
- RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
+ RNA_pointer_create(NULL, ot->srna, properties_temp, &opptr);
- if (WM_operator_properties_default(&opptr, true) ||
- (!is_strict && ot->prop && RNA_property_is_set(&opptr, ot->prop)))
- {
- /* for operator that has enum menu, unset it so it always matches */
- if (!is_strict && ot->prop) {
- RNA_property_unset(&opptr, ot->prop);
- }
+ if (RNA_property_is_set(&opptr, ot->prop)) {
+ /* for operator that has enum menu, unset it so its value does not affect comparison result */
+ RNA_property_unset(&opptr, ot->prop);
- found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, false, is_hotkey, keymap_r);
+ found = wm_keymap_item_find_props(C, opname, opcontext, properties_temp,
+ is_strict, is_hotkey, keymap_r);
}
- IDP_FreeProperty(properties_default);
- MEM_freeN(properties_default);
+ IDP_FreeProperty(properties_temp);
+ MEM_freeN(properties_temp);
+ }
+ }
+
+ /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
+ if (G.debug & G_DEBUG_WM) {
+ if (!found && is_strict && properties) {
+ wmKeyMap *km;
+ wmKeyMapItem *kmi;
+ if (ot) {
+ /* make a copy of the properties and set unset ones to their default values. */
+ PointerRNA opptr;
+ IDProperty *properties_default = IDP_CopyProperty(properties);
+
+ RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
+ WM_operator_properties_default(&opptr, true);
+
+ kmi = wm_keymap_item_find_props(C, opname, opcontext, properties_default, is_strict, is_hotkey, &km);
+ if (kmi) {
+ char kmi_str[128];
+ WM_keymap_item_to_string(kmi, kmi_str, sizeof(kmi_str));
+ printf("%s: Some set values in keymap entry match default op values, "
+ "this might not be desired!\n", opname);
+ printf("\tkm: '%s', kmi: '%s'\n", km->idname, kmi_str);
+#ifndef NDEBUG
+ printf("OPERATOR\n");
+ IDP_spit(properties);
+ printf("KEYMAP\n");
+ IDP_spit(kmi->ptr->data);
+#endif
+ printf("\n");
+ }
+
+ IDP_FreeProperty(properties_default);
+ MEM_freeN(properties_default);
+ }
}
}
@@ -1354,7 +1429,7 @@ void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapIt
if (orig) {
/* restore to original */
- if (strcmp(orig->idname, kmi->idname) != 0) {
+ if (!STREQ(orig->idname, kmi->idname)) {
BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname));
WM_keymap_properties_reset(kmi, NULL);
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 68aad2dbda6..6f9646f35a1 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -38,8 +38,11 @@
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
+#include <errno.h>
-#include "GHOST_C-api.h"
+#ifdef WIN32
+# include "GHOST_C-api.h"
+#endif
#include "MEM_guardedalloc.h"
@@ -58,12 +61,14 @@
#include "BLI_blenlib.h"
#include "BLI_dial.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLO_readfile.h"
+#include "BKE_appdir.h"
#include "BKE_autoexec.h"
#include "BKE_blender.h"
#include "BKE_brush.h"
@@ -72,12 +77,14 @@
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h" /* BKE_ST_MAXNAME */
+#include "BKE_unit.h"
#include "BKE_utildefines.h"
#include "BKE_idcode.h"
@@ -90,15 +97,19 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "ED_numinput.h"
#include "ED_screen.h"
#include "ED_util.h"
#include "ED_view3d.h"
+#include "GPU_material.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "WM_api.h"
@@ -147,9 +158,9 @@ wmOperatorType *WM_operatortype_find(const char *idname, bool quiet)
}
/* caller must free */
-GHashIterator *WM_operatortype_iter(void)
+void WM_operatortype_iter(GHashIterator *ghi)
{
- return BLI_ghashIterator_new(global_ops_hash);
+ BLI_ghashIterator_init(ghi, global_ops_hash);
}
/* all ops in 1 list (for time being... needs evaluation later) */
@@ -494,6 +505,27 @@ bool WM_operatortype_remove(const char *idname)
return true;
}
+/**
+ * Remove memory of all previously executed tools.
+ */
+void WM_operatortype_last_properties_clear_all(void)
+{
+ GHashIterator iter;
+
+ for (WM_operatortype_iter(&iter);
+ (!BLI_ghashIterator_done(&iter));
+ (BLI_ghashIterator_step(&iter)))
+ {
+ wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
+
+ if (ot->last_properties) {
+ IDP_FreeProperty(ot->last_properties);
+ MEM_freeN(ot->last_properties);
+ ot->last_properties = NULL;
+ }
+ }
+}
+
/* SOME_OT_op -> some.op */
void WM_operator_py_idname(char *to, const char *from)
{
@@ -1052,12 +1084,13 @@ int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
return retval;
}
else {
- pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
/* set this so the default execution context is the same as submenus */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
uiItemsFullEnumO(layout, op->type->idname, RNA_property_identifier(prop), op->ptr->data, WM_OP_EXEC_REGION_WIN, 0);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
+ return OPERATOR_INTERFACE;
}
return OPERATOR_CANCELLED;
@@ -1074,19 +1107,19 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
uiBut *but;
wmOperator *op = (wmOperator *)arg_op;
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
#if 0 /* ok, this isn't so easy... */
- uiDefBut(block, LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, uiSearchBoxWidth(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
#endif
but = uiDefSearchButO_ptr(block, op->type, op->ptr->data, search, 0, ICON_VIEWZOOM, sizeof(search),
- 10, 10, uiSearchBoxWidth(), UI_UNIT_Y, 0, 0, "");
+ 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, 0, 0, "");
/* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
- uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
+ UI_block_bounds_set_popup(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
@@ -1101,8 +1134,8 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPupBlock(C, wm_enum_search_menu, op);
- return OPERATOR_CANCELLED;
+ UI_popup_block_invoke(C, wm_enum_search_menu, op);
+ return OPERATOR_INTERFACE;
}
/* Can't be used as an invoke directly, needs message arg (can be NULL) */
@@ -1119,12 +1152,12 @@ int WM_operator_confirm_message_ex(bContext *C, wmOperator *op,
else
properties = NULL;
- pup = uiPupMenuBegin(C, title, icon);
- layout = uiPupMenuLayout(pup);
+ pup = UI_popup_menu_begin(C, title, icon);
+ layout = UI_popup_menu_layout(pup);
uiItemFullO_ptr(layout, op->type, message, ICON_NONE, properties, WM_OP_EXEC_REGION_WIN, 0);
- uiPupMenuEnd(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
@@ -1156,7 +1189,7 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFor
/* dont NULL check prop, this can only run on ops with a 'filepath' */
prop = RNA_struct_find_property(op->ptr, "filepath");
RNA_property_string_get(op->ptr, prop, filepath);
- if (BKE_add_image_extension(filepath, im_format)) {
+ if (BKE_image_path_ensure_ext_from_imformat(filepath, im_format)) {
RNA_property_string_set(op->ptr, prop, filepath);
/* note, we could check for and update 'filename' here,
* but so far nothing needs this. */
@@ -1194,31 +1227,32 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type,
if (action == FILE_SAVE) {
/* note, this is only used to check if we should highlight the filename area red when the
* filepath is an existing file. */
- prop = RNA_def_boolean(ot->srna, "check_existing", 1, "Check Existing", "Check and warn on overwriting existing files");
+ prop = RNA_def_boolean(ot->srna, "check_existing", true, "Check Existing",
+ "Check and warn on overwriting existing files");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
- prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & BLENDERFILE), "Filter .blend files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & FILE_TYPE_BLENDER) != 0, "Filter .blend files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & BLENDERFILE_BACKUP), "Filter .blend files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & FILE_TYPE_BLENDER_BACKUP) != 0, "Filter .blend files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_image", (filter & IMAGEFILE), "Filter image files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_image", (filter & FILE_TYPE_IMAGE) != 0, "Filter image files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & MOVIEFILE), "Filter movie files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & FILE_TYPE_MOVIE) != 0, "Filter movie files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_python", (filter & PYSCRIPTFILE), "Filter python files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_python", (filter & FILE_TYPE_PYSCRIPT) != 0, "Filter python files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_font", (filter & FTFONTFILE), "Filter font files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_font", (filter & FILE_TYPE_FTFONT) != 0, "Filter font files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_sound", (filter & SOUNDFILE), "Filter sound files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_sound", (filter & FILE_TYPE_SOUND) != 0, "Filter sound files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_text", (filter & TEXTFILE), "Filter text files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_text", (filter & FILE_TYPE_TEXT) != 0, "Filter text files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_btx", (filter & BTXFILE), "Filter btx files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_btx", (filter & FILE_TYPE_BTX) != 0, "Filter btx files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & COLLADAFILE), "Filter COLLADA files", "");
+ prop = RNA_def_boolean(ot->srna, "filter_collada", (filter & FILE_TYPE_COLLADA) != 0, "Filter COLLADA files", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FOLDERFILE), "Filter folders", "");
+ prop = RNA_def_boolean(ot->srna, "filter_folder", (filter & FILE_TYPE_FOLDER) != 0, "Filter folders", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna, "filemode", type, FILE_LOADLIB, FILE_SPECIAL,
@@ -1307,7 +1341,7 @@ void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend)
WM_operator_properties_border(ot);
if (extend) {
- RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
}
}
@@ -1315,11 +1349,12 @@ void WM_operator_properties_mouse_select(wmOperatorType *ot)
{
PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend",
+ "Extend selection instead of deselecting everything first");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from selection");
+ prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Remove from selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Selection", "Toggle the selection");
+ prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle Selection", "Toggle the selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
@@ -1373,6 +1408,64 @@ wmOperator *WM_operator_last_redo(const bContext *C)
return op;
}
+/**
+ * Use for drag & drop a path or name with operators invoke() function.
+ */
+ID *WM_operator_drop_load_path(struct bContext *C, wmOperator *op, const short idcode)
+{
+ ID *id = NULL;
+ /* check input variables */
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ char path[FILE_MAX];
+ bool exists = false;
+
+ RNA_string_get(op->ptr, "filepath", path);
+
+ errno = 0;
+
+ if (idcode == ID_IM) {
+ id = (ID *)BKE_image_load_exists_ex(path, &exists);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (!id) {
+ BKE_reportf(op->reports, RPT_ERROR, "Cannot read %s '%s': %s",
+ BKE_idcode_to_name(idcode), path,
+ errno ? strerror(errno) : TIP_("unsupported format"));
+ return NULL;
+ }
+
+ if (is_relative_path ) {
+ if (exists == false) {
+ Main *bmain = CTX_data_main(C);
+
+ if (idcode == ID_IM) {
+ BLI_path_rel(((Image *)id)->name, bmain->name);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+ else if (RNA_struct_property_is_set(op->ptr, "name")) {
+ char name[MAX_ID_NAME - 2];
+ RNA_string_get(op->ptr, "name", name);
+ id = BKE_libblock_find_name(idcode, name);
+ if (!id) {
+ BKE_reportf(op->reports, RPT_ERROR, "%s '%s' not found",
+ BKE_idcode_to_name(idcode), name);
+ return NULL;
+ }
+ id_us_plus(id);
+ }
+
+ return id;
+}
+
static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event))
{
wmOperator *op = arg_op;
@@ -1404,19 +1497,19 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
wmOperator *op = arg_op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
int width = 15 * UI_UNIT_X;
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockClearFlag(block, UI_BLOCK_LOOP);
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_disable(block, UI_BLOCK_LOOP);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
/* if register is not enabled, the operator gets freed on OPERATOR_FINISHED
* ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */
assert(op->type->flag & OPTYPE_REGISTER);
- uiBlockSetHandleFunc(block, wm_block_redo_cb, arg_op);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, 0, style);
+ UI_block_func_handle_set(block, wm_block_redo_cb, arg_op);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, 0, style);
if (op == WM_operator_last_redo(C))
if (!WM_operator_check_ui_enabled(C, op->type->name))
@@ -1431,7 +1524,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
}
- uiPopupBoundsBlock(block, 4, 0, 0);
+ UI_block_bounds_set_popup(block, 4, 0, 0);
return block;
}
@@ -1458,7 +1551,7 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
/* in this case, wm_operator_ui_popup_cancel wont run */
MEM_freeN(data);
- uiPupBlockClose(C, block);
+ UI_popup_block_close(C, block);
}
static void dialog_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
@@ -1482,23 +1575,23 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
wmOperator *op = data->op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockClearFlag(block, UI_BLOCK_LOOP);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_disable(block, UI_BLOCK_LOOP);
/* intentionally don't use 'UI_BLOCK_MOVEMOUSE_QUIT', some dialogues have many items
* where quitting by accident is very annoying */
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
- uiBlockSetFunc(block, dialog_check_cb, op, NULL);
+ UI_block_func_set(block, dialog_check_cb, op, NULL);
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
/* clear so the OK button is left alone */
- uiBlockSetFunc(block, NULL, NULL, NULL);
+ UI_block_func_set(block, NULL, NULL, NULL);
/* new column so as not to interfere with custom layouts [#26436] */
{
@@ -1509,12 +1602,12 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
col = uiLayoutColumn(layout, false);
col_block = uiLayoutGetBlock(col);
/* Create OK button, the callback of which will execute op */
- btn = uiDefBut(col_block, BUT, 0, IFACE_("OK"), 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- uiButSetFunc(btn, dialog_exec_cb, data, col_block);
+ btn = uiDefBut(col_block, UI_BTYPE_BUT, 0, IFACE_("OK"), 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_but_func_set(btn, dialog_exec_cb, data, col_block);
}
/* center around the mouse */
- uiPopupBoundsBlock(block, 4, data->width / -2, data->height / 2);
+ UI_block_bounds_set_popup(block, 4, data->width / -2, data->height / 2);
return block;
}
@@ -1525,18 +1618,18 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
wmOperator *op = data->op;
uiBlock *block;
uiLayout *layout;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockClearFlag(block, UI_BLOCK_LOOP);
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_disable(block, UI_BLOCK_LOOP);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
/* since ui is defined the auto-layout args are not used */
uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0);
- uiPopupBoundsBlock(block, 4, 0, 0);
+ UI_block_bounds_set_popup(block, 4, 0, 0);
return block;
}
@@ -1577,14 +1670,14 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
data->width = width;
data->height = height;
data->free_op = true; /* if this runs and gets registered we may want not to free it */
- uiPupBlockEx(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data);
+ UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data);
return OPERATOR_RUNNING_MODAL;
}
/**
* For use by #WM_operator_props_popup_call, #WM_operator_props_popup only.
*
- * \note operator menu needs undo flag enabled , for redo callback */
+ * \note operator menu needs undo flag enabled, for redo callback */
static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
const bool do_call, const bool do_redo)
{
@@ -1607,7 +1700,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
if (!do_redo || !(U.uiflag & USER_GLOBALUNDO))
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y);
- uiPupBlockEx(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
+ UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
if (do_call)
wm_block_redo_cb(C, op, 0);
@@ -1647,7 +1740,7 @@ int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int h
data->free_op = true; /* if this runs and gets registered we may want not to free it */
/* op is not executed until popup OK but is clicked */
- uiPupBlockEx(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data);
+ UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data);
return OPERATOR_RUNNING_MODAL;
}
@@ -1665,7 +1758,7 @@ int WM_operator_redo_popup(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- uiPupBlock(C, wm_block_create_redo, op);
+ UI_popup_block_invoke(C, wm_block_create_redo, op);
return OPERATOR_CANCELLED;
}
@@ -1730,7 +1823,7 @@ static void WM_OT_operator_defaults(wmOperatorType *ot)
static void wm_block_splash_close(bContext *C, void *arg_block, void *UNUSED(arg))
{
- uiPupBlockClose(C, arg_block);
+ UI_popup_block_close(C, arg_block);
}
static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *arg_unused);
@@ -1742,22 +1835,22 @@ static void wm_block_splash_refreshmenu(bContext *UNUSED(C), void *UNUSED(arg_bl
/* ugh, causes crashes in other buttons, disabling for now until
* a better fix */
#if 0
- uiPupBlockClose(C, arg_block);
- uiPupBlock(C, wm_block_create_splash, NULL);
+ UI_popup_block_close(C, arg_block);
+ UI_popup_block_invoke(C, wm_block_create_splash, NULL);
#endif
}
static int wm_resource_check_prev(void)
{
- const char *res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, true);
+ const char *res = BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, true);
// if (res) printf("USER: %s\n", res);
#if 0 /* ignore the local folder */
if (res == NULL) {
/* with a local dir, copying old files isn't useful since local dir get priority for config */
- res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, true);
+ res = BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, true);
}
#endif
@@ -1766,7 +1859,7 @@ static int wm_resource_check_prev(void)
return false;
}
else {
- return (BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, true) != NULL);
+ return (BKE_appdir_folder_id_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, true) != NULL);
}
}
@@ -1775,7 +1868,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
uiBlock *block;
uiBut *but;
uiLayout *layout, *split, *col;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
const struct RecentFile *recent;
int i;
MenuType *mt = WM_menutype_find("USERPREF_MT_splash", true);
@@ -1821,17 +1914,17 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
}
#endif
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
/* note on UI_BLOCK_NO_WIN_CLIP, the window size is not always synchronized
* with the OS when the splash shows, window clipping in this case gives
* ugly results and clipping the splash isn't useful anyway, just disable it [#32938] */
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP);
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP);
/* XXX splash scales with pixelsize, should become widget-units */
- but = uiDefBut(block, BUT_IMAGE, 0, "", 0, 0.5f * U.widget_unit, U.pixelsize * 501, U.pixelsize * 282, ibuf, 0.0, 0.0, 0, 0, ""); /* button owns the imbuf now */
- uiButSetFunc(but, wm_block_splash_close, block, NULL);
- uiBlockSetFunc(block, wm_block_splash_refreshmenu, block, NULL);
+ but = uiDefBut(block, UI_BTYPE_IMAGE, 0, "", 0, 0.5f * U.widget_unit, U.pixelsize * 501, U.pixelsize * 282, ibuf, 0.0, 0.0, 0, 0, ""); /* button owns the imbuf now */
+ UI_but_func_set(but, wm_block_splash_close, block, NULL);
+ UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL);
/* label for 'a' bugfix releases, or 'Release Candidate 1'...
* avoids recreating splash for version updates */
@@ -1849,32 +1942,32 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
int w = 240;
/* hack to have text draw 'text_sel' */
- uiBlockSetEmboss(block, UI_EMBOSSN);
- but = uiDefBut(block, LABEL, 0, version_suffix, x * U.pixelsize, y * U.pixelsize, w * U.pixelsize, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, version_suffix, x * U.pixelsize, y * U.pixelsize, w * U.pixelsize, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
/* XXX, set internal flag - UI_SELECT */
- uiButSetFlag(but, 1);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_but_flag_enable(but, 1);
+ UI_block_emboss_set(block, UI_EMBOSS);
}
#ifdef WITH_BUILDINFO
if (build_commit_timestamp != 0) {
- uiDefBut(block, LABEL, 0, date_buf, U.pixelsize * 494 - date_width, U.pixelsize * 270, date_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, date_buf, U.pixelsize * 494 - date_width, U.pixelsize * 270, date_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
label_delta = 12;
}
- uiDefBut(block, LABEL, 0, hash_buf, U.pixelsize * 494 - hash_width, U.pixelsize * (270 - label_delta), hash_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, hash_buf, U.pixelsize * 494 - hash_width, U.pixelsize * (270 - label_delta), hash_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
if (!STREQ(build_branch, "master")) {
char branch_buf[128] = "\0";
int branch_width;
BLI_snprintf(branch_buf, sizeof(branch_buf), "Branch: %s", build_branch);
branch_width = (int)BLF_width(style->widgetlabel.uifont_id, branch_buf, sizeof(branch_buf)) + U.widget_unit;
- uiDefBut(block, LABEL, 0, branch_buf, U.pixelsize * 494 - branch_width, U.pixelsize * (258 - label_delta), branch_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, branch_buf, U.pixelsize * 494 - branch_width, U.pixelsize * (258 - label_delta), branch_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
}
#endif /* WITH_BUILDINFO */
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.pixelsize * 480, U.pixelsize * 110, 0, style);
+ layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.pixelsize * 480, U.pixelsize * 110, 0, style);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ UI_block_emboss_set(block, UI_EMBOSS);
/* show the splash menu (containing interaction presets), using python */
if (mt) {
Menu menu = {NULL};
@@ -1886,7 +1979,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
// uiItemM(layout, C, "USERPREF_MT_keyconfigs", U.keyconfigstr, ICON_NONE);
}
- uiBlockSetEmboss(block, UI_EMBOSSP);
+ UI_block_emboss_set(block, UI_EMBOSS_PULLDOWN);
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
split = uiLayoutSplit(layout, 0.0f, false);
@@ -1902,7 +1995,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
BLENDER_VERSION / 100, BLENDER_VERSION % 100);
uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", url);
uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url",
- "http://wiki.blender.org/index.php/Doc:2.6/Manual");
+ "http://www.blender.org/manual");
uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org");
if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d"
@@ -1935,14 +2028,22 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
uiItemO(col, NULL, ICON_RECOVER_LAST, "WM_OT_recover_last_session");
uiItemL(col, "", ICON_NONE);
- uiCenteredBoundsBlock(block, 0);
+ mt = WM_menutype_find("USERPREF_MT_splash_footer", false);
+ if (mt) {
+ Menu menu = {NULL};
+ menu.layout = uiLayoutColumn(layout, false);
+ menu.type = mt;
+ mt->draw(C, &menu);
+ }
+
+ UI_block_bounds_set_centered(block, 0);
return block;
}
static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- uiPupBlock(C, wm_block_create_splash, NULL);
+ UI_popup_block_invoke(C, wm_block_create_splash, NULL);
return OPERATOR_FINISHED;
}
@@ -1967,16 +2068,16 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_
uiBlock *block;
uiBut *but;
- block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+ block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, uiSearchBoxWidth(), UI_UNIT_Y, 0, 0, "");
- uiOperatorSearch_But(but);
+ but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, 0, 0, "");
+ UI_but_func_operator_search(but);
/* fake button, it holds space for search items */
- uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
- uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
+ UI_block_bounds_set_popup(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
wm_event_init_from_window(win, &event);
event.type = EVT_BUT_OPEN;
@@ -1995,9 +2096,9 @@ static int wm_search_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPupBlock(C, wm_block_search_menu, op);
+ UI_popup_block_invoke(C, wm_block_search_menu, op);
- return OPERATOR_CANCELLED;
+ return OPERATOR_INTERFACE;
}
/* op->poll */
@@ -2036,9 +2137,7 @@ static int wm_call_menu_exec(bContext *C, wmOperator *op)
char idname[BKE_ST_MAXNAME];
RNA_string_get(op->ptr, "name", idname);
- uiPupMenuInvoke(C, idname, op->reports);
-
- return OPERATOR_CANCELLED;
+ return UI_popup_menu_invoke(C, idname, op->reports);
}
static void WM_OT_call_menu(wmOperatorType *ot)
@@ -2060,9 +2159,7 @@ static int wm_call_pie_menu_invoke(bContext *C, wmOperator *op, const wmEvent *e
char idname[BKE_ST_MAXNAME];
RNA_string_get(op->ptr, "name", idname);
- uiPieMenuInvoke(C, idname, event);
-
- return OPERATOR_CANCELLED;
+ return UI_pie_menu_invoke(C, idname, event);
}
static int wm_call_pie_menu_exec(bContext *C, wmOperator *op)
@@ -2070,9 +2167,7 @@ static int wm_call_pie_menu_exec(bContext *C, wmOperator *op)
char idname[BKE_ST_MAXNAME];
RNA_string_get(op->ptr, "name", idname);
- uiPieMenuInvoke(C, idname, CTX_wm_window(C)->eventstate);
-
- return OPERATOR_CANCELLED;
+ return UI_pie_menu_invoke(C, idname, CTX_wm_window(C)->eventstate);
}
static void WM_OT_call_menu_pie(wmOperatorType *ot)
@@ -2374,7 +2469,7 @@ static void WM_OT_open_mainfile(wmOperatorType *ot)
ot->ui = wm_open_mainfile_ui;
/* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
RNA_def_boolean(ot->srna, "load_ui", true, "Load UI", "Load user interface setup in the .blend file");
@@ -2561,6 +2656,13 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
lib = mainl->curlib;
BLI_assert(lib);
+ if (mainl->versionfile < 250) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Linking or appending from a very old .blend file format (%d.%d), no animation conversion will "
+ "be done! You may want to re-save your lib file with current Blender",
+ mainl->versionfile, mainl->subversionfile);
+ }
+
if (totfiles == 0) {
BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
}
@@ -2590,7 +2692,9 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
/* recreate dependency graph to include new objects */
DAG_scene_relations_rebuild(bmain, scene);
-
+
+ /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */
+ GPU_materials_free();
BLO_blendhandle_close(bh);
/* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
@@ -2634,7 +2738,7 @@ static void WM_OT_link(wmOperatorType *ot)
ot->flag |= OPTYPE_UNDO;
WM_operator_properties_filesel(
- ot, FOLDERFILE | BLENDERFILE, FILE_LOADLIB, FILE_OPENFILE,
+ ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_LOADLIB, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_RELPATH | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY);
@@ -2654,7 +2758,7 @@ static void WM_OT_append(wmOperatorType *ot)
ot->flag |= OPTYPE_UNDO;
WM_operator_properties_filesel(
- ot, FOLDERFILE | BLENDERFILE, FILE_LOADLIB, FILE_OPENFILE,
+ ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_LOADLIB, FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILENAME | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY);
@@ -2667,7 +2771,7 @@ void WM_recover_last_session(bContext *C, ReportList *reports)
{
char filepath[FILE_MAX];
- BLI_make_file_string("/", filepath, BLI_temp_dir_base(), BLENDER_QUIT_FILE);
+ BLI_make_file_string("/", filepath, BKE_tempdir_base(), BLENDER_QUIT_FILE);
/* if reports==NULL, it's called directly without operator, we add a quick check here */
if (reports || BLI_exists(filepath)) {
G.fileflags |= G_FILE_RECOVER;
@@ -2746,7 +2850,7 @@ static void WM_OT_recover_auto_save(wmOperatorType *ot)
ot->exec = wm_recover_auto_save_exec;
ot->invoke = wm_recover_auto_save_invoke;
- WM_operator_properties_filesel(ot, BLENDERFILE, FILE_BLENDER, FILE_OPENFILE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_BLENDER, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_LONGDISPLAY);
}
@@ -2763,9 +2867,9 @@ static void save_set_compress(wmOperator *op)
{
if (!RNA_struct_property_is_set(op->ptr, "compress")) {
if (G.save_over) /* keep flag for existing file */
- RNA_boolean_set(op->ptr, "compress", G.fileflags & G_FILE_COMPRESS);
+ RNA_boolean_set(op->ptr, "compress", (G.fileflags & G_FILE_COMPRESS) != 0);
else /* use userdef for new file */
- RNA_boolean_set(op->ptr, "compress", U.flag & USER_FILECOMPRESS);
+ RNA_boolean_set(op->ptr, "compress", (U.flag & USER_FILECOMPRESS) != 0);
}
}
@@ -2824,6 +2928,8 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
(RNA_struct_find_property(op->ptr, "use_mesh_compat") &&
RNA_boolean_get(op->ptr, "use_mesh_compat")),
G_FILE_MESH_COMPAT);
+#else
+# error "don't remove by accident"
#endif
if (wm_file_write(C, path, fileflags, op->reports) != 0)
@@ -2862,16 +2968,16 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot)
ot->check = blend_save_check;
/* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
- RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file");
- RNA_def_boolean(ot->srna, "relative_remap", 1, "Remap Relative",
+ RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file");
+ RNA_def_boolean(ot->srna, "relative_remap", true, "Remap Relative",
"Remap relative paths when saving in a different directory");
- prop = RNA_def_boolean(ot->srna, "copy", 0, "Save Copy",
+ prop = RNA_def_boolean(ot->srna, "copy", false, "Save Copy",
"Save a copy of the actual working state but does not make saved file active");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
#ifdef USE_BMESH_SAVE_AS_COMPAT
- RNA_def_boolean(ot->srna, "use_mesh_compat", 0, "Legacy Mesh Format",
+ RNA_def_boolean(ot->srna, "use_mesh_compat", false, "Legacy Mesh Format",
"Save using legacy mesh format (no ngons) - WARNING: only saves tris and quads, other ngons will "
"be lost (no implicit triangulation)");
#endif
@@ -2938,10 +3044,11 @@ static void WM_OT_save_mainfile(wmOperatorType *ot)
ot->check = blend_save_check;
/* omit window poll so this can work in background mode */
- WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_SAVE,
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
- RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file");
- RNA_def_boolean(ot->srna, "relative_remap", 0, "Remap Relative", "Remap relative paths when saving in a different directory");
+ RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file");
+ RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative",
+ "Remap relative paths when saving in a different directory");
}
static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
@@ -3064,14 +3171,16 @@ static int border_apply_rect(wmOperator *op)
static int border_apply(bContext *C, wmOperator *op, int gesture_mode)
{
+ PropertyRNA *prop;
+
int retval;
if (!border_apply_rect(op))
return 0;
/* XXX weak; border should be configured for this without reading event types */
- if (RNA_struct_find_property(op->ptr, "gesture_mode")) {
- RNA_int_set(op->ptr, "gesture_mode", gesture_mode);
+ if ((prop = RNA_struct_find_property(op->ptr, "gesture_mode"))) {
+ RNA_property_int_set(op->ptr, prop, gesture_mode);
}
retval = op->type->exec(C, op);
@@ -3391,6 +3500,8 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ PropertyRNA *prop;
+
op->customdata = WM_gesture_new(C, event, WM_GESTURE_LASSO);
/* add modal handler */
@@ -3398,8 +3509,8 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wm_gesture_tag_redraw(C);
- if (RNA_struct_find_property(op->ptr, "cursor")) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
}
return OPERATOR_RUNNING_MODAL;
@@ -3407,6 +3518,8 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ PropertyRNA *prop;
+
op->customdata = WM_gesture_new(C, event, WM_GESTURE_LINES);
/* add modal handler */
@@ -3414,8 +3527,8 @@ int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wm_gesture_tag_redraw(C);
- if (RNA_struct_find_property(op->ptr, "cursor")) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
}
return OPERATOR_RUNNING_MODAL;
@@ -3621,6 +3734,8 @@ static int straightline_apply(bContext *C, wmOperator *op)
int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ PropertyRNA *prop;
+
op->customdata = WM_gesture_new(C, event, WM_GESTURE_STRAIGHTLINE);
/* add modal handler */
@@ -3628,8 +3743,8 @@ int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *e
wm_gesture_tag_redraw(C);
- if (RNA_struct_find_property(op->ptr, "cursor")) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
}
return OPERATOR_RUNNING_MODAL;
@@ -3709,9 +3824,10 @@ void WM_OT_straightline_gesture(wmOperatorType *ot)
/* *********************** radial control ****************** */
-#define WM_RADIAL_CONTROL_DISPLAY_SIZE 200
-#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE 35
+#define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * U.pixelsize)
+#define WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE (35 * U.pixelsize)
#define WM_RADIAL_CONTROL_DISPLAY_WIDTH (WM_RADIAL_CONTROL_DISPLAY_SIZE - WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE)
+#define WM_RADIAL_CONTROL_HEADER_LENGTH 180
#define WM_RADIAL_MAX_STR 6
typedef struct {
@@ -3729,8 +3845,24 @@ typedef struct {
ListBase orig_paintcursors;
bool use_secondary_tex;
void *cursor;
+ NumInput num_input;
} RadialControl;
+static void radial_control_update_header(wmOperator *op, bContext *C)
+{
+ RadialControl *rc = op->customdata;
+ char msg[WM_RADIAL_CONTROL_HEADER_LENGTH];
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+
+ if (sa && hasNumInput(&rc->num_input)) {
+ char num_str[NUM_STR_REP_LEN];
+ outputNumInput(&rc->num_input, num_str, &scene->unit);
+ BLI_snprintf(msg, WM_RADIAL_CONTROL_HEADER_LENGTH, "%s: %s", RNA_property_ui_name(rc->prop), num_str);
+ ED_area_headerprint(sa, msg);
+ }
+}
+
static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event)
{
float d[2] = {0, 0};
@@ -3742,8 +3874,9 @@ static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *e
switch (rc->subtype) {
case PROP_NONE:
case PROP_DISTANCE:
+ case PROP_PERCENTAGE:
case PROP_PIXEL:
- d[0] = rc->initial_value;
+ d[0] = rc->initial_value * U.pixelsize;
break;
case PROP_FACTOR:
d[0] = (1 - rc->initial_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE;
@@ -3837,7 +3970,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
{
RadialControl *rc = customdata;
ARegion *ar = CTX_wm_region(C);
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_style_get();
const uiFontStyle *fstyle = &style->widget;
const int fontid = fstyle->uifont_id;
short fstyle_points = fstyle->points;
@@ -3850,9 +3983,10 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
switch (rc->subtype) {
case PROP_NONE:
case PROP_DISTANCE:
+ case PROP_PERCENTAGE:
case PROP_PIXEL:
- r1 = rc->current_value;
- r2 = rc->initial_value;
+ r1 = rc->current_value * U.pixelsize;
+ r2 = rc->initial_value * U.pixelsize;
tex_radius = r1;
alpha = 0.75;
break;
@@ -3877,11 +4011,6 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
break;
}
- /* adjust for DPI, like BKE_brush_size_get */
- r1 *= U.pixelsize;
- r2 *= U.pixelsize;
- tex_radius *= U.pixelsize;
-
/* Keep cursor in the original place */
x = rc->initial_mouse[0] - ar->winrct.xmin;
y = rc->initial_mouse[1] - ar->winrct.ymin;
@@ -3989,7 +4118,7 @@ static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op,
PropertyType prop_type = RNA_property_type(*r_prop);
if (((flags & RC_PROP_REQUIRE_BOOL) && (prop_type != PROP_BOOLEAN)) ||
- ((flags & RC_PROP_REQUIRE_FLOAT) && prop_type != PROP_FLOAT))
+ ((flags & RC_PROP_REQUIRE_FLOAT) && (prop_type != PROP_FLOAT)))
{
MEM_freeN(str);
BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a float", name);
@@ -4113,14 +4242,21 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
return OPERATOR_CANCELLED;
}
+ /* initialize numerical input */
+ initNumInput(&rc->num_input);
+ rc->num_input.idx_max = 0;
+ rc->num_input.val_flag[0] |= NUM_NO_NEGATIVE;
+ rc->num_input.unit_sys = USER_UNIT_NONE;
+ rc->num_input.unit_type[0] = B_UNIT_LENGTH;
+
/* get subtype of property */
rc->subtype = RNA_property_subtype(rc->prop);
- if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE, PROP_PIXEL)) {
- BKE_report(op->reports, RPT_ERROR, "Property must be a none, distance, a factor, or an angle");
+ if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_PERCENTAGE, PROP_ANGLE, PROP_PIXEL)) {
+ BKE_report(op->reports, RPT_ERROR, "Property must be a none, distance, factor, percentage, angle, or pixel");
MEM_freeN(rc);
return OPERATOR_CANCELLED;
}
-
+
rc->current_value = rc->initial_value;
radial_control_set_initial_mouse(rc, event);
radial_control_set_tex(rc);
@@ -4157,11 +4293,16 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
{
RadialControl *rc = op->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
+ ScrArea *sa = CTX_wm_area(C);
if (rc->dial) {
MEM_freeN(rc->dial);
rc->dial = NULL;
}
+
+ if (sa) {
+ ED_area_headerprint(sa, NULL);
+ }
WM_paint_cursor_end(wm, rc->cursor);
@@ -4185,125 +4326,183 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
float delta[2], ret = OPERATOR_RUNNING_MODAL;
bool snap;
float angle_precision = 0.0f;
+ const bool has_numInput = hasNumInput(&rc->num_input);
+ bool handled = false;
+ float numValue;
/* TODO: fix hardcoded events */
snap = event->ctrl != 0;
- switch (event->type) {
- case MOUSEMOVE:
- if (rc->slow_mode) {
- if (rc->subtype == PROP_ANGLE) {
- float position[2] = {event->x, event->y};
-
- /* calculate the initial angle here first */
- delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
- delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
-
- /* precision angle gets calculated from dial and gets added later */
- angle_precision = -0.1f * BLI_dial_angle(rc->dial, position);
- }
- else {
- delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
- delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
-
- if (rc->zoom_prop) {
- RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- delta[0] /= zoom[0];
- delta[1] /= zoom[1];
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &rc->num_input, event)) {
+ handled = true;
+ applyNumInput(&rc->num_input, &numValue);
+
+ if (rc->subtype == PROP_ANGLE) {
+ numValue = DEG2RADF(numValue);
+ numValue = fmod(numValue, 2.0f * (float)M_PI);
+ if (numValue < 0.0f)
+ numValue += 2.0f * (float)M_PI;
+ }
+
+ CLAMP(numValue, rc->min_value, rc->max_value);
+ new_value = numValue;
+
+ radial_control_set_value(rc, new_value);
+ rc->current_value = new_value;
+ radial_control_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ handled = false;
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ /* canceled; restore original value */
+ radial_control_set_value(rc, rc->initial_value);
+ ret = OPERATOR_CANCELLED;
+ break;
+
+ case LEFTMOUSE:
+ case PADENTER:
+ case RETKEY:
+ /* done; value already set */
+ RNA_property_update(C, &rc->ptr, rc->prop);
+ ret = OPERATOR_FINISHED;
+ break;
+
+ case MOUSEMOVE:
+ if (!has_numInput) {
+ if (rc->slow_mode) {
+ if (rc->subtype == PROP_ANGLE) {
+ float position[2] = {event->x, event->y};
+
+ /* calculate the initial angle here first */
+ delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
+ delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
+
+ /* precision angle gets calculated from dial and gets added later */
+ angle_precision = -0.1f * BLI_dial_angle(rc->dial, position);
+ }
+ else {
+ delta[0] = rc->initial_mouse[0] - rc->slow_mouse[0];
+ delta[1] = rc->initial_mouse[1] - rc->slow_mouse[1];
+
+ if (rc->zoom_prop) {
+ RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = len_v2(delta);
+
+ delta[0] = event->x - rc->slow_mouse[0];
+ delta[1] = event->y - rc->slow_mouse[1];
+
+ if (rc->zoom_prop) {
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = dist + 0.1f * (delta[0] + delta[1]);
+ }
}
-
- dist = len_v2(delta);
-
- delta[0] = event->x - rc->slow_mouse[0];
- delta[1] = event->y - rc->slow_mouse[1];
-
- if (rc->zoom_prop) {
- delta[0] /= zoom[0];
- delta[1] /= zoom[1];
+ else {
+ delta[0] = rc->initial_mouse[0] - event->x;
+ delta[1] = rc->initial_mouse[1] - event->y;
+
+ if (rc->zoom_prop) {
+ RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
+ delta[0] /= zoom[0];
+ delta[1] /= zoom[1];
+ }
+
+ dist = len_v2(delta);
}
-
- dist = dist + 0.1f * (delta[0] + delta[1]);
+
+ /* calculate new value and apply snapping */
+ switch (rc->subtype) {
+ case PROP_NONE:
+ case PROP_DISTANCE:
+ case PROP_PERCENTAGE:
+ case PROP_PIXEL:
+ new_value = dist;
+ if (snap) new_value = ((int)new_value + 5) / 10 * 10;
+ new_value /= U.pixelsize;
+ break;
+ case PROP_FACTOR:
+ new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH;
+ if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
+ break;
+ case PROP_ANGLE:
+ new_value = atan2f(delta[1], delta[0]) + (float)M_PI + angle_precision;
+ new_value = fmod(new_value, 2.0f * (float)M_PI);
+ if (new_value < 0.0f)
+ new_value += 2.0f * (float)M_PI;
+ if (snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10 * 10);
+ break;
+ default:
+ new_value = dist; /* dummy value, should this ever happen? - campbell */
+ break;
+ }
+
+ /* clamp and update */
+ CLAMP(new_value, rc->min_value, rc->max_value);
+ radial_control_set_value(rc, new_value);
+ rc->current_value = new_value;
+ handled = true;
+ break;
}
- }
- else {
- delta[0] = rc->initial_mouse[0] - event->x;
- delta[1] = rc->initial_mouse[1] - event->y;
+ break;
- if (rc->zoom_prop) {
- RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- delta[0] /= zoom[0];
- delta[1] /= zoom[1];
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ {
+ if (event->val == KM_PRESS) {
+ rc->slow_mouse[0] = event->x;
+ rc->slow_mouse[1] = event->y;
+ rc->slow_mode = true;
+ if (rc->subtype == PROP_ANGLE) {
+ float initial_position[2] = {UNPACK2(rc->initial_mouse)};
+ float current_position[2] = {UNPACK2(rc->slow_mouse)};
+ rc->dial = BLI_dial_initialize(initial_position, 0.0f);
+ /* immediately set the position to get a an initial direction */
+ BLI_dial_angle(rc->dial, current_position);
+ }
+ handled = true;
}
-
- dist = len_v2(delta);
+ if (event->val == KM_RELEASE) {
+ rc->slow_mode = false;
+ handled = true;
+ if (rc->dial) {
+ MEM_freeN(rc->dial);
+ rc->dial = NULL;
+ }
+ }
+ break;
}
+ }
- /* calculate new value and apply snapping */
- switch (rc->subtype) {
- case PROP_NONE:
- case PROP_DISTANCE:
- case PROP_PIXEL:
- new_value = dist;
- if (snap) new_value = ((int)new_value + 5) / 10 * 10;
- break;
- case PROP_FACTOR:
- new_value = (WM_RADIAL_CONTROL_DISPLAY_SIZE - dist) / WM_RADIAL_CONTROL_DISPLAY_WIDTH;
- if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f;
- break;
- case PROP_ANGLE:
- new_value = atan2f(delta[1], delta[0]) + M_PI + angle_precision;
- new_value = fmod(new_value, 2.0f * (float)M_PI);
- if (new_value < 0.0f)
- new_value += 2.0f * (float)M_PI;
- if (snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10 * 10);
- break;
- default:
- new_value = dist; /* dummy value, should this ever happen? - campbell */
- break;
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &rc->num_input, event)) {
+ applyNumInput(&rc->num_input, &numValue);
+
+ if (rc->subtype == PROP_ANGLE) {
+ numValue = DEG2RADF(numValue);
+ numValue = fmod(numValue, 2.0f * (float)M_PI);
+ if (numValue < 0.0f)
+ numValue += 2.0f * (float)M_PI;
}
- /* clamp and update */
- CLAMP(new_value, rc->min_value, rc->max_value);
+ CLAMP(numValue, rc->min_value, rc->max_value);
+ new_value = numValue;
+
radial_control_set_value(rc, new_value);
- rc->current_value = new_value;
- break;
-
- case ESCKEY:
- case RIGHTMOUSE:
- /* canceled; restore original value */
- radial_control_set_value(rc, rc->initial_value);
- ret = OPERATOR_CANCELLED;
- break;
-
- case LEFTMOUSE:
- case PADENTER:
- /* done; value already set */
- RNA_property_update(C, &rc->ptr, rc->prop);
- ret = OPERATOR_FINISHED;
- break;
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (event->val == KM_PRESS) {
- rc->slow_mouse[0] = event->x;
- rc->slow_mouse[1] = event->y;
- rc->slow_mode = true;
- if (rc->subtype == PROP_ANGLE) {
- float initial_position[2] = {UNPACK2(rc->initial_mouse)};
- float current_position[2] = {UNPACK2(rc->slow_mouse)};
- rc->dial = BLI_dial_initialize(initial_position, 0.0f);
- /* immediately set the position to get a an initial direction */
- BLI_dial_angle(rc->dial, current_position);
- }
- }
- if (event->val == KM_RELEASE) {
- rc->slow_mode = false;
- if (rc->dial) {
- MEM_freeN(rc->dial);
- rc->dial = NULL;
- }
- }
- break;
+ rc->current_value = new_value;
+ radial_control_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
}
ED_region_tag_redraw(CTX_wm_region(C));
@@ -4343,7 +4542,7 @@ static void WM_OT_radial_control(wmOperatorType *ot)
RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control");
- RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
+ RNA_def_boolean(ot->srna, "secondary_tex", false, "Secondary Texture", "Tweak brush secondary/mask texture");
}
/* ************************** timer for testing ***************** */
@@ -4525,6 +4724,90 @@ static void WM_OT_dependency_relations(wmOperatorType *ot)
ot->exec = dependency_relations_exec;
}
+/* *************************** Mat/tex/etc. previews generation ************* */
+
+typedef struct PreviewsIDEnsureStack {
+ Scene *scene;
+
+ BLI_LINKSTACK_DECLARE(id_stack, ID *);
+} PreviewsIDEnsureStack;
+
+static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
+{
+ BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA));
+
+ /* Only preview non-library datablocks, lib ones do not pertain to this .blend file!
+ * Same goes for ID with no user. */
+ if (!id->lib && (id->us != 0)) {
+ UI_id_icon_render(C, scene, id, false, false);
+ UI_id_icon_render(C, scene, id, true, false);
+ }
+}
+
+static bool previews_id_ensure_callback(void *todo_v, ID **idptr, int UNUSED(cd_flag))
+{
+ PreviewsIDEnsureStack *todo = todo_v;
+ ID *id = *idptr;
+
+ if (id && (id->flag & LIB_DOIT)) {
+ if (ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)) {
+ previews_id_ensure(NULL, todo->scene, id);
+ }
+ id->flag &= ~LIB_DOIT; /* Tag the ID as done in any case. */
+ BLI_LINKSTACK_PUSH(todo->id_stack, id);
+ }
+
+ return true;
+}
+
+static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ ListBase *lb[] = {&bmain->mat, &bmain->tex, &bmain->image, &bmain->world, &bmain->lamp, NULL};
+ PreviewsIDEnsureStack preview_id_stack;
+ Scene *scene;
+ ID *id;
+ int i;
+
+ /* We use LIB_DOIT to check whether we have already handled a given ID or not. */
+ BKE_main_id_flag_all(bmain, LIB_DOIT, true);
+
+ BLI_LINKSTACK_INIT(preview_id_stack.id_stack);
+
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
+ preview_id_stack.scene = scene;
+ id = (ID *)scene;
+
+ do {
+ /* This will loop over all IDs linked by current one, render icons for them if needed,
+ * and add them to 'todo' preview_id_stack. */
+ BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_stack, IDWALK_READONLY);
+ } while ((id = BLI_LINKSTACK_POP(preview_id_stack.id_stack)));
+ }
+
+ BLI_LINKSTACK_FREE(preview_id_stack.id_stack);
+
+ /* Check a last time for ID not used (fake users only, in theory), and
+ * do our best for those, using current scene... */
+ for (i = 0; lb[i]; i++) {
+ for (id = lb[i]->first; id; id = id->next) {
+ previews_id_ensure(C, NULL, id);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void WM_OT_previews_ensure(wmOperatorType *ot)
+{
+ ot->name = "Refresh DataBlock Previews";
+ ot->idname = "WM_OT_previews_ensure";
+ ot->description = "Ensure datablock previews are available and up-to-date "
+ "(to be saved in .blend file, only for some types like materials, textures, etc.)";
+
+ ot->exec = previews_ensure_exec;
+}
+
/* ******************************************************* */
static void operatortype_ghash_free_cb(wmOperatorType *ot)
@@ -4588,6 +4871,7 @@ void wm_operatortype_init(void)
#if defined(WIN32)
WM_operatortype_append(WM_OT_console_toggle);
#endif
+ WM_operatortype_append(WM_OT_previews_ensure);
}
/* circleselect-like modal operators */
@@ -4645,6 +4929,8 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle");
WM_modalkeymap_assign(keymap, "MASK_OT_select_circle");
WM_modalkeymap_assign(keymap, "NODE_OT_select_circle");
+ WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_circle");
+ WM_modalkeymap_assign(keymap, "GRAPH_OT_select_circle");
}
@@ -4741,6 +5027,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_border");
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border"); /* XXX TODO: zoom border should perhaps map rightmouse to zoom out instead of in+cancel */
WM_modalkeymap_assign(keymap, "IMAGE_OT_render_border");
+ WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_border");
}
/* zoom to border modal operators */
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 76add2f9aac..31883cf234c 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -69,8 +69,6 @@
#include "GHOST_C-api.h"
#include "BLF_api.h"
-#include "wm_event_types.h"
-
#include "WM_api.h" /* only for WM_main_playanim */
struct PlayState;
@@ -298,8 +296,8 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
glRasterPos2f(offs_x + (ps->draw_flip[0] ? span_x : 0.0f),
offs_y + (ps->draw_flip[1] ? span_y : 0.0f));
- glPixelZoom(ps->zoom * ps->draw_flip[0] ? -1.0f : 1.0f,
- ps->zoom * ps->draw_flip[1] ? -1.0f : 1.0f);
+ glPixelZoom(ps->zoom * (ps->draw_flip[0] ? -1.0f : 1.0f),
+ ps->zoom * (ps->draw_flip[1] ? -1.0f : 1.0f));
glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
@@ -850,6 +848,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey)
{
+ GHOST_GLSettings glsettings = {0};
GHOST_TUns32 scr_w, scr_h;
GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h);
@@ -862,7 +861,7 @@ static void playanim_window_open(const char *title, int posx, int posy, int size
/* could optionally start fullscreen */
GHOST_kWindowStateNormal,
GHOST_kDrawingContextTypeOpenGL,
- false /* no stereo */, false);
+ glsettings);
}
static void playanim_window_zoom(PlayState *ps, const float zoom_offset)
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index e26bcac9b1a..4ce2415e310 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -53,7 +53,6 @@
#include "WM_api.h"
#include "wm_subwindow.h"
-#include "wm_window.h"
/* wmSubWindow stored in wmWindow... but not exposed outside this C file */
/* it seems a bit redundant (area regions can store it too, but we keep it
@@ -368,7 +367,7 @@ static void wmOrtho2_offset(const float x, const float y, const float ofs)
*/
void wmOrtho2_region_pixelspace(const struct ARegion *ar)
{
- wmOrtho2_offset(ar->winx + 1, ar->winy + 1, -GLA_PIXEL_OFS);
+ wmOrtho2_offset(ar->winx, ar->winy, -0.01f);
}
void wmOrtho2_pixelspace(const float x, const float y)
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 46a20d3bf88..4f7e5ab75b3 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -356,6 +356,7 @@ float wm_window_pixelsize(wmWindow *win)
static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wmWindow *win)
{
GHOST_WindowHandle ghostwin;
+ GHOST_GLSettings glSettings = {0};
static int multisamples = -1;
int scr_w, scr_h, posy;
@@ -363,7 +364,12 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wm
* mix it, either all windows have it, or none (tested in OSX opengl) */
if (multisamples == -1)
multisamples = U.ogl_multisamples;
-
+
+ glSettings.numOfAASamples = multisamples;
+
+ if (!(U.uiflag2 & USER_OPENGL_NO_WARN_SUPPORT))
+ glSettings.flags |= GHOST_glWarnSupport;
+
wm_get_screensize(&scr_w, &scr_h);
posy = (scr_h - win->posy - win->sizey);
@@ -371,8 +377,7 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wm
win->posx, posy, win->sizex, win->sizey,
(GHOST_TWindowState)win->windowstate,
GHOST_kDrawingContextTypeOpenGL,
- 0 /* no stereo */,
- multisamples /* AA */);
+ glSettings);
if (ghostwin) {
GHOST_RectangleHandle bounds;
@@ -1524,3 +1529,21 @@ bool WM_window_is_fullscreen(wmWindow *win)
return win->windowstate == GHOST_kWindowStateFullScreen;
}
+
+#ifdef WITH_INPUT_IME
+/* note: keep in mind wm_window_IME_begin is also used to reposition the IME window */
+void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complete)
+{
+ BLI_assert(win);
+
+ GHOST_BeginIME(win->ghostwin, x, win->sizey - y, w, h, complete);
+}
+
+void wm_window_IME_end(wmWindow *win)
+{
+ BLI_assert(win && win->ime_data);
+
+ GHOST_EndIME(win->ghostwin);
+ win->ime_data = NULL;
+}
+#endif /* WITH_INPUT_IME */
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index d1a94194108..f89177a82ea 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -65,9 +65,6 @@ typedef struct wmEventHandler {
struct ARegion *ui_region; /* for derived/modal handlers */
struct ARegion *ui_menu; /* for derived/modal handlers */
- /* fileselect handler re-uses modal operator data */
- struct bScreen *filescreen; /* screen it started in, to validate exec */
-
/* drop box handler */
ListBase *dropboxes;
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 7dfc2b52c33..ecc29de0e7d 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -86,10 +86,19 @@ enum {
* paint and drawing tools however will want to handle these. */
INBETWEEN_MOUSEMOVE = 0x0011,
+/* IME event, GHOST_kEventImeCompositionStart in ghost */
+ WM_IME_COMPOSITE_START = 0x0014,
+/* IME event, GHOST_kEventImeComposition in ghost */
+ WM_IME_COMPOSITE_EVENT = 0x0015,
+/* IME event, GHOST_kEventImeCompositionEnd in ghost */
+ WM_IME_COMPOSITE_END = 0x0016,
+
/* *** Start of keyboard codes. *** */
/* standard keyboard.
* XXX from 0x0020 to 0x00ff, and 0x012c to 0x013f for function keys! */
+
+ /* NOTE: these values are saved in keymap files, do not change them but just add new ones */
AKEY = 0x0061, /* 'a' */
BKEY = 0x0062, /* 'b' */
CKEY = 0x0063, /* 'c' */
@@ -299,16 +308,21 @@ enum {
/* Tweak, gestures: 0x500x, 0x501x */
EVT_ACTIONZONE_AREA = 0x5000,
EVT_ACTIONZONE_REGION = 0x5001,
- EVT_ACTIONZONE_FULLSCREEN = 0x5002,
+ EVT_ACTIONZONE_FULLSCREEN = 0x5011,
+
+ /* NOTE: these values are saved in keymap files, do not change them but just add new ones */
+
/* tweak events, for L M R mousebuttons */
- EVT_TWEAK_L = 0x5003,
- EVT_TWEAK_M = 0x5004,
- EVT_TWEAK_R = 0x5005,
+ EVT_TWEAK_L = 0x5002,
+ EVT_TWEAK_M = 0x5003,
+ EVT_TWEAK_R = 0x5004,
/* tweak events for action or select mousebutton */
- EVT_TWEAK_A = 0x5006,
- EVT_TWEAK_S = 0x5007,
+ EVT_TWEAK_A = 0x5005,
+ EVT_TWEAK_S = 0x5006,
EVT_GESTURE = 0x5010,
+ /* 0x5011 is taken, see EVT_ACTIONZONE_FULLSCREEN */
+
/* Misc Blender internals: 0x502x */
EVT_FILESELECT = 0x5020,
EVT_BUT_OPEN = 0x5021,
@@ -355,10 +369,23 @@ enum {
(event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) == false && \
(event_type >= UNKNOWNKEY && event_type <= GRLESSKEY) == false)
+/* internal helpers*/
+#define _VA_IS_EVENT_MOD2(v, a) (CHECK_TYPE_INLINE(v, wmEvent *), \
+ ((v)->a))
+#define _VA_IS_EVENT_MOD3(v, a, b) \
+ (_VA_IS_EVENT_MOD2(v, a) || ((v)->b))
+#define _VA_IS_EVENT_MOD4(v, a, b, c) \
+ (_VA_IS_EVENT_MOD3(v, a, b) || ((v)->c))
+#define _VA_IS_EVENT_MOD5(v, a, b, c, d) \
+ (_VA_IS_EVENT_MOD4(v, a, b, c) || ((v)->d))
+
+/* reusable IS_EVENT_MOD(event, shift, ctrl, alt, oskey), macro */
+#define IS_EVENT_MOD(...) VA_NARGS_CALL_OVERLOAD(_VA_IS_EVENT_MOD, __VA_ARGS__)
/* ********** wmEvent.val ********** */
/* Gestures */
+/* NOTE: these values are saved in keymap files, do not change them but just add new ones */
enum {
/* value of tweaks and line gestures, note, KM_ANY (-1) works for this case too */
EVT_GESTURE_N = 1,
@@ -382,11 +409,10 @@ enum {
/* File select */
enum {
- EVT_FILESELECT_OPEN = 1,
- EVT_FILESELECT_FULL_OPEN = 2,
- EVT_FILESELECT_EXEC = 3,
- EVT_FILESELECT_CANCEL = 4,
- EVT_FILESELECT_EXTERNAL_CANCEL = 5,
+ EVT_FILESELECT_FULL_OPEN = 1,
+ EVT_FILESELECT_EXEC = 2,
+ EVT_FILESELECT_CANCEL = 3,
+ EVT_FILESELECT_EXTERNAL_CANCEL = 4,
};
/* Gesture */
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index 9c9c79d2f54..833234b0f13 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -69,6 +69,11 @@ wmWindow *wm_window_copy (bContext *C, wmWindow *winorig);
void wm_window_testbreak (void);
+#ifdef WITH_INPUT_IME
+void wm_window_IME_begin (wmWindow *win, int x, int y, int w, int h, bool complete);
+void wm_window_IME_end (wmWindow *win);
+#endif
+
/* *************** window operators ************** */
int wm_window_duplicate_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);