Compare commits
141 Commits
curve-node
...
pie-menus
Author | SHA1 | Date | |
---|---|---|---|
30bebec477 | |||
![]() |
1f9657ecc7 | ||
704d710ddc | |||
315d00f76b | |||
f03e2bf47a | |||
d42b85e2d8 | |||
ec6043cd66 | |||
4ce9447b08 | |||
e6e5fd5475 | |||
d73a57698b | |||
c8794563f1 | |||
ba4bc4c58e | |||
8323d88ef8 | |||
2b67bf7510 | |||
863fd8a4fc | |||
8e12efb431 | |||
485f9b88db | |||
c3b87fced2 | |||
4e52fac147 | |||
20cb5f7a3e | |||
5b5c8afb60 | |||
4fe223ab0e | |||
b7ad6b4437 | |||
567e062102 | |||
ed62c38730 | |||
b8801997b2 | |||
b892c8a452 | |||
664dc55305 | |||
0a3f279855 | |||
f52cdcf97c | |||
0ae03b6fa1 | |||
eb20ebe5c2 | |||
d60804b72d | |||
e38cafbe51 | |||
dcf5c52e44 | |||
b844da7750 | |||
5eae52ae96 | |||
759d772408 | |||
517d28ea26 | |||
90906db4fd | |||
0f34796ed9 | |||
6c4bab22db | |||
ba3acdeba0 | |||
7a4cec4c22 | |||
c18e168c09 | |||
9643f78cfe | |||
ba918f2f3d | |||
![]() |
f6fc2f5991 | ||
0b064ce2d4 | |||
da844af3a0 | |||
4a17f1bd62 | |||
65df2781fd | |||
ea3a11fa69 | |||
ab409e645d | |||
bc11096db4 | |||
336ca4e398 | |||
0ed8058347 | |||
06278f03dd | |||
5fd10b15a6 | |||
0d92435a71 | |||
c3f8a08fe4 | |||
b5ce99ddf7 | |||
8359fa245e | |||
cae1d7dab0 | |||
09977b40c4 | |||
45bff7af39 | |||
b192c1da74 | |||
69c0e5f175 | |||
6ac1a646ec | |||
87799657fe | |||
84b7035227 | |||
9241221ff1 | |||
37e9ab73e1 | |||
17d35f9e80 | |||
5529e51a21 | |||
42143ce873 | |||
02c7aa4455 | |||
53a1708860 | |||
8df8824f3a | |||
838c692b93 | |||
97ab366e44 | |||
fba08b9092 | |||
d00f63627b | |||
921b8d6907 | |||
a69ab5509a | |||
47c2250a7e | |||
eade6e7b66 | |||
af8d5d2b24 | |||
285bea9949 | |||
3a969f52ee | |||
795592dc90 | |||
83d713c606 | |||
4c84e89761 | |||
a613ef67df | |||
e748662785 | |||
dc77502804 | |||
6c9216fc49 | |||
6a27e8ed0b | |||
8eb5aa1c35 | |||
3a7899c5eb | |||
cb2aca5833 | |||
6fbd801713 | |||
989bdf6748 | |||
0c7fd1622a | |||
20a570f6b7 | |||
b94eaf041f | |||
a3128b0c95 | |||
74432c94f3 | |||
882e6de2fa | |||
25175306e3 | |||
6d1f76d21b | |||
c5b7841b78 | |||
a209b323dc | |||
9ad2623d0d | |||
4349505c6e | |||
8d838f02e2 | |||
814df8ca34 | |||
bd5aa57c35 | |||
208d21d63f | |||
15c2ed08a6 | |||
69667a7e1f | |||
1709562a04 | |||
8df7e10f30 | |||
c6f727c667 | |||
bc032b9880 | |||
cfb0ae2a17 | |||
929033a13b | |||
1f7a59ce7b | |||
8947cfe30c | |||
e767a7bd44 | |||
d13a194bb7 | |||
95dca123d2 | |||
faf41c6c20 | |||
bbd0f6d37f | |||
1f4337b770 | |||
49e4866312 | |||
e13bc48780 | |||
c3b6b8d86a | |||
a1fbb85c76 | |||
f268dfe88e | |||
39dd7ec5b4 |
@@ -525,6 +525,16 @@ processEvents(
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* when using autorepeat, some keypress events can actually come *after* the
|
||||
* last keyrelease. The next code takes care of that */
|
||||
if (xevent.type == KeyRelease) {
|
||||
m_last_release_keycode = xevent.xkey.keycode;
|
||||
m_last_release_time = xevent.xkey.time;
|
||||
}
|
||||
else if (xevent.type == KeyPress) {
|
||||
if ((xevent.xkey.keycode == m_last_release_keycode) && ((xevent.xkey.time <= m_last_release_time)))
|
||||
continue;
|
||||
}
|
||||
|
||||
processEvent(&xevent);
|
||||
anyProcessed = true;
|
||||
|
@@ -356,6 +356,10 @@ private:
|
||||
* and stop accumulating all events generated before that */
|
||||
Time m_last_warp;
|
||||
|
||||
/* detect autorepeat glitch */
|
||||
unsigned int m_last_release_keycode;
|
||||
Time m_last_release_time;
|
||||
|
||||
/**
|
||||
* Return the ghost window associated with the
|
||||
* X11 window xwind
|
||||
|
@@ -140,6 +140,15 @@ class WindowManager(bpy_types.ID):
|
||||
finally:
|
||||
self.pupmenu_end__internal(popup)
|
||||
|
||||
def popup_menu_pie(self, event, draw_func, title="", icon='NONE'):
|
||||
import bpy
|
||||
pie = self.piemenu_begin__internal(title, icon, event)
|
||||
|
||||
try:
|
||||
draw_func(pie, bpy.context)
|
||||
finally:
|
||||
self.piemenu_end__internal(pie)
|
||||
|
||||
|
||||
class _GenericBone:
|
||||
"""
|
||||
|
@@ -527,7 +527,33 @@ class WM_OT_context_menu_enum(Operator):
|
||||
|
||||
context.window_manager.popup_menu(draw_func=draw_cb, title=prop.name, icon=prop.icon)
|
||||
|
||||
return {'PASS_THROUGH'}
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class WM_OT_context_pie_enum(Operator):
|
||||
bl_idname = "wm.context_pie_enum"
|
||||
bl_label = "Context Enum Pie"
|
||||
bl_options = {'UNDO', 'INTERNAL'}
|
||||
data_path = rna_path_prop
|
||||
|
||||
def invoke(self, context, event):
|
||||
data_path = self.data_path
|
||||
value = context_path_validate(context, data_path)
|
||||
|
||||
if value is Ellipsis:
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
base_path, prop_string = data_path.rsplit(".", 1)
|
||||
value_base = context_path_validate(context, base_path)
|
||||
prop = value_base.bl_rna.properties[prop_string]
|
||||
|
||||
def draw_cb(self, context):
|
||||
layout = self.layout
|
||||
layout.prop(value_base, prop_string, expand=True)
|
||||
|
||||
context.window_manager.popup_menu_pie(draw_func=draw_cb, title=prop.name, icon=prop.icon, event=event)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class WM_OT_context_set_id(Operator):
|
||||
|
@@ -216,6 +216,13 @@ class USERPREF_PT_interface(Panel):
|
||||
sub.prop(view, "open_toplevel_delay", text="Top Level")
|
||||
sub.prop(view, "open_sublevel_delay", text="Sub Level")
|
||||
|
||||
col.separator()
|
||||
col.label(text="Pie Menus:")
|
||||
sub = col.column(align=True)
|
||||
sub.prop(view, "pie_animation_timeout")
|
||||
sub.prop(view, "pie_initial_timeout")
|
||||
sub.prop(view, "pie_menu_radius")
|
||||
sub.prop(view, "pie_menu_threshold")
|
||||
col.separator()
|
||||
col.separator()
|
||||
col.separator()
|
||||
@@ -681,6 +688,9 @@ class USERPREF_PT_theme(Panel):
|
||||
col.label(text="Menu:")
|
||||
self._theme_widget_style(col, ui.wcol_menu)
|
||||
|
||||
col.label(text="Pie Menu:")
|
||||
self._theme_widget_style(col, ui.wcol_pie_menu)
|
||||
|
||||
col.label(text="Pulldown:")
|
||||
self._theme_widget_style(col, ui.wcol_pulldown)
|
||||
|
||||
|
32
release/scripts/templates_py/ui_pie_menu.py
Normal file
32
release/scripts/templates_py/ui_pie_menu.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import bpy
|
||||
from bpy.types import Menu
|
||||
|
||||
# spawn an edit mode selection pie (run while object is in edit mode to get a valid output)
|
||||
|
||||
|
||||
class VIEW3D_PIE_template(Menu):
|
||||
# label is displayed at the center of the pie menu.
|
||||
bl_label = "Select Mode"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
pie = layout.menu_pie()
|
||||
# operator_enum will just spread all available options
|
||||
# for the type enum of the operator on the pie
|
||||
pie.operator_enum("mesh.select_mode", "type")
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(VIEW3D_PIE_template)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(VIEW3D_PIE_template)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
bpy.ops.wm.call_menu_pie(name="VIEW3D_PIE_template")
|
||||
|
@@ -42,7 +42,7 @@ extern "C" {
|
||||
* and keep comment above the defines.
|
||||
* Use STRINGIFY() rather than defining with quotes */
|
||||
#define BLENDER_VERSION 271
|
||||
#define BLENDER_SUBVERSION 3
|
||||
#define BLENDER_SUBVERSION 4
|
||||
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
|
||||
#define BLENDER_MINVERSION 270
|
||||
#define BLENDER_MINSUBVERSION 5
|
||||
|
@@ -805,10 +805,14 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
|
||||
// DIFFUSE
|
||||
// color
|
||||
if (ef->getDiffuse().isColor()) {
|
||||
/* too high intensity can create artefacts (fireflies)
|
||||
So here we take care that intensity is set to 0.8 wherever possible
|
||||
*/
|
||||
col = ef->getDiffuse().getColor();
|
||||
ma->r = col.getRed();
|
||||
ma->g = col.getGreen();
|
||||
ma->b = col.getBlue();
|
||||
ma->ref = max_ffff(col.getRed(), col.getGreen(), col.getBlue(), 0.8);
|
||||
ma->r = col.getRed() / ma->ref;
|
||||
ma->g = col.getGreen() / ma->ref;
|
||||
ma->b = col.getBlue() / ma->ref;
|
||||
}
|
||||
// texture
|
||||
else if (ef->getDiffuse().isTexture()) {
|
||||
|
@@ -35,6 +35,7 @@ struct ARegionType;
|
||||
struct bContext;
|
||||
|
||||
void ED_spacetypes_init(void);
|
||||
void ED_spacemacros_init(void);
|
||||
|
||||
/* the pluginnable API for export to editors */
|
||||
|
||||
|
@@ -102,6 +102,7 @@ typedef struct uiLayout uiLayout;
|
||||
#define UI_EMBOSSN 1 /* Nothing, only icon and/or text */
|
||||
#define UI_EMBOSSP 2 /* Pulldown menu style */
|
||||
#define UI_EMBOSST 3 /* Table */
|
||||
#define UI_EMBOSSR 4 /* Pie Menu */
|
||||
|
||||
/* uiBlock->direction */
|
||||
#define UI_DIRECTION (UI_TOP | UI_DOWN | UI_LEFT | UI_RIGHT)
|
||||
@@ -137,6 +138,7 @@ typedef struct uiLayout uiLayout;
|
||||
/* block->flag bits 14-17 are identical to but->drawflag bits */
|
||||
|
||||
#define UI_BLOCK_LIST_ITEM (1 << 19)
|
||||
#define UI_BLOCK_RADIAL (1 << 20)
|
||||
|
||||
/* uiPopupBlockHandle->menuretval */
|
||||
#define UI_RETURN_CANCEL (1 << 0) /* cancel all menus cascading */
|
||||
@@ -359,6 +361,17 @@ struct uiLayout *uiPupMenuLayout(uiPopupMenu *head);
|
||||
void uiPupMenuReports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL();
|
||||
bool uiPupMenuInvoke(struct bContext *C, const char *idname, struct ReportList *reports) ATTR_NONNULL(1, 2);
|
||||
|
||||
/* Pie menus */
|
||||
typedef struct uiPieMenu uiPieMenu;
|
||||
|
||||
void uiPieMenuInvoke(struct bContext *C, const char *idname, const struct wmEvent *event);
|
||||
void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
|
||||
const char *propname, const struct wmEvent *event);
|
||||
void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path, const struct wmEvent *event);
|
||||
|
||||
struct uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const struct wmEvent *event) ATTR_NONNULL();
|
||||
void uiPieMenuEnd(struct bContext *C, uiPieMenu *pie);
|
||||
struct uiLayout *uiPieMenuLayout(struct uiPieMenu *pie);
|
||||
/* Popup Blocks
|
||||
*
|
||||
* Functions used to create popup blocks. These are like popup menus
|
||||
@@ -416,7 +429,8 @@ typedef enum {
|
||||
UI_BLOCK_BOUNDS_TEXT,
|
||||
UI_BLOCK_BOUNDS_POPUP_MOUSE,
|
||||
UI_BLOCK_BOUNDS_POPUP_MENU,
|
||||
UI_BLOCK_BOUNDS_POPUP_CENTER
|
||||
UI_BLOCK_BOUNDS_POPUP_CENTER,
|
||||
UI_BLOCK_BOUNDS_PIE_CENTER,
|
||||
} eBlockBoundsCalc;
|
||||
|
||||
void uiBoundsBlock(struct uiBlock *block, int addval);
|
||||
@@ -704,7 +718,7 @@ void UI_panel_category_draw_all(struct ARegion *ar, const
|
||||
* as screen/ if ED_KEYMAP_UI is set, or internally in popup functions. */
|
||||
|
||||
void UI_add_region_handlers(struct ListBase *handlers);
|
||||
void UI_add_popup_handlers(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup);
|
||||
void UI_add_popup_handlers(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click);
|
||||
void UI_remove_popup_handlers(struct ListBase *handlers, uiPopupBlockHandle *popup);
|
||||
void UI_remove_popup_handlers_all(struct bContext *C, struct ListBase *handlers);
|
||||
|
||||
@@ -736,6 +750,7 @@ void UI_exit(void);
|
||||
#define UI_LAYOUT_HEADER 1
|
||||
#define UI_LAYOUT_MENU 2
|
||||
#define UI_LAYOUT_TOOLBAR 3
|
||||
#define UI_LAYOUT_PIEMENU 4
|
||||
|
||||
#define UI_UNIT_X ((void)0, U.widget_unit)
|
||||
#define UI_UNIT_Y ((void)0, U.widget_unit)
|
||||
@@ -826,8 +841,8 @@ uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *ui_list, struct Point
|
||||
uiLayout *uiLayoutAbsolute(uiLayout *layout, int align);
|
||||
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align);
|
||||
uiLayout *uiLayoutOverlap(uiLayout *layout);
|
||||
|
||||
uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout);
|
||||
uiLayout *uiLayoutRadial(uiLayout *layout);
|
||||
|
||||
/* templates */
|
||||
void uiTemplateHeader(uiLayout *layout, struct bContext *C);
|
||||
|
@@ -321,6 +321,20 @@ static void ui_centered_bounds_block(wmWindow *window, uiBlock *block)
|
||||
ui_bounds_block(block);
|
||||
|
||||
}
|
||||
|
||||
static void ui_centered_pie_bounds_block(uiBlock *block)
|
||||
{
|
||||
const int xy[2] = {
|
||||
block->pie_data.pie_center_spawned[0],
|
||||
block->pie_data.pie_center_spawned[1]
|
||||
};
|
||||
|
||||
ui_block_translate(block, xy[0], xy[1]);
|
||||
|
||||
/* now recompute bounds and safety */
|
||||
ui_bounds_block(block);
|
||||
}
|
||||
|
||||
static void ui_popup_bounds_block(wmWindow *window, uiBlock *block,
|
||||
eBlockBoundsCalc bounds_calc, const int xy[2])
|
||||
{
|
||||
@@ -1062,6 +1076,42 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
|
||||
return found;
|
||||
}
|
||||
|
||||
/* this goes in a seemingly weird pattern:
|
||||
*
|
||||
* 4
|
||||
* 5 6
|
||||
* 1 2
|
||||
* 7 8
|
||||
* 3
|
||||
*
|
||||
* but it's actually quite logical. It's designed to be 'upwards compatible'
|
||||
* for muscle memory so that the menu item locations are fixed and don't move
|
||||
* as new items are added to the menu later on. It also optimises efficiency -
|
||||
* a radial menu is best kept symmetrical, with as large an angle between
|
||||
* items as possible, so that the gestural mouse movements can be fast and inexact.
|
||||
|
||||
* It starts off with two opposite sides for the first two items
|
||||
* then joined by the one below for the third (this way, even with three items,
|
||||
* the menu seems to still be 'in order' reading left to right). Then the fourth is
|
||||
* added to complete the compass directions. From here, it's just a matter of
|
||||
* subdividing the rest of the angles for the last 4 items.
|
||||
*
|
||||
* --Matt 07/2006
|
||||
*/
|
||||
const char ui_radial_dir_order[8] = {
|
||||
UI_RADIAL_W, UI_RADIAL_E, UI_RADIAL_S, UI_RADIAL_N,
|
||||
UI_RADIAL_NW, UI_RADIAL_NE, UI_RADIAL_SW, UI_RADIAL_SE};
|
||||
|
||||
const char ui_radial_dir_to_numpad[8] = {8, 9, 6, 3, 2, 1, 4, 7};
|
||||
const short ui_radial_dir_to_angle_visual[8] = {90, 40, 0, 320, 270, 220, 180, 140};
|
||||
const short ui_radial_dir_to_angle[8] = {90, 45, 0, 315, 270, 225, 180, 135};
|
||||
|
||||
static void ui_but_pie_direction_string(uiBut *but, char *buf, int size)
|
||||
{
|
||||
BLI_assert(but->pie_dir < ARRAY_SIZE(ui_radial_dir_to_numpad));
|
||||
BLI_snprintf(buf, size, "%d", ui_radial_dir_to_numpad[but->pie_dir]);
|
||||
}
|
||||
|
||||
static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
|
||||
{
|
||||
uiBut *but;
|
||||
@@ -1071,13 +1121,23 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
|
||||
if (block->rect.xmin != block->rect.xmax)
|
||||
return;
|
||||
|
||||
for (but = block->buttons.first; but; but = but->next) {
|
||||
|
||||
if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
|
||||
ui_but_add_shortcut(but, buf, false);
|
||||
if (block->flag & UI_BLOCK_RADIAL) {
|
||||
for (but = block->buttons.first; but; but = but->next) {
|
||||
if (but->pie_dir != UI_RADIAL_NONE) {
|
||||
ui_but_pie_direction_string(but, buf, sizeof(buf));
|
||||
ui_but_add_shortcut(but, buf, false);
|
||||
}
|
||||
}
|
||||
else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
|
||||
ui_but_add_shortcut(but, buf, false);
|
||||
}
|
||||
else {
|
||||
for (but = block->buttons.first; but; but = but->next) {
|
||||
|
||||
if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
|
||||
ui_but_add_shortcut(but, buf, false);
|
||||
}
|
||||
else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
|
||||
ui_but_add_shortcut(but, buf, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1173,6 +1233,9 @@ void uiEndBlock_ex(const bContext *C, uiBlock *block, const int xy[2])
|
||||
case UI_BLOCK_BOUNDS_POPUP_CENTER:
|
||||
ui_centered_bounds_block(window, block);
|
||||
break;
|
||||
case UI_BLOCK_BOUNDS_PIE_CENTER:
|
||||
ui_centered_pie_bounds_block(block);
|
||||
break;
|
||||
|
||||
/* fallback */
|
||||
case UI_BLOCK_BOUNDS_POPUP_MOUSE:
|
||||
@@ -1244,6 +1307,10 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
|
||||
rcti rect;
|
||||
int multisample_enabled;
|
||||
|
||||
/* early exit if cancelled */
|
||||
if ((block->flag & UI_BLOCK_RADIAL) && (block->pie_data.flags & UI_PIE_FINISHED))
|
||||
return;
|
||||
|
||||
/* get menu region or area region */
|
||||
ar = CTX_wm_menu(C);
|
||||
if (!ar)
|
||||
@@ -1279,7 +1346,9 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
|
||||
wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
|
||||
|
||||
/* back */
|
||||
if (block->flag & UI_BLOCK_LOOP)
|
||||
if (block->flag & UI_BLOCK_RADIAL)
|
||||
ui_draw_pie_center(block);
|
||||
else if (block->flag & UI_BLOCK_LOOP)
|
||||
ui_draw_menu_back(&style, block, &rect);
|
||||
else if (block->panel)
|
||||
ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar));
|
||||
@@ -3002,6 +3071,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
|
||||
but->lock = block->lock;
|
||||
but->lockstr = block->lockstr;
|
||||
but->dt = block->dt;
|
||||
but->pie_dir = UI_RADIAL_NONE;
|
||||
|
||||
but->block = block; /* pointer back, used for frontbuffer status, and picker */
|
||||
|
||||
@@ -3028,8 +3098,11 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
|
||||
}
|
||||
}
|
||||
|
||||
if ((block->flag & UI_BLOCK_LOOP) ||
|
||||
ELEM(but->type, MENU, TEX, LABEL, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
|
||||
if (block->flag & UI_BLOCK_RADIAL) {
|
||||
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
|
||||
}
|
||||
else if ((block->flag & UI_BLOCK_LOOP) ||
|
||||
ELEM(but->type, MENU, TEX, LABEL, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
|
||||
{
|
||||
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
|
||||
}
|
||||
|
@@ -116,6 +116,7 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
|
||||
#define BUTTON_TOOLTIP_DELAY 0.500
|
||||
#define BUTTON_FLASH_DELAY 0.020
|
||||
#define MENU_SCROLL_INTERVAL 0.1
|
||||
#define PIE_MENU_INTERVAL 0.01
|
||||
#define BUTTON_AUTO_OPEN_THRESH 0.3
|
||||
#define BUTTON_MOUSE_TOWARDS_THRESH 1.0
|
||||
/* pixels to move the cursor to get out of keyboard navigation */
|
||||
@@ -1238,7 +1239,7 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
|
||||
WM_event_add_ui_handler(C, &data->window->modalhandlers,
|
||||
ui_handler_region_drag_toggle,
|
||||
ui_handler_region_drag_toggle_remove,
|
||||
drag_info);
|
||||
drag_info, false);
|
||||
|
||||
CTX_wm_region_set(C, ar_prev);
|
||||
}
|
||||
@@ -6377,6 +6378,43 @@ static bool ui_but_contains_pt(uiBut *but, float mx, float my)
|
||||
return BLI_rctf_isect_pt(&but->rect, mx, my);
|
||||
}
|
||||
|
||||
static void ui_but_pie_dir__internal(RadialDirection dir, float vec[2], const short angles[8])
|
||||
{
|
||||
float angle;
|
||||
|
||||
BLI_assert(dir != UI_RADIAL_NONE);
|
||||
|
||||
angle = DEG2RADF((float)angles[dir]);
|
||||
vec[0] = cosf(angle);
|
||||
vec[1] = sinf(angle);
|
||||
}
|
||||
|
||||
void ui_but_pie_dir_visual(RadialDirection dir, float vec[2])
|
||||
{
|
||||
ui_but_pie_dir__internal(dir, vec, ui_radial_dir_to_angle_visual);
|
||||
}
|
||||
|
||||
void ui_but_pie_dir(RadialDirection dir, float vec[2])
|
||||
{
|
||||
ui_but_pie_dir__internal(dir, vec, ui_radial_dir_to_angle);
|
||||
}
|
||||
|
||||
static bool ui_but_isect_pie_seg(uiBlock *block, uiBut *but)
|
||||
{
|
||||
const float angle_range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_4 : M_PI_4 / 2.0;
|
||||
float vec[2];
|
||||
|
||||
if (block->pie_data.flags & UI_PIE_INVALID_DIR)
|
||||
return false;
|
||||
|
||||
ui_but_pie_dir(but->pie_dir, vec);
|
||||
|
||||
if (saacos(dot_v2v2(vec, block->pie_data.pie_dir)) < angle_range)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uiBut *ui_but_find_activated(ARegion *ar)
|
||||
{
|
||||
uiBlock *block;
|
||||
@@ -6495,6 +6533,7 @@ static bool ui_mouse_inside_region(ARegion *ar, int x, int y)
|
||||
|
||||
static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
|
||||
{
|
||||
uiBlock *block = but->block;
|
||||
float mx, my;
|
||||
if (!ui_mouse_inside_region(ar, x, y))
|
||||
return false;
|
||||
@@ -6502,10 +6541,16 @@ static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
|
||||
mx = x;
|
||||
my = y;
|
||||
|
||||
ui_window_to_block_fl(ar, but->block, &mx, &my);
|
||||
ui_window_to_block_fl(ar, block, &mx, &my);
|
||||
|
||||
if (!ui_but_contains_pt(but, mx, my))
|
||||
if (but->dt == UI_EMBOSSR) {
|
||||
if (!ui_but_isect_pie_seg(block, but)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!ui_but_contains_pt(but, mx, my)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -6559,7 +6604,13 @@ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, c
|
||||
|
||||
for (but = block->buttons.last; but; but = but->prev) {
|
||||
if (ui_is_but_interactive(but, labeledit)) {
|
||||
if (ui_but_contains_pt(but, mx, my)) {
|
||||
if (but->pie_dir != UI_RADIAL_NONE) {
|
||||
if (ui_but_isect_pie_seg(block, but)) {
|
||||
butover = but;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ui_but_contains_pt(but, mx, my)) {
|
||||
butover = but;
|
||||
break;
|
||||
}
|
||||
@@ -6764,7 +6815,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
|
||||
if (!(but->block->handle && but->block->handle->popup)) {
|
||||
if (button_modal_state(state)) {
|
||||
if (!button_modal_state(data->state))
|
||||
WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data);
|
||||
WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, false);
|
||||
}
|
||||
else {
|
||||
if (button_modal_state(data->state)) {
|
||||
@@ -7914,6 +7965,30 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
|
||||
return retval;
|
||||
}
|
||||
|
||||
void ui_block_calculate_pie_segment(uiBlock *block, const float event_xy[2])
|
||||
{
|
||||
float seg1[2];
|
||||
float seg2[2];
|
||||
float len;
|
||||
|
||||
if (block->pie_data.flags & UI_PIE_INITIAL_DIRECTION) {
|
||||
copy_v2_v2(seg1, block->pie_data.pie_center_init);
|
||||
}
|
||||
else {
|
||||
copy_v2_v2(seg1, block->pie_data.pie_center_spawned);
|
||||
}
|
||||
|
||||
sub_v2_v2v2(seg2, event_xy, seg1);
|
||||
|
||||
len = normalize_v2_v2(block->pie_data.pie_dir, seg2);
|
||||
|
||||
/* ten pixels for now, a bit arbitrary */
|
||||
if (len < U.pie_menu_threshold * U.pixelsize)
|
||||
block->pie_data.flags |= UI_PIE_INVALID_DIR;
|
||||
else
|
||||
block->pie_data.flags &= ~UI_PIE_INVALID_DIR;
|
||||
}
|
||||
|
||||
static int ui_handle_menu_event(
|
||||
bContext *C, const wmEvent *event, uiPopupBlockHandle *menu,
|
||||
int level, const bool is_parent_inside, const bool is_parent_menu, const bool is_floating)
|
||||
@@ -8415,10 +8490,311 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo
|
||||
ui_mouse_motion_towards_reinit(menu, &event->x);
|
||||
}
|
||||
|
||||
if (menu->menuretval)
|
||||
if (menu->menuretval) {
|
||||
/* pie menus should not close but wait for release instead */
|
||||
if ((block->flag & UI_BLOCK_RADIAL) &&
|
||||
!(block->pie_data.flags & UI_PIE_CLICK_STYLE))
|
||||
{
|
||||
menu->menuretval = 0;
|
||||
block->pie_data.flags |= UI_PIE_FINISHED;
|
||||
}
|
||||
|
||||
return WM_UI_HANDLER_CONTINUE;
|
||||
else
|
||||
}
|
||||
else {
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ui_but_pie_menu_supported_apply(uiBut *but)
|
||||
{
|
||||
return (but->type != NUMSLI);
|
||||
}
|
||||
|
||||
static int ui_but_pie_menu_apply(bContext *C, uiPopupBlockHandle *menu, uiBut *but, bool force_close, bool click_style)
|
||||
{
|
||||
int retval = WM_UI_HANDLER_BREAK;
|
||||
|
||||
if (but && ui_but_pie_menu_supported_apply(but)) {
|
||||
if (but->type == MENU) {
|
||||
/* forcing the pie menu to close will not handle menus */
|
||||
if (!force_close) {
|
||||
uiBut *active_but = ui_but_find_activated(menu->region);
|
||||
|
||||
if (active_but) {
|
||||
button_activate_exit(C, active_but, active_but->active, false, false);
|
||||
}
|
||||
|
||||
button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OPEN);
|
||||
return retval;
|
||||
}
|
||||
else {
|
||||
menu->menuretval = UI_RETURN_CANCEL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ui_apply_button(C, but->block, but, but->active, false);
|
||||
button_activate_exit((bContext *)C, but, but->active, false, true);
|
||||
|
||||
if (!(click_style || force_close)) {
|
||||
but->block->pie_data.flags |= UI_PIE_FINISHED;
|
||||
menu->menuretval = 0;
|
||||
}
|
||||
else {
|
||||
menu->menuretval = UI_RETURN_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uiBlock *block = menu->region->uiblocks.first;
|
||||
|
||||
if (!(click_style || force_close)) {
|
||||
block->pie_data.flags |= UI_PIE_FINISHED;
|
||||
}
|
||||
else {
|
||||
menu->menuretval = UI_RETURN_CANCEL;
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(menu->region);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static uiBut *ui_block_pie_dir_activate(uiBlock *block, const wmEvent *event, RadialDirection dir)
|
||||
{
|
||||
uiBut *but;
|
||||
|
||||
if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
|
||||
for (but = block->buttons.first; but; but = but->next) {
|
||||
if (but->pie_dir == dir && !ELEM(but->type, SEPR, SEPRLINE)) {
|
||||
return but;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ui_but_pie_button_activate(bContext *C, uiBut *but, uiPopupBlockHandle *menu, bool is_click_style)
|
||||
{
|
||||
uiBut *active_but;
|
||||
|
||||
if (but == NULL)
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
|
||||
active_but = ui_but_find_activated(menu->region);
|
||||
|
||||
if (active_but)
|
||||
button_activate_exit(C, active_but, active_but->active, false, false);
|
||||
|
||||
button_activate_init(C, menu->region, but, BUTTON_ACTIVATE_OVER);
|
||||
return ui_but_pie_menu_apply(C, menu, but, false, is_click_style);
|
||||
}
|
||||
|
||||
static int ui_handler_pie(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
|
||||
{
|
||||
ARegion *ar;
|
||||
uiBlock *block;
|
||||
uiBut *but;
|
||||
float event_xy[2];
|
||||
double duration;
|
||||
bool is_click_style;
|
||||
|
||||
/* we block all events, this is modal interaction, except for drop events which is described below */
|
||||
int retval = WM_UI_HANDLER_BREAK;
|
||||
|
||||
if (event->type == EVT_DROP) {
|
||||
/* may want to leave this here for later if we support pie ovens */
|
||||
|
||||
retval = WM_UI_HANDLER_CONTINUE;
|
||||
}
|
||||
|
||||
ar = menu->region;
|
||||
block = ar->uiblocks.first;
|
||||
|
||||
is_click_style = (block->pie_data.flags & UI_PIE_CLICK_STYLE);
|
||||
|
||||
if (menu->scrolltimer == NULL) {
|
||||
menu->scrolltimer =
|
||||
WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, PIE_MENU_INTERVAL);
|
||||
menu->scrolltimer->duration = 0.0;
|
||||
}
|
||||
|
||||
duration = menu->scrolltimer->duration;
|
||||
|
||||
if (event->type == TIMER) {
|
||||
if (event->customdata == menu->scrolltimer) {
|
||||
/* deactivate initial direction after a while */
|
||||
if (duration > 0.01 * U.pie_initial_timeout) {
|
||||
block->pie_data.flags &= ~UI_PIE_INITIAL_DIRECTION;
|
||||
}
|
||||
|
||||
/* handle animation */
|
||||
if (!(block->pie_data.flags & UI_PIE_ANIMATION_FINISHED)) {
|
||||
uiBut *but;
|
||||
double final_time = 0.01 * U.pie_animation_timeout;
|
||||
float fac = duration / final_time;
|
||||
float pie_radius = U.pie_menu_radius * UI_DPI_FAC;
|
||||
|
||||
if (fac > 1.0f) {
|
||||
fac = 1.0f;
|
||||
block->pie_data.flags |= UI_PIE_ANIMATION_FINISHED;
|
||||
}
|
||||
|
||||
pie_radius *= fac;
|
||||
|
||||
for (but = block->buttons.first; but; but = but->next) {
|
||||
if (but->pie_dir != UI_RADIAL_NONE) {
|
||||
float dir[2];
|
||||
|
||||
ui_but_pie_dir_visual(but->pie_dir, dir);
|
||||
|
||||
mul_v2_fl(dir, pie_radius );
|
||||
add_v2_v2(dir, block->pie_data.pie_center_spawned);
|
||||
BLI_rctf_recenter(&but->rect, dir[0], dir[1]);
|
||||
}
|
||||
}
|
||||
block->pie_data.alphafac = fac;
|
||||
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event_xy[0] = event->x;
|
||||
event_xy[1] = event->y;
|
||||
|
||||
ui_window_to_block_fl(ar, block, &event_xy[0], &event_xy[1]);
|
||||
|
||||
ui_block_calculate_pie_segment(block, event_xy);
|
||||
|
||||
if (block->pie_data.flags & UI_PIE_FINISHED) {
|
||||
if ((event->type == block->pie_data.event && event->val == KM_RELEASE) ||
|
||||
((event->type == RIGHTMOUSE || event->type == ESCKEY) && (event->val == KM_PRESS)))
|
||||
{
|
||||
menu->menuretval = UI_RETURN_OK;
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(ar);
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
|
||||
if (event->type == block->pie_data.event) {
|
||||
if (event->val != KM_RELEASE) {
|
||||
ui_handle_menu_button(C, event, menu);
|
||||
|
||||
/* why redraw here? It's simple, we are getting many double click events here.
|
||||
* Those operate like mouse move events almost */
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
else {
|
||||
/* distance from initial point */
|
||||
if (len_squared_v2v2(event_xy, block->pie_data.pie_center_init) < PIE_CLICK_THRESHOLD_SQ) {
|
||||
block->pie_data.flags |= UI_PIE_CLICK_STYLE;
|
||||
}
|
||||
else if (!is_click_style) {
|
||||
uiBut *but = ui_but_find_activated(menu->region);
|
||||
|
||||
retval = ui_but_pie_menu_apply(C, menu, but, true, is_click_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* direction from numpad */
|
||||
RadialDirection num_dir = UI_RADIAL_NONE;
|
||||
|
||||
switch (event->type) {
|
||||
case MOUSEMOVE:
|
||||
/* mouse move should always refresh the area for pie menus */
|
||||
ui_handle_menu_button(C, event, menu);
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
|
||||
case LEFTMOUSE:
|
||||
if (event->val == KM_PRESS) {
|
||||
uiBut *but = ui_but_find_activated(menu->region);
|
||||
retval = ui_but_pie_menu_apply(C, menu, but, false, is_click_style);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESCKEY:
|
||||
case RIGHTMOUSE:
|
||||
if (!is_click_style) {
|
||||
block->pie_data.flags |= UI_PIE_FINISHED;
|
||||
menu->menuretval = 0;
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
else
|
||||
menu->menuretval = UI_RETURN_CANCEL;
|
||||
break;
|
||||
|
||||
case AKEY:
|
||||
case BKEY:
|
||||
case CKEY:
|
||||
case DKEY:
|
||||
case EKEY:
|
||||
case FKEY:
|
||||
case GKEY:
|
||||
case HKEY:
|
||||
case IKEY:
|
||||
case JKEY:
|
||||
case KKEY:
|
||||
case LKEY:
|
||||
case MKEY:
|
||||
case NKEY:
|
||||
case OKEY:
|
||||
case PKEY:
|
||||
case QKEY:
|
||||
case RKEY:
|
||||
case SKEY:
|
||||
case TKEY:
|
||||
case UKEY:
|
||||
case VKEY:
|
||||
case WKEY:
|
||||
case XKEY:
|
||||
case YKEY:
|
||||
case ZKEY:
|
||||
{
|
||||
if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
|
||||
(event->shift == 0) &&
|
||||
(event->ctrl == 0) &&
|
||||
(event->oskey == 0))
|
||||
{
|
||||
for (but = block->buttons.first; but; but = but->next) {
|
||||
if (but->menu_key == event->type) {
|
||||
ui_but_pie_button_activate(C, but, menu, is_click_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#define CASE_NUM_TO_DIR(n, d) \
|
||||
case (ZEROKEY + n): case (PAD0 + n): \
|
||||
{ if (num_dir == UI_RADIAL_NONE) num_dir = d; } (void)0
|
||||
|
||||
CASE_NUM_TO_DIR(1, UI_RADIAL_SW);
|
||||
CASE_NUM_TO_DIR(2, UI_RADIAL_S);
|
||||
CASE_NUM_TO_DIR(3, UI_RADIAL_SE);
|
||||
CASE_NUM_TO_DIR(4, UI_RADIAL_W);
|
||||
CASE_NUM_TO_DIR(6, UI_RADIAL_E);
|
||||
CASE_NUM_TO_DIR(7, UI_RADIAL_NW);
|
||||
CASE_NUM_TO_DIR(8, UI_RADIAL_N);
|
||||
CASE_NUM_TO_DIR(9, UI_RADIAL_NE);
|
||||
{
|
||||
but = ui_block_pie_dir_activate(block, event, num_dir);
|
||||
retval = ui_but_pie_button_activate(C, but, menu, is_click_style);
|
||||
break;
|
||||
}
|
||||
#undef CASE_NUM_TO_DIR
|
||||
default:
|
||||
retval = ui_handle_menu_button(C, event, menu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int ui_handle_menus_recursive(
|
||||
@@ -8440,17 +8816,21 @@ static int ui_handle_menus_recursive(
|
||||
uiBlock *block = menu->region->uiblocks.first;
|
||||
const bool is_menu = ui_block_is_menu(block);
|
||||
bool inside = false;
|
||||
/* root pie menus accept the key that spawned them as double click to improve responsiveness */
|
||||
bool do_recursion = (!(block->flag & UI_BLOCK_RADIAL) || event->type != block->pie_data.event);
|
||||
|
||||
if (is_parent_inside == false) {
|
||||
int mx, my;
|
||||
if (do_recursion) {
|
||||
if (is_parent_inside == false) {
|
||||
int mx, my;
|
||||
|
||||
mx = event->x;
|
||||
my = event->y;
|
||||
ui_window_to_block(menu->region, block, &mx, &my);
|
||||
inside = BLI_rctf_isect_pt(&block->rect, mx, my);
|
||||
mx = event->x;
|
||||
my = event->y;
|
||||
ui_window_to_block(menu->region, block, &mx, &my);
|
||||
inside = BLI_rctf_isect_pt(&block->rect, mx, my);
|
||||
}
|
||||
|
||||
retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside, is_menu, false);
|
||||
}
|
||||
|
||||
retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside, is_menu, false);
|
||||
}
|
||||
|
||||
/* now handle events for our own menu */
|
||||
@@ -8483,7 +8863,12 @@ static int ui_handle_menus_recursive(
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating);
|
||||
uiBlock *block = menu->region->uiblocks.first;
|
||||
|
||||
if (block->flag & UI_BLOCK_RADIAL)
|
||||
retval = ui_handler_pie(C, event, menu);
|
||||
else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK)
|
||||
retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8698,12 +9083,12 @@ static void ui_handler_remove_popup(bContext *C, void *userdata)
|
||||
void UI_add_region_handlers(ListBase *handlers)
|
||||
{
|
||||
WM_event_remove_ui_handler(handlers, ui_handler_region, ui_handler_remove_region, NULL, false);
|
||||
WM_event_add_ui_handler(NULL, handlers, ui_handler_region, ui_handler_remove_region, NULL);
|
||||
WM_event_add_ui_handler(NULL, handlers, ui_handler_region, ui_handler_remove_region, NULL, false);
|
||||
}
|
||||
|
||||
void UI_add_popup_handlers(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup)
|
||||
void UI_add_popup_handlers(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click)
|
||||
{
|
||||
WM_event_add_ui_handler(C, handlers, ui_handler_popup, ui_handler_remove_popup, popup);
|
||||
WM_event_add_ui_handler(C, handlers, ui_handler_popup, ui_handler_remove_popup, popup, accept_dbl_click);
|
||||
}
|
||||
|
||||
void UI_remove_popup_handlers(ListBase *handlers, uiPopupBlockHandle *popup)
|
||||
|
@@ -88,6 +88,7 @@ typedef enum {
|
||||
|
||||
UI_WTYPE_PULLDOWN,
|
||||
UI_WTYPE_MENU_ITEM,
|
||||
UI_WTYPE_MENU_ITEM_RADIAL,
|
||||
UI_WTYPE_MENU_BACK,
|
||||
|
||||
/* specials */
|
||||
@@ -121,6 +122,24 @@ enum {
|
||||
/* warn: rest of uiBut->flag in UI_interface.h */
|
||||
};
|
||||
|
||||
/* but->pie_dir */
|
||||
typedef enum RadialDirection {
|
||||
UI_RADIAL_NONE = -1,
|
||||
UI_RADIAL_N = 0,
|
||||
UI_RADIAL_NE = 1,
|
||||
UI_RADIAL_E = 2,
|
||||
UI_RADIAL_SE = 3,
|
||||
UI_RADIAL_S = 4,
|
||||
UI_RADIAL_SW = 5,
|
||||
UI_RADIAL_W = 6,
|
||||
UI_RADIAL_NW = 7,
|
||||
} RadialDirection;
|
||||
|
||||
extern const char ui_radial_dir_order[8];
|
||||
extern const char ui_radial_dir_to_numpad[8];
|
||||
extern const short ui_radial_dir_to_angle_visual[8];
|
||||
extern const short ui_radial_dir_to_angle[8];
|
||||
|
||||
/* internal panel drawing defines */
|
||||
#define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */
|
||||
#define PNL_HEADER (UI_UNIT_Y + 4) /* 24 default */
|
||||
@@ -144,6 +163,19 @@ enum {
|
||||
/* split numbuts by ':' and align l/r */
|
||||
#define USE_NUMBUTS_LR_ALIGN
|
||||
|
||||
/* PieMenuData->flags */
|
||||
enum {
|
||||
UI_PIE_DEGREES_RANGE_LARGE = (1 << 0), /* pie menu item collision is detected at 90 degrees */
|
||||
UI_PIE_INITIAL_DIRECTION = (1 << 1), /* use initial center of pie menu to calculate direction */
|
||||
UI_PIE_3_ITEMS = (1 << 2), /* pie menu has only 3 items, careful when centering */
|
||||
UI_PIE_INVALID_DIR = (1 << 3), /* mouse not far enough from center position */
|
||||
UI_PIE_FINISHED = (1 << 4), /* pie menu finished but we still wait for a release event */
|
||||
UI_PIE_CLICK_STYLE = (1 << 5), /* pie menu changed to click style, click to confirm */
|
||||
UI_PIE_ANIMATION_FINISHED = (1 << 6), /* pie animation finished, do not calculate any more motio */
|
||||
};
|
||||
|
||||
#define PIE_CLICK_THRESHOLD_SQ 50.0f
|
||||
|
||||
typedef struct uiLinkLine { /* only for draw/edit */
|
||||
struct uiLinkLine *next, *prev;
|
||||
struct uiBut *from, *to;
|
||||
@@ -227,6 +259,7 @@ struct uiBut {
|
||||
BIFIconID icon;
|
||||
bool lock;
|
||||
char dt; /* drawtype: UI_EMBOSS, UI_EMBOSSN ... etc, copied from the block */
|
||||
signed char pie_dir; /* direction in a pie menu, used for collision detection (RadialDirection) */
|
||||
char changed; /* could be made into a single flag */
|
||||
unsigned char unit_type; /* so buttons can support unit systems which are not RNA */
|
||||
short modifier_key;
|
||||
@@ -274,6 +307,15 @@ struct uiBut {
|
||||
uiBlock *block;
|
||||
};
|
||||
|
||||
struct PieMenuData {
|
||||
float pie_dir[2];
|
||||
float pie_center_init[2];
|
||||
float pie_center_spawned[2];
|
||||
int flags;
|
||||
int event; /* initial event used to fire the pie menu, store here so we can query for release */
|
||||
float alphafac;
|
||||
};
|
||||
|
||||
struct uiBlock {
|
||||
uiBlock *next, *prev;
|
||||
|
||||
@@ -356,6 +398,7 @@ struct uiBlock {
|
||||
char display_device[64]; /* display device name used to display this block,
|
||||
* used by color widgets to transform colors from/to scene linear
|
||||
*/
|
||||
struct PieMenuData pie_data;
|
||||
};
|
||||
|
||||
typedef struct uiSafetyRct {
|
||||
@@ -561,6 +604,9 @@ extern int ui_button_open_menu_direction(uiBut *but);
|
||||
extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
|
||||
extern uiBut *ui_but_find_activated(struct ARegion *ar);
|
||||
bool ui_but_is_editable(const uiBut *but);
|
||||
void ui_but_pie_dir_visual(RadialDirection dir, float vec[2]);
|
||||
void ui_but_pie_dir(RadialDirection dir, float vec[2]);
|
||||
void ui_block_calculate_pie_segment(struct uiBlock *block, const float event_xy[2]);
|
||||
|
||||
void ui_button_clipboard_free(void);
|
||||
void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
|
||||
@@ -571,6 +617,7 @@ uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
|
||||
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
|
||||
void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha);
|
||||
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
|
||||
void ui_draw_pie_center(uiBlock *block);
|
||||
uiWidgetColors *ui_tooltip_get_theme(void);
|
||||
void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
|
||||
void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
|
||||
|
@@ -106,6 +106,7 @@ typedef enum uiItemType {
|
||||
ITEM_LAYOUT_ABSOLUTE,
|
||||
ITEM_LAYOUT_SPLIT,
|
||||
ITEM_LAYOUT_OVERLAP,
|
||||
ITEM_LAYOUT_RADIAL,
|
||||
|
||||
ITEM_LAYOUT_ROOT
|
||||
#if 0
|
||||
@@ -218,7 +219,9 @@ static int ui_item_fit(int item, int pos, int all, int available, int last, int
|
||||
|
||||
static int ui_layout_vary_direction(uiLayout *layout)
|
||||
{
|
||||
return (layout->root->type == UI_LAYOUT_HEADER || layout->alignment != UI_LAYOUT_ALIGN_EXPAND) ? UI_ITEM_VARY_X : UI_ITEM_VARY_Y;
|
||||
return ((ELEM(layout->root->type, UI_LAYOUT_HEADER, UI_LAYOUT_PIEMENU) ||
|
||||
(layout->alignment != UI_LAYOUT_ALIGN_EXPAND)) ?
|
||||
UI_ITEM_VARY_X : UI_ITEM_VARY_Y);
|
||||
}
|
||||
|
||||
/* estimated size of text + icon */
|
||||
@@ -553,15 +556,24 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
|
||||
*/
|
||||
|
||||
uiBut *but;
|
||||
uiLayout *layout_radial = NULL;
|
||||
EnumPropertyItem *item, *item_array;
|
||||
const char *name;
|
||||
int itemw, icon, value;
|
||||
bool free;
|
||||
bool radial = (layout->root->type == UI_LAYOUT_PIEMENU);
|
||||
|
||||
RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item_array, NULL, &free);
|
||||
if (radial)
|
||||
RNA_property_enum_items_gettexted_all(block->evil_C, ptr, prop, &item_array, NULL, &free);
|
||||
else
|
||||
RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item_array, NULL, &free);
|
||||
|
||||
/* we dont want nested rows, cols in menus */
|
||||
if (layout->root->type != UI_LAYOUT_MENU) {
|
||||
if (radial) {
|
||||
layout_radial = uiLayoutRadial(layout);
|
||||
uiBlockSetCurLayout(block, layout_radial);
|
||||
}
|
||||
else if (layout->root->type != UI_LAYOUT_MENU) {
|
||||
uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
|
||||
}
|
||||
else {
|
||||
@@ -569,8 +581,11 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
|
||||
}
|
||||
|
||||
for (item = item_array; item->identifier; item++) {
|
||||
if (!item->identifier[0])
|
||||
if (!item->identifier[0]) {
|
||||
if (radial)
|
||||
uiItemS(layout_radial);
|
||||
continue;
|
||||
}
|
||||
|
||||
name = (!uiname || uiname[0]) ? item->name : "";
|
||||
icon = item->icon;
|
||||
@@ -869,6 +884,8 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop;
|
||||
uiBlock *block = layout->root->block;
|
||||
const bool radial = (layout->item.type == ITEM_LAYOUT_RADIAL) ||
|
||||
((layout->item.type == ITEM_LAYOUT_ROOT) && (layout->root->type == UI_LAYOUT_PIEMENU));
|
||||
|
||||
if (!ot || !ot->srna) {
|
||||
ui_item_disabled(layout, opname);
|
||||
@@ -887,10 +904,24 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
|
||||
if (prop && RNA_property_type(prop) == PROP_ENUM) {
|
||||
EnumPropertyItem *item, *item_array = NULL;
|
||||
bool free;
|
||||
uiLayout *split = uiLayoutSplit(layout, 0.0f, false);
|
||||
uiLayout *column = uiLayoutColumn(split, layout->align);
|
||||
uiLayout *split;
|
||||
uiLayout *target;
|
||||
|
||||
if (radial) {
|
||||
target = uiLayoutRadial(layout);
|
||||
}
|
||||
else {
|
||||
split = uiLayoutSplit(layout, 0.0f, false);
|
||||
target = uiLayoutColumn(split, layout->align);
|
||||
}
|
||||
|
||||
if (radial) {
|
||||
RNA_property_enum_items_gettexted_all(block->evil_C, &ptr, prop, &item_array, NULL, &free);
|
||||
}
|
||||
else {
|
||||
RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, NULL, &free);
|
||||
}
|
||||
|
||||
RNA_property_enum_items_gettexted(block->evil_C, &ptr, prop, &item_array, NULL, &free);
|
||||
for (item = item_array; item->identifier; item++) {
|
||||
if (item->identifier[0]) {
|
||||
PointerRNA tptr;
|
||||
@@ -905,20 +936,24 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
|
||||
}
|
||||
RNA_property_enum_set(&tptr, prop, item->value);
|
||||
|
||||
uiItemFullO_ptr(column, ot, item->name, item->icon, tptr.data, context, flag);
|
||||
uiItemFullO_ptr(target, ot, item->name, item->icon, tptr.data, context, flag);
|
||||
|
||||
ui_but_tip_from_enum_item(block->buttons.last, item);
|
||||
}
|
||||
else {
|
||||
if (item->name) {
|
||||
uiBut *but;
|
||||
if (item != item_array) {
|
||||
column = uiLayoutColumn(split, layout->align);
|
||||
|
||||
if (item != item_array && !radial) {
|
||||
target = uiLayoutColumn(split, layout->align);
|
||||
|
||||
/* inconsistent, but menus with labels do not look good flipped */
|
||||
block->flag |= UI_BLOCK_NO_FLIP;
|
||||
}
|
||||
|
||||
if (item->icon) {
|
||||
uiItemL(column, item->name, item->icon);
|
||||
if (item->icon || radial) {
|
||||
uiItemL(target, item->name, item->icon);
|
||||
|
||||
but = block->buttons.last;
|
||||
}
|
||||
else {
|
||||
@@ -928,8 +963,14 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
|
||||
}
|
||||
ui_but_tip_from_enum_item(but, item);
|
||||
}
|
||||
else { /* XXX bug here, colums draw bottom item badly */
|
||||
uiItemS(column);
|
||||
else {
|
||||
if (radial) {
|
||||
uiItemS(target);
|
||||
}
|
||||
else {
|
||||
/* XXX bug here, colums draw bottom item badly */
|
||||
uiItemS(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2072,16 +2113,135 @@ static void ui_litem_layout_column(uiLayout *litem)
|
||||
litem->y = y;
|
||||
}
|
||||
|
||||
/* calculates the angle of a specified button in a radial menu,
|
||||
* stores a float vector in unit circle */
|
||||
static RadialDirection ui_get_radialbut_vec(float vec[2], short itemnum)
|
||||
{
|
||||
RadialDirection dir;
|
||||
BLI_assert(itemnum < 8);
|
||||
|
||||
dir = ui_radial_dir_order[itemnum];
|
||||
ui_but_pie_dir_visual(dir, vec);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static bool ui_item_is_radial_displayable(uiItem *item)
|
||||
{
|
||||
|
||||
if ((item->type == ITEM_BUTTON) && (((uiButtonItem *)item)->but->type == LABEL))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ui_item_is_radial_drawable(uiButtonItem *bitem)
|
||||
{
|
||||
|
||||
if (ELEM(bitem->but->type, SEPR, SEPRLINE))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ui_litem_layout_radial(uiLayout *litem)
|
||||
{
|
||||
uiItem *item;
|
||||
int itemh, itemw, x, y;
|
||||
int itemnum = 0;
|
||||
int totitems = 0;
|
||||
|
||||
int minx, miny, maxx, maxy;
|
||||
/* For the radial layout we will use Matt Ebb's design
|
||||
* for radiation, see http://mattebb.com/weblog/radiation/
|
||||
* also the old code at http://developer.blender.org/T5103
|
||||
*/
|
||||
|
||||
int pie_radius = U.pie_menu_radius * UI_DPI_FAC;
|
||||
|
||||
x = litem->x;
|
||||
y = litem->y;
|
||||
|
||||
minx = x, miny = y, maxx = x, maxy = y;
|
||||
|
||||
/* first count total items */
|
||||
for (item = litem->items.first; item; item = item->next)
|
||||
totitems++;
|
||||
|
||||
if (totitems < 5)
|
||||
litem->root->block->pie_data.flags |= UI_PIE_DEGREES_RANGE_LARGE;
|
||||
|
||||
if (totitems == 3)
|
||||
litem->root->block->pie_data.flags |= UI_PIE_3_ITEMS;
|
||||
|
||||
for (item = litem->items.first; item; item = item->next) {
|
||||
/* not all button types are drawn in a radial menu, do filtering here */
|
||||
if (ui_item_is_radial_displayable(item)) {
|
||||
RadialDirection dir;
|
||||
float vec[2];
|
||||
|
||||
dir = ui_get_radialbut_vec(vec, itemnum);
|
||||
|
||||
itemnum++;
|
||||
|
||||
if (item->type == ITEM_BUTTON) {
|
||||
uiButtonItem *bitem = (uiButtonItem *) item;
|
||||
|
||||
bitem->but->pie_dir = dir;
|
||||
/* scale the buttons */
|
||||
bitem->but->rect.ymax *= 1.5f;
|
||||
/* add a little bit more here to include number */
|
||||
bitem->but->rect.xmax += 1.5f * UI_UNIT_X;
|
||||
/* enable drawing as pie item if supported by widget */
|
||||
if (ui_item_is_radial_drawable(bitem))
|
||||
bitem->but->dt = UI_EMBOSSR;
|
||||
}
|
||||
|
||||
ui_item_size(item, &itemw, &itemh);
|
||||
|
||||
ui_item_position(item, x + vec[0] * pie_radius - itemw / 2, y + vec[1] * pie_radius - itemh / 2, itemw, itemh);
|
||||
|
||||
minx = min_ii(minx, x + vec[0] * pie_radius - itemw / 2);
|
||||
maxx = max_ii(maxx, x + vec[0] * pie_radius + itemw / 2);
|
||||
miny = min_ii(miny, y + vec[1] * pie_radius - itemh / 2);
|
||||
maxy = max_ii(maxy, y + vec[1] * pie_radius + itemh / 2);
|
||||
}
|
||||
}
|
||||
|
||||
litem->x = minx;
|
||||
litem->y = miny;
|
||||
litem->w = maxx - minx;
|
||||
litem->h = maxy - miny;
|
||||
}
|
||||
|
||||
/* root layout */
|
||||
static void ui_litem_estimate_root(uiLayout *UNUSED(litem))
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static void ui_litem_layout_root_radial(uiLayout *litem)
|
||||
{
|
||||
/* first item is pie menu title, align on center of menu */
|
||||
uiItem *item = litem->items.first;
|
||||
|
||||
if (item->type == ITEM_BUTTON) {
|
||||
int itemh, itemw, x, y;
|
||||
x = litem->x;
|
||||
y = litem->y;
|
||||
|
||||
ui_item_size(item, &itemw, &itemh);
|
||||
|
||||
ui_item_position(item, x - itemw / 2, y + 2 * UI_UNIT_Y, itemw, itemh);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_litem_layout_root(uiLayout *litem)
|
||||
{
|
||||
if (litem->root->type == UI_LAYOUT_HEADER)
|
||||
ui_litem_layout_row(litem);
|
||||
else if (litem->root->type == UI_LAYOUT_PIEMENU)
|
||||
ui_litem_layout_root_radial(litem);
|
||||
else
|
||||
ui_litem_layout_column(litem);
|
||||
}
|
||||
@@ -2497,6 +2657,40 @@ static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
|
||||
return box;
|
||||
}
|
||||
|
||||
uiLayout *uiLayoutRadial(uiLayout *layout)
|
||||
{
|
||||
uiLayout *litem;
|
||||
uiItem *item;
|
||||
|
||||
/* radial layouts are only valid for radial menus */
|
||||
if (layout->root->type != UI_LAYOUT_PIEMENU)
|
||||
return ui_item_local_sublayout(layout, layout, 0);
|
||||
|
||||
/* only one radial wheel per root layout is allowed, so check and return that, if it exists */
|
||||
for (item = layout->root->layout->items.first; item; item = item->next) {
|
||||
litem = (uiLayout *)item;
|
||||
if (litem->item.type == ITEM_LAYOUT_RADIAL) {
|
||||
uiBlockSetCurLayout(layout->root->block, litem);
|
||||
return litem;
|
||||
}
|
||||
}
|
||||
|
||||
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRadial");
|
||||
litem->item.type = ITEM_LAYOUT_RADIAL;
|
||||
litem->root = layout->root;
|
||||
litem->active = true;
|
||||
litem->enabled = true;
|
||||
litem->context = layout->context;
|
||||
litem->redalert = layout->redalert;
|
||||
litem->w = layout->w;
|
||||
BLI_addtail(&layout->root->layout->items, litem);
|
||||
|
||||
uiBlockSetCurLayout(layout->root->block, litem);
|
||||
|
||||
return litem;
|
||||
}
|
||||
|
||||
|
||||
uiLayout *uiLayoutBox(uiLayout *layout)
|
||||
{
|
||||
return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
|
||||
@@ -2843,6 +3037,9 @@ static void ui_item_layout(uiItem *item)
|
||||
case ITEM_LAYOUT_OVERLAP:
|
||||
ui_litem_layout_overlap(litem);
|
||||
break;
|
||||
case ITEM_LAYOUT_RADIAL:
|
||||
ui_litem_layout_radial(litem);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2916,7 +3113,7 @@ uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int siz
|
||||
layout->enabled = 1;
|
||||
layout->context = NULL;
|
||||
|
||||
if (type == UI_LAYOUT_MENU)
|
||||
if (type == UI_LAYOUT_MENU || type == UI_LAYOUT_PIEMENU)
|
||||
layout->space = 0;
|
||||
|
||||
if (dir == UI_LAYOUT_HORIZONTAL) {
|
||||
|
@@ -1912,7 +1912,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
|
||||
data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData");
|
||||
pa->activedata = data;
|
||||
|
||||
WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa);
|
||||
WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, false);
|
||||
}
|
||||
|
||||
if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG))
|
||||
|
@@ -43,6 +43,8 @@
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_report.h"
|
||||
@@ -1704,18 +1706,69 @@ uiBlock *ui_popup_block_refresh(
|
||||
BLI_addhead(&block->saferct, saferct);
|
||||
}
|
||||
|
||||
/* clip block with window boundary */
|
||||
ui_popup_block_clip(window, block);
|
||||
|
||||
/* the block and buttons were positioned in window space as in 2.4x, now
|
||||
* these menu blocks are regions so we bring it back to region space.
|
||||
* additionally we add some padding for the menu shadow or rounded menus */
|
||||
ar->winrct.xmin = block->rect.xmin - width;
|
||||
ar->winrct.xmax = block->rect.xmax + width;
|
||||
ar->winrct.ymin = block->rect.ymin - width;
|
||||
ar->winrct.ymax = block->rect.ymax + MENU_TOP;
|
||||
|
||||
ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
|
||||
if (block->flag & UI_BLOCK_RADIAL) {
|
||||
uiBut *but;
|
||||
int win_width = UI_SCREEN_MARGIN;
|
||||
int winx, winy;
|
||||
|
||||
int x_offset = 0, y_offset = 0;
|
||||
|
||||
winx = WM_window_pixels_x(window);
|
||||
winy = WM_window_pixels_y(window);
|
||||
|
||||
copy_v2_v2(block->pie_data.pie_center_init, block->pie_data.pie_center_spawned);
|
||||
|
||||
/* only try translation if area is large enough */
|
||||
if (BLI_rctf_size_x(&block->rect) < winx - (2.0f * win_width)) {
|
||||
if (block->rect.xmin < win_width ) x_offset += win_width - block->rect.xmin;
|
||||
if (block->rect.xmax > winx - win_width) x_offset += winx - win_width - block->rect.xmax;
|
||||
}
|
||||
|
||||
if (BLI_rctf_size_y(&block->rect) < winy - (2.0f * win_width)) {
|
||||
if (block->rect.ymin < win_width ) y_offset += win_width - block->rect.ymin;
|
||||
if (block->rect.ymax > winy - win_width) y_offset += winy - win_width - block->rect.ymax;
|
||||
}
|
||||
/* if we are offsetting set up initial data for timeout functionality */
|
||||
|
||||
if ((x_offset != 0) || (y_offset != 0)) {
|
||||
block->pie_data.pie_center_spawned[0] += x_offset;
|
||||
block->pie_data.pie_center_spawned[1] += y_offset;
|
||||
|
||||
ui_block_translate(block, x_offset, y_offset);
|
||||
|
||||
if (U.pie_initial_timeout > 0)
|
||||
block->pie_data.flags |= UI_PIE_INITIAL_DIRECTION;
|
||||
}
|
||||
|
||||
ar->winrct.xmin = 0;
|
||||
ar->winrct.xmax = winx;
|
||||
ar->winrct.ymin = 0;
|
||||
ar->winrct.ymax = winy;
|
||||
|
||||
ui_block_calculate_pie_segment(block, block->pie_data.pie_center_init);
|
||||
|
||||
/* lastly set the buttons at the center of the pie menu, ready for animation */
|
||||
if (U.pie_animation_timeout > 0) {
|
||||
for (but = block->buttons.first; but; but = but->next) {
|
||||
if (but->pie_dir != UI_RADIAL_NONE) {
|
||||
BLI_rctf_recenter(&but->rect, UNPACK2(block->pie_data.pie_center_spawned));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* clip block with window boundary */
|
||||
ui_popup_block_clip(window, block);
|
||||
/* the block and buttons were positioned in window space as in 2.4x, now
|
||||
* these menu blocks are regions so we bring it back to region space.
|
||||
* additionally we add some padding for the menu shadow or rounded menus */
|
||||
ar->winrct.xmin = block->rect.xmin - width;
|
||||
ar->winrct.xmax = block->rect.xmax + width;
|
||||
ar->winrct.ymin = block->rect.ymin - width;
|
||||
ar->winrct.ymax = block->rect.ymax + MENU_TOP;
|
||||
|
||||
ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
|
||||
}
|
||||
|
||||
if (block_old) {
|
||||
block->oldblock = block_old;
|
||||
@@ -2353,6 +2406,12 @@ struct uiPopupMenu {
|
||||
void *menu_arg;
|
||||
};
|
||||
|
||||
struct uiPieMenu {
|
||||
uiBlock *block_radial; /* radial block of the pie menu (more could be added later) */
|
||||
uiLayout *layout;
|
||||
int mx, my;
|
||||
};
|
||||
|
||||
static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
|
||||
{
|
||||
uiBlock *block;
|
||||
@@ -2526,7 +2585,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut
|
||||
if (!but) {
|
||||
handle->popup = true;
|
||||
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, handle);
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
|
||||
WM_event_add_mousemove(C);
|
||||
}
|
||||
|
||||
@@ -2588,7 +2647,7 @@ void uiPupMenuEnd(bContext *C, uiPopupMenu *pup)
|
||||
menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup);
|
||||
menu->popup = true;
|
||||
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, menu);
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, menu, false);
|
||||
WM_event_add_mousemove(C);
|
||||
|
||||
MEM_freeN(pup);
|
||||
@@ -2599,6 +2658,175 @@ uiLayout *uiPupMenuLayout(uiPopupMenu *pup)
|
||||
return pup->layout;
|
||||
}
|
||||
|
||||
/*************************** Pie Menus ***************************************/
|
||||
|
||||
static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handle, void *arg_pie)
|
||||
{
|
||||
uiBlock *block;
|
||||
uiPieMenu *pie = arg_pie;
|
||||
int minwidth, width, height;
|
||||
|
||||
minwidth = 50;
|
||||
block = pie->block_radial;
|
||||
|
||||
/* in some cases we create the block before the region,
|
||||
* so we set it delayed here if necessary */
|
||||
if (BLI_findindex(&handle->region->uiblocks, block) == -1)
|
||||
uiBlockSetRegion(block, handle->region);
|
||||
|
||||
uiBlockLayoutResolve(block, &width, &height);
|
||||
|
||||
uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
|
||||
|
||||
block->minbounds = minwidth;
|
||||
block->bounds = 1;
|
||||
block->mx = 0;
|
||||
block->my = 0;
|
||||
block->bounds_type = UI_BLOCK_BOUNDS_PIE_CENTER;
|
||||
|
||||
block->pie_data.pie_center_spawned[0] = pie->mx;
|
||||
block->pie_data.pie_center_spawned[1] = pie->my;
|
||||
|
||||
return pie->block_radial;
|
||||
}
|
||||
|
||||
static float uiPieTitleWidth(const char *name, int icon)
|
||||
{
|
||||
return (UI_GetStringWidth(name) +
|
||||
(UI_UNIT_X * (1.50f + (icon ? 0.25f : 0.0f))));
|
||||
}
|
||||
|
||||
uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const wmEvent *event)
|
||||
{
|
||||
uiStyle *style = UI_GetStyleDraw();
|
||||
uiPieMenu *pie = MEM_callocN(sizeof(uiPopupMenu), "pie menu");
|
||||
|
||||
pie->block_radial = uiBeginBlock(C, NULL, __func__, UI_EMBOSS);
|
||||
/* may be useful later to allow spawning pies
|
||||
* from old positions */
|
||||
/* pie->block_radial->flag |= UI_BLOCK_POPUP_MEMORY; */
|
||||
pie->block_radial->puphash = ui_popup_menu_hash(title);
|
||||
pie->block_radial->flag |= UI_BLOCK_RADIAL;
|
||||
pie->block_radial->pie_data.event = event->type;
|
||||
|
||||
pie->layout = uiBlockLayout(pie->block_radial, UI_LAYOUT_VERTICAL, UI_LAYOUT_PIEMENU, 0, 0, 200, 0, 0, style);
|
||||
pie->mx = event->x;
|
||||
pie->my = event->y;
|
||||
|
||||
/* create title button */
|
||||
if (title[0]) {
|
||||
char titlestr[256];
|
||||
int w;
|
||||
if (icon) {
|
||||
BLI_snprintf(titlestr, sizeof(titlestr), " %s", title);
|
||||
w = uiPieTitleWidth(titlestr, icon);
|
||||
uiDefIconTextBut(pie->block_radial, LABEL, 0, icon, titlestr, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
|
||||
}
|
||||
else {
|
||||
w = uiPieTitleWidth(title, 0);
|
||||
uiDefBut(pie->block_radial, LABEL, 0, title, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
|
||||
}
|
||||
}
|
||||
|
||||
return pie;
|
||||
}
|
||||
|
||||
void uiPieMenuEnd(bContext *C, uiPieMenu *pie)
|
||||
{
|
||||
wmWindow *window = CTX_wm_window(C);
|
||||
uiPopupBlockHandle *menu;
|
||||
|
||||
menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie);
|
||||
menu->popup = true;
|
||||
menu->towardstime = PIL_check_seconds_timer();
|
||||
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, menu, true);
|
||||
WM_event_add_mousemove(C);
|
||||
|
||||
MEM_freeN(pie);
|
||||
}
|
||||
|
||||
uiLayout *uiPieMenuLayout(uiPieMenu *pie)
|
||||
{
|
||||
return pie->layout;
|
||||
}
|
||||
|
||||
void uiPieMenuInvoke(struct bContext *C, const char *idname, const wmEvent *event)
|
||||
{
|
||||
uiPieMenu *pie;
|
||||
uiLayout *layout;
|
||||
Menu menu;
|
||||
MenuType *mt = WM_menutype_find(idname, true);
|
||||
|
||||
if (mt == NULL) {
|
||||
printf("%s: named menu \"%s\" not found\n", __func__, idname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mt->poll && mt->poll(C, mt) == 0)
|
||||
return;
|
||||
|
||||
pie = uiPieMenuBegin(C, IFACE_(mt->label), ICON_NONE, event);
|
||||
layout = uiPieMenuLayout(pie);
|
||||
|
||||
menu.layout = layout;
|
||||
menu.type = mt;
|
||||
|
||||
if (G.debug & G_DEBUG_WM) {
|
||||
printf("%s: opening menu \"%s\"\n", __func__, idname);
|
||||
}
|
||||
|
||||
mt->draw(C, &menu);
|
||||
|
||||
uiPieMenuEnd(C, pie);
|
||||
}
|
||||
|
||||
void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
|
||||
const char *propname, const wmEvent *event)
|
||||
{
|
||||
uiPieMenu *pie;
|
||||
uiLayout *layout;
|
||||
|
||||
pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event);
|
||||
layout = uiPieMenuLayout(pie);
|
||||
|
||||
layout = uiLayoutRadial(layout);
|
||||
uiItemsEnumO(layout, opname, propname);
|
||||
|
||||
uiPieMenuEnd(C, pie);
|
||||
}
|
||||
|
||||
void uiPieEnumInvoke(struct bContext *C, const char *title, const char *path,
|
||||
const wmEvent *event)
|
||||
{
|
||||
PointerRNA ctx_ptr;
|
||||
PointerRNA r_ptr;
|
||||
PropertyRNA *r_prop;
|
||||
uiPieMenu *pie;
|
||||
uiLayout *layout;
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
|
||||
|
||||
if (!RNA_path_resolve(&ctx_ptr, path, &r_ptr, &r_prop)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* invalid property, only accept enums */
|
||||
if (RNA_property_type(r_prop) != PROP_ENUM) {
|
||||
BLI_assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
pie = uiPieMenuBegin(C, IFACE_(title), ICON_NONE, event);
|
||||
layout = uiPieMenuLayout(pie);
|
||||
|
||||
layout = uiLayoutRadial(layout);
|
||||
uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, NULL, 0);
|
||||
|
||||
uiPieMenuEnd(C, pie);
|
||||
}
|
||||
|
||||
|
||||
/*************************** Standard Popup Menus ****************************/
|
||||
|
||||
void uiPupMenuReports(bContext *C, ReportList *reports)
|
||||
@@ -2695,7 +2923,7 @@ void uiPupBlockO(bContext *C, uiBlockCreateFunc func, void *arg, const char *opn
|
||||
handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
|
||||
handle->opcontext = opcontext;
|
||||
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, handle);
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
|
||||
WM_event_add_mousemove(C);
|
||||
}
|
||||
|
||||
@@ -2718,7 +2946,7 @@ void uiPupBlockEx(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_f
|
||||
handle->cancel_func = cancel_func;
|
||||
// handle->opcontext = opcontext;
|
||||
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, handle);
|
||||
UI_add_popup_handlers(C, &window->modalhandlers, handle, false);
|
||||
WM_event_add_mousemove(C);
|
||||
}
|
||||
|
||||
|
@@ -1596,6 +1596,21 @@ static struct uiWidgetColors wcol_menu_back = {
|
||||
25, -20
|
||||
};
|
||||
|
||||
/* pie menus */
|
||||
static struct uiWidgetColors wcol_pie_menu = {
|
||||
{10, 10, 10, 200},
|
||||
{25, 25, 25, 230},
|
||||
{140, 140, 140, 255},
|
||||
{45, 45, 45, 230},
|
||||
|
||||
{160, 160, 160, 255},
|
||||
{255, 255, 255, 255},
|
||||
|
||||
1,
|
||||
10, -10
|
||||
};
|
||||
|
||||
|
||||
/* tooltip color */
|
||||
static struct uiWidgetColors wcol_tooltip = {
|
||||
{0, 0, 0, 255},
|
||||
@@ -1743,6 +1758,7 @@ void ui_widget_color_init(ThemeUI *tui)
|
||||
tui->wcol_menu = wcol_menu;
|
||||
tui->wcol_pulldown = wcol_pulldown;
|
||||
tui->wcol_menu_back = wcol_menu_back;
|
||||
tui->wcol_pie_menu = wcol_pie_menu;
|
||||
tui->wcol_tooltip = wcol_tooltip;
|
||||
tui->wcol_menu_item = wcol_menu_item;
|
||||
tui->wcol_box = wcol_box;
|
||||
@@ -1891,6 +1907,34 @@ static void widget_state_pulldown(uiWidgetType *wt, int state)
|
||||
copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
|
||||
}
|
||||
|
||||
/* special case, pie menu items */
|
||||
static void widget_state_pie_menu_item(uiWidgetType *wt, int state)
|
||||
{
|
||||
wt->wcol = *(wt->wcol_theme);
|
||||
|
||||
/* active and disabled (not so common) */
|
||||
if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
|
||||
widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f);
|
||||
/* draw the backdrop at low alpha, helps navigating with keys
|
||||
* when disabled items are active */
|
||||
copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
|
||||
wt->wcol.inner[3] = 64;
|
||||
}
|
||||
/* regular disabled */
|
||||
else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
|
||||
widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
|
||||
}
|
||||
/* regular active */
|
||||
else if (state & UI_SELECT) {
|
||||
copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel);
|
||||
copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
|
||||
}
|
||||
else if (state & UI_ACTIVE) {
|
||||
copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
|
||||
copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
|
||||
}
|
||||
}
|
||||
|
||||
/* special case, menu items */
|
||||
static void widget_state_menu_item(uiWidgetType *wt, int state)
|
||||
{
|
||||
@@ -2973,6 +3017,29 @@ static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
|
||||
static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
|
||||
{
|
||||
uiWidgetBase wtb;
|
||||
float rad;
|
||||
float fac = but->block->pie_data.alphafac;
|
||||
|
||||
widget_init(&wtb);
|
||||
|
||||
wtb.emboss = 0;
|
||||
|
||||
rad = 0.5f * BLI_rcti_size_y(rect);
|
||||
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
|
||||
|
||||
wcol->inner[3] *= fac;
|
||||
wcol->inner_sel[3] *= fac;
|
||||
wcol->item[3] *= fac;
|
||||
wcol->text[3] *= fac;
|
||||
wcol->text_sel[3] *= fac;
|
||||
wcol->outline[3] *= fac;
|
||||
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
|
||||
static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
|
||||
{
|
||||
uiWidgetBase wtb;
|
||||
@@ -3291,6 +3358,12 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
|
||||
wt.wcol_theme = &btheme->tui.wcol_progress;
|
||||
wt.custom = widget_progressbar;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_MENU_ITEM_RADIAL:
|
||||
wt.wcol_theme = &btheme->tui.wcol_pie_menu;
|
||||
wt.custom = widget_menu_radial_itembut;
|
||||
wt.state = widget_state_pie_menu_item;
|
||||
break;
|
||||
}
|
||||
|
||||
return &wt;
|
||||
@@ -3397,6 +3470,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
|
||||
/* "nothing" */
|
||||
wt = widget_type(UI_WTYPE_ICON);
|
||||
}
|
||||
else if (but->dt == UI_EMBOSSR) {
|
||||
wt = widget_type(UI_WTYPE_MENU_ITEM_RADIAL);
|
||||
}
|
||||
else {
|
||||
|
||||
switch (but->type) {
|
||||
@@ -3649,6 +3725,125 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_disk_shaded(
|
||||
float start, float angle,
|
||||
float radius_int, float radius_ext, int subd,
|
||||
const char col1[4], const char col2[4],
|
||||
bool shaded)
|
||||
{
|
||||
const float radius_ext_scale = (0.5f / radius_ext); /* 1 / (2 * radius_ext) */
|
||||
int i;
|
||||
|
||||
float s, c;
|
||||
float y1, y2;
|
||||
float fac;
|
||||
unsigned char r_col[4];
|
||||
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
|
||||
s = sinf(start);
|
||||
c = cosf(start);
|
||||
|
||||
y1 = s * radius_int;
|
||||
y2 = s * radius_ext;
|
||||
|
||||
if (shaded) {
|
||||
fac = (y1 + radius_ext) * radius_ext_scale;
|
||||
round_box_shade_col4_r(r_col, col1, col2, fac);
|
||||
|
||||
glColor4ubv(r_col);
|
||||
}
|
||||
|
||||
glVertex2f(c * radius_int, s * radius_int);
|
||||
|
||||
if (shaded) {
|
||||
fac = (y2 + radius_ext) * radius_ext_scale;
|
||||
round_box_shade_col4_r(r_col, col1, col2, fac);
|
||||
|
||||
glColor4ubv(r_col);
|
||||
}
|
||||
glVertex2f(c * radius_ext, s * radius_ext);
|
||||
|
||||
for (i = 1; i < subd; i++) {
|
||||
float a;
|
||||
|
||||
a = start + ((i) / (float)(subd - 1)) * angle;
|
||||
s = sinf(a);
|
||||
c = cosf(a);
|
||||
y1 = s * radius_int;
|
||||
y2 = s * radius_ext;
|
||||
|
||||
if (shaded) {
|
||||
fac = (y1 + radius_ext) * radius_ext_scale;
|
||||
round_box_shade_col4_r(r_col, col1, col2, fac);
|
||||
|
||||
glColor4ubv(r_col);
|
||||
}
|
||||
glVertex2f(c * radius_int, s * radius_int);
|
||||
|
||||
if (shaded) {
|
||||
fac = (y2 + radius_ext) * radius_ext_scale;
|
||||
round_box_shade_col4_r(r_col, col1, col2, fac);
|
||||
|
||||
glColor4ubv(r_col);
|
||||
}
|
||||
glVertex2f(c * radius_ext, s * radius_ext);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
void ui_draw_pie_center(uiBlock *block)
|
||||
{
|
||||
bTheme *btheme = UI_GetTheme();
|
||||
float cx = block->pie_data.pie_center_spawned[0];
|
||||
float cy = block->pie_data.pie_center_spawned[1];
|
||||
|
||||
float *pie_dir = block->pie_data.pie_dir;
|
||||
|
||||
float pie_radius_internal = U.pixelsize * U.pie_menu_threshold;
|
||||
float pie_radius_external = U.pixelsize * (U.pie_menu_threshold + 7.0f);
|
||||
|
||||
int subd = 40;
|
||||
|
||||
float angle = atan2(pie_dir[1], pie_dir[0]);
|
||||
float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? ((float)M_PI / 2.0f) : ((float)M_PI / 4.0f);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(cx, cy, 0.0f);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
if (btheme->tui.wcol_pie_menu.shaded) {
|
||||
char col1[4], col2[4];
|
||||
shadecolors4(col1, col2, btheme->tui.wcol_pie_menu.inner, btheme->tui.wcol_pie_menu.shadetop, btheme->tui.wcol_pie_menu.shadedown);
|
||||
draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true);
|
||||
}
|
||||
else {
|
||||
glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner);
|
||||
draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
|
||||
}
|
||||
|
||||
if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) {
|
||||
if (btheme->tui.wcol_pie_menu.shaded) {
|
||||
char col1[4], col2[4];
|
||||
shadecolors4(col1, col2, btheme->tui.wcol_pie_menu.inner_sel, btheme->tui.wcol_pie_menu.shadetop, btheme->tui.wcol_pie_menu.shadedown);
|
||||
draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, col1, col2, true);
|
||||
}
|
||||
else {
|
||||
glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner_sel);
|
||||
draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.outline);
|
||||
glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd);
|
||||
glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
uiWidgetColors *ui_tooltip_get_theme(void)
|
||||
{
|
||||
uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
|
||||
|
@@ -2454,6 +2454,31 @@ void init_userdef_do_versions(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (U.versionfile < 271 || (U.versionfile == 271 && U.subversionfile < 4)) {
|
||||
bTheme *btheme;
|
||||
|
||||
struct uiWidgetColors wcol_pie_menu = {
|
||||
{10, 10, 10, 200},
|
||||
{25, 25, 25, 230},
|
||||
{140, 140, 140, 255},
|
||||
{45, 45, 45, 230},
|
||||
|
||||
{160, 160, 160, 255},
|
||||
{255, 255, 255, 255},
|
||||
|
||||
1,
|
||||
10, -10
|
||||
};
|
||||
|
||||
U.pie_menu_radius = 150;
|
||||
U.pie_menu_threshold = 12;
|
||||
U.pie_animation_timeout = 6;
|
||||
|
||||
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
|
||||
btheme->tui.wcol_pie_menu = wcol_pie_menu;
|
||||
}
|
||||
}
|
||||
|
||||
if (U.pixelsize == 0.0f)
|
||||
U.pixelsize = 1.0f;
|
||||
|
||||
|
@@ -61,6 +61,7 @@
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_sound.h"
|
||||
#include "ED_uvedit.h"
|
||||
#include "ED_view3d.h"
|
||||
#include "ED_mball.h"
|
||||
#include "ED_logic.h"
|
||||
#include "ED_clip.h"
|
||||
@@ -130,8 +131,17 @@ void ED_spacetypes_init(void)
|
||||
type->operatortypes();
|
||||
}
|
||||
|
||||
/* Macros's must go last since they reference other operators
|
||||
* maybe we'll need to have them go after python operators too? */
|
||||
/* register internal render callbacks */
|
||||
ED_render_internal_init();
|
||||
}
|
||||
|
||||
void ED_spacemacros_init(void)
|
||||
{
|
||||
const ListBase *spacetypes;
|
||||
SpaceType *type;
|
||||
|
||||
/* Macros's must go last since they reference other operators.
|
||||
* We need to have them go after python operators too */
|
||||
ED_operatormacros_armature();
|
||||
ED_operatormacros_mesh();
|
||||
ED_operatormacros_metaball();
|
||||
@@ -152,9 +162,6 @@ void ED_spacetypes_init(void)
|
||||
if (type->dropboxes)
|
||||
type->dropboxes();
|
||||
}
|
||||
|
||||
/* register internal render callbacks */
|
||||
ED_render_internal_init();
|
||||
}
|
||||
|
||||
/* called in wm.c */
|
||||
|
@@ -78,6 +78,7 @@
|
||||
#include "ED_view3d.h"
|
||||
#include "ED_sculpt.h"
|
||||
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "PIL_time.h" /* smoothview */
|
||||
|
||||
@@ -3550,13 +3551,13 @@ void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot)
|
||||
/* ********************* Changing view operator ****************** */
|
||||
|
||||
static EnumPropertyItem prop_view_items[] = {
|
||||
{RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"},
|
||||
{RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View From the Right"},
|
||||
{RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View From the Bottom"},
|
||||
{RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View From the Top"},
|
||||
{RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"},
|
||||
{RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"},
|
||||
{RV3D_VIEW_LEFT, "LEFT", 0, "Left", "View From the Left"},
|
||||
{RV3D_VIEW_RIGHT, "RIGHT", 0, "Right", "View From the Right"},
|
||||
{RV3D_VIEW_TOP, "TOP", 0, "Top", "View From the Top"},
|
||||
{RV3D_VIEW_BOTTOM, "BOTTOM", 0, "Bottom", "View From the Bottom"},
|
||||
{RV3D_VIEW_CAMERA, "CAMERA", 0, "Camera", "View From the Active Camera"},
|
||||
{RV3D_VIEW_CAMERA, "CAMERA", ICON_CAMERA_DATA, "Camera", "View From the Active Camera"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@@ -162,7 +162,7 @@ typedef struct ThemeUI {
|
||||
uiWidgetColors wcol_radio, wcol_option, wcol_toggle;
|
||||
uiWidgetColors wcol_num, wcol_numslider;
|
||||
uiWidgetColors wcol_menu, wcol_pulldown, wcol_menu_back, wcol_menu_item, wcol_tooltip;
|
||||
uiWidgetColors wcol_box, wcol_scroll, wcol_progress, wcol_list_item;
|
||||
uiWidgetColors wcol_box, wcol_scroll, wcol_progress, wcol_list_item, wcol_pie_menu;
|
||||
|
||||
uiWidgetStateColors wcol_state;
|
||||
|
||||
@@ -534,6 +534,15 @@ typedef struct UserDef {
|
||||
float fcu_inactive_alpha; /* opacity of inactive F-Curves in F-Curve Editor */
|
||||
float pixelsize; /* private, set by GHOST, to multiply DPI with */
|
||||
|
||||
short pie_interaction_type; /* if keeping a pie menu spawn button pressed after this time, it turns into
|
||||
* a drag/release pie menu */
|
||||
short pie_initial_timeout; /* direction in the pie menu will always be calculated from the initial position
|
||||
* within this time limit */
|
||||
int pie_animation_timeout;
|
||||
int pad2;
|
||||
short pie_menu_radius; /* pie menu radius */
|
||||
short pie_menu_threshold; /* pie menu distance from center before a direction is set */
|
||||
|
||||
struct WalkNavigation walk_navigation;
|
||||
} UserDef;
|
||||
|
||||
|
@@ -633,6 +633,7 @@ extern StructRNA RNA_TransformConstraint;
|
||||
extern StructRNA RNA_TransformSequence;
|
||||
extern StructRNA RNA_UILayout;
|
||||
extern StructRNA RNA_UIList;
|
||||
extern StructRNA RNA_UIPieMenu;
|
||||
extern StructRNA RNA_UIPopupMenu;
|
||||
extern StructRNA RNA_UVWarpModifier;
|
||||
extern StructRNA RNA_UVProjectModifier;
|
||||
@@ -794,6 +795,8 @@ void RNA_property_enum_items(struct bContext *C, PointerRNA *ptr, PropertyRNA *p
|
||||
EnumPropertyItem **item, int *r_totitem, bool *r_free);
|
||||
void RNA_property_enum_items_gettexted(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop,
|
||||
EnumPropertyItem **r_item, int *r_totitem, bool *r_free);
|
||||
void RNA_property_enum_items_gettexted_all(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop,
|
||||
EnumPropertyItem **r_item, int *r_totitem, bool *r_free);
|
||||
bool RNA_property_enum_value(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value);
|
||||
bool RNA_property_enum_identifier(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier);
|
||||
bool RNA_property_enum_name(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name);
|
||||
|
@@ -1249,12 +1249,9 @@ void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, En
|
||||
}
|
||||
}
|
||||
|
||||
void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
|
||||
EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
|
||||
{
|
||||
RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
|
||||
|
||||
#ifdef WITH_INTERNATIONAL
|
||||
static void property_enum_translate(PropertyRNA *prop, EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
|
||||
{
|
||||
if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
|
||||
int i;
|
||||
|
||||
@@ -1300,9 +1297,71 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA
|
||||
|
||||
*r_item = nitem;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
|
||||
EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
|
||||
{
|
||||
RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
|
||||
|
||||
#ifdef WITH_INTERNATIONAL
|
||||
property_enum_translate(prop, r_item, r_totitem, r_free);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RNA_property_enum_items_gettexted_all(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
|
||||
EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
|
||||
{
|
||||
EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
|
||||
int mem_size = sizeof(EnumPropertyItem) * (eprop->totitem + 1);
|
||||
/* first return all items */
|
||||
*r_free = true;
|
||||
*r_item = MEM_mallocN(mem_size, "enum_gettext_all");
|
||||
memcpy(*r_item, eprop->item, mem_size);
|
||||
|
||||
if (r_totitem)
|
||||
*r_totitem = eprop->totitem;
|
||||
|
||||
if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
|
||||
EnumPropertyItem *item;
|
||||
int i;
|
||||
bool free = false;
|
||||
|
||||
if (prop->flag & PROP_ENUM_NO_CONTEXT)
|
||||
item = eprop->itemf(NULL, ptr, prop, &free);
|
||||
else
|
||||
item = eprop->itemf(C, ptr, prop, &free);
|
||||
|
||||
/* any callbacks returning NULL should be fixed */
|
||||
BLI_assert(item != NULL);
|
||||
|
||||
for (i = 0; i < eprop->totitem; i++) {
|
||||
bool exists = false;
|
||||
int i_fixed;
|
||||
|
||||
/* items that do not exist on list are returned, but have their names/identifiers NULLed out */
|
||||
for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
|
||||
if (STREQ(item[i_fixed].identifier, (*r_item)[i].identifier)) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
(*r_item)[i].name = NULL;
|
||||
(*r_item)[i].identifier = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (free)
|
||||
MEM_freeN(item);
|
||||
}
|
||||
|
||||
#ifdef WITH_INTERNATIONAL
|
||||
property_enum_translate(prop, r_item, r_totitem, r_free);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
|
||||
{
|
||||
|
@@ -61,12 +61,12 @@
|
||||
EnumPropertyItem object_mode_items[] = {
|
||||
{OB_MODE_OBJECT, "OBJECT", ICON_OBJECT_DATAMODE, "Object Mode", ""},
|
||||
{OB_MODE_EDIT, "EDIT", ICON_EDITMODE_HLT, "Edit Mode", ""},
|
||||
{OB_MODE_POSE, "POSE", ICON_POSE_HLT, "Pose Mode", ""},
|
||||
{OB_MODE_SCULPT, "SCULPT", ICON_SCULPTMODE_HLT, "Sculpt Mode", ""},
|
||||
{OB_MODE_VERTEX_PAINT, "VERTEX_PAINT", ICON_VPAINT_HLT, "Vertex Paint", ""},
|
||||
{OB_MODE_WEIGHT_PAINT, "WEIGHT_PAINT", ICON_WPAINT_HLT, "Weight Paint", ""},
|
||||
{OB_MODE_TEXTURE_PAINT, "TEXTURE_PAINT", ICON_TPAINT_HLT, "Texture Paint", ""},
|
||||
{OB_MODE_PARTICLE_EDIT, "PARTICLE_EDIT", ICON_PARTICLEMODE, "Particle Edit", ""},
|
||||
{OB_MODE_POSE, "POSE", ICON_POSE_HLT, "Pose Mode", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@@ -1784,11 +1784,11 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem manipulators_items[] = {
|
||||
{V3D_MANIP_TRANSLATE, "TRANSLATE", ICON_MAN_TRANS, "Manipulator Translate",
|
||||
{V3D_MANIP_TRANSLATE, "TRANSLATE", ICON_MAN_TRANS, "Translate",
|
||||
"Use the manipulator for movement transformations"},
|
||||
{V3D_MANIP_ROTATE, "ROTATE", ICON_MAN_ROT, "Manipulator Rotate",
|
||||
{V3D_MANIP_ROTATE, "ROTATE", ICON_MAN_ROT, "Rotate",
|
||||
"Use the manipulator for rotation transformations"},
|
||||
{V3D_MANIP_SCALE, "SCALE", ICON_MAN_SCALE, "Manipulator Scale",
|
||||
{V3D_MANIP_SCALE, "SCALE", ICON_MAN_SCALE, "Scale",
|
||||
"Use the manipulator for scale transformations"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
@@ -462,6 +462,13 @@ void RNA_api_ui_layout(StructRNA *srna)
|
||||
RNA_def_float(func, "percentage", 0.0f, 0.0f, 1.0f, "Percentage", "Percentage of width to split at", 0.0f, 1.0f);
|
||||
RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
|
||||
|
||||
/* radial/pie layout */
|
||||
func = RNA_def_function(srna, "menu_pie", "uiLayoutRadial");
|
||||
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
|
||||
RNA_def_function_return(func, parm);
|
||||
RNA_def_function_ui_description(func, "Sublayout. Items placed in this sublayout are placed "
|
||||
"in a radial fashion around the menu center)");
|
||||
|
||||
/* Icon of a rna pointer */
|
||||
func = RNA_def_function(srna, "icon", "rna_ui_get_rnaptr_icon");
|
||||
parm = RNA_def_int(func, "icon_value", ICON_NONE, 0, INT_MAX, "", "Icon identifier", 0, INT_MAX);
|
||||
|
@@ -953,6 +953,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_ui_text(prop, "Menu Backdrop Colors", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop = RNA_def_property(srna, "wcol_pie_menu", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_ui_text(prop, "Pie Menu Colors", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop = RNA_def_property(srna, "wcol_tooltip", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_ui_text(prop, "Tooltip Colors", "");
|
||||
@@ -3208,6 +3214,26 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Sub Level Menu Open Delay",
|
||||
"Time delay in 1/10 seconds before automatically opening sub level menus");
|
||||
|
||||
/* pie menus */
|
||||
prop = RNA_def_property(srna, "pie_initial_timeout", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0, 1000);
|
||||
RNA_def_property_ui_text(prop, "Recenter Timeout",
|
||||
"Pie menus will use the initial mouse position as center for this amount of time "
|
||||
"(in 1/100ths of sec)");
|
||||
|
||||
prop = RNA_def_property(srna, "pie_animation_timeout", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0, 1000);
|
||||
RNA_def_property_ui_text(prop, "Animation Timeout",
|
||||
"Time needed to fully animate the pie to unfolded state (in 1/100ths of sec)");
|
||||
|
||||
prop = RNA_def_property(srna, "pie_menu_radius", PROP_INT, PROP_PIXEL);
|
||||
RNA_def_property_range(prop, 0, 1000);
|
||||
RNA_def_property_ui_text(prop, "Radius", "Pie menu size in pixels");
|
||||
|
||||
prop = RNA_def_property(srna, "pie_menu_threshold", PROP_INT, PROP_PIXEL);
|
||||
RNA_def_property_range(prop, 0, 1000);
|
||||
RNA_def_property_ui_text(prop, "Threshold", "Distance from center needed before a selection can be made");
|
||||
|
||||
prop = RNA_def_property(srna, "use_quit_dialog", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_QUIT_PROMPT);
|
||||
RNA_def_property_ui_text(prop, "Prompt Quit",
|
||||
|
@@ -594,6 +594,17 @@ static PointerRNA rna_PopupMenu_layout_get(PointerRNA *ptr)
|
||||
return rptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr)
|
||||
{
|
||||
struct uiPieMenu *pie = ptr->data;
|
||||
uiLayout *layout = uiPieMenuLayout(pie);
|
||||
|
||||
PointerRNA rptr;
|
||||
RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr);
|
||||
|
||||
return rptr;
|
||||
}
|
||||
|
||||
static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
|
||||
{
|
||||
wmWindow *win = (wmWindow *)ptr->data;
|
||||
@@ -1716,6 +1727,26 @@ static void rna_def_popupmenu(BlenderRNA *brna)
|
||||
RNA_define_verify_sdna(1); /* not in sdna */
|
||||
}
|
||||
|
||||
static void rna_def_piemenu(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "UIPieMenu", NULL);
|
||||
RNA_def_struct_ui_text(srna, "PieMenu", "");
|
||||
RNA_def_struct_sdna(srna, "uiPieMenu");
|
||||
|
||||
RNA_define_verify_sdna(0); /* not in sdna */
|
||||
|
||||
/* could wrap more, for now this is enough */
|
||||
prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "UILayout");
|
||||
RNA_def_property_pointer_funcs(prop, "rna_PieMenu_layout_get",
|
||||
NULL, NULL, NULL);
|
||||
|
||||
RNA_define_verify_sdna(1); /* not in sdna */
|
||||
}
|
||||
|
||||
static void rna_def_window(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -2078,6 +2109,7 @@ void RNA_def_wm(BlenderRNA *brna)
|
||||
rna_def_event(brna);
|
||||
rna_def_timer(brna);
|
||||
rna_def_popupmenu(brna);
|
||||
rna_def_piemenu(brna);
|
||||
rna_def_window(brna);
|
||||
rna_def_windowmanager(brna);
|
||||
rna_def_keyconfig(brna);
|
||||
|
@@ -310,6 +310,24 @@ static void rna_PupMenuEnd(bContext *C, PointerRNA *handle)
|
||||
uiPupMenuEnd(C, handle->data);
|
||||
}
|
||||
|
||||
/* pie menu wrapper */
|
||||
static PointerRNA rna_PieMenuBegin(bContext *C, const char *title, int icon, PointerRNA *event)
|
||||
{
|
||||
PointerRNA r_ptr;
|
||||
void *data;
|
||||
|
||||
data = (void *)uiPieMenuBegin(C, title, icon, event->data);
|
||||
|
||||
RNA_pointer_create(NULL, &RNA_UIPieMenu, data, &r_ptr);
|
||||
|
||||
return r_ptr;
|
||||
}
|
||||
|
||||
static void rna_PieMenuEnd(bContext *C, PointerRNA *handle)
|
||||
{
|
||||
uiPieMenuEnd(C, handle->data);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define WM_GEN_INVOKE_EVENT (1 << 0)
|
||||
@@ -461,6 +479,26 @@ void RNA_api_wm(StructRNA *srna)
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
|
||||
parm = RNA_def_pointer(func, "menu", "UIPopupMenu", "", "");
|
||||
RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
|
||||
|
||||
/* wrap uiPieMenuBegin */
|
||||
func = RNA_def_function(srna, "piemenu_begin__internal", "rna_PieMenuBegin");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
|
||||
parm = RNA_def_string(func, "title", NULL, 0, "", "");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm = RNA_def_property(func, "icon", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(parm, icon_items);
|
||||
parm = RNA_def_pointer(func, "event", "Event", "", "");
|
||||
RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
|
||||
/* return */
|
||||
parm = RNA_def_pointer(func, "menu_pie", "UIPieMenu", "", "");
|
||||
RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
/* wrap uiPieMenuEnd */
|
||||
func = RNA_def_function(srna, "piemenu_end__internal", "rna_PieMenuEnd");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
|
||||
parm = RNA_def_pointer(func, "menu", "UIPieMenu", "", "");
|
||||
RNA_def_property_flag(parm, PROP_RNAPTR | PROP_NEVER_NULL);
|
||||
}
|
||||
|
||||
void RNA_api_operator(StructRNA *srna)
|
||||
|
@@ -151,7 +151,7 @@ typedef void (*wmUIHandlerRemoveFunc)(struct bContext *C, void *userdata);
|
||||
struct wmEventHandler *WM_event_add_ui_handler(
|
||||
const struct bContext *C, ListBase *handlers,
|
||||
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
|
||||
void *userdata);
|
||||
void *userdata, const bool accept_dbl_click);
|
||||
void WM_event_remove_ui_handler(
|
||||
ListBase *handlers,
|
||||
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
|
||||
|
@@ -64,6 +64,8 @@ wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, in
|
||||
int val, int modifier, int keymodifier);
|
||||
wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type,
|
||||
int val, int modifier, int keymodifier);
|
||||
wmKeyMapItem *WM_keymap_add_menu_pie(struct wmKeyMap *keymap, const char *idname, int type,
|
||||
int val, int modifier, int keymodifier, bool force_click);
|
||||
|
||||
bool WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi);
|
||||
int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, const int len);
|
||||
|
@@ -401,8 +401,12 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve
|
||||
|
||||
/* UI code doesn't handle return values - it just always returns break.
|
||||
* to make the DBL_CLICK conversion work, we just don't send this to UI, except mouse clicks */
|
||||
if (event->type != LEFTMOUSE && event->val == KM_DBL_CLICK)
|
||||
if (((handler->flag & WM_HANDLER_ACCEPT_DBL_CLICK) == 0) &&
|
||||
(event->type != LEFTMOUSE) &&
|
||||
(event->val == KM_DBL_CLICK))
|
||||
{
|
||||
return WM_HANDLER_CONTINUE;
|
||||
}
|
||||
|
||||
/* UI is quite aggressive with swallowing events, like scrollwheel */
|
||||
/* I realize this is not extremely nice code... when UI gets keymaps it can be maybe smarter */
|
||||
@@ -2563,7 +2567,7 @@ void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
|
||||
wmEventHandler *WM_event_add_ui_handler(
|
||||
const bContext *C, ListBase *handlers,
|
||||
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
|
||||
void *userdata)
|
||||
void *userdata, const bool accept_dbl_click)
|
||||
{
|
||||
wmEventHandler *handler = MEM_callocN(sizeof(wmEventHandler), "event ui handler");
|
||||
handler->ui_handle = ui_handle;
|
||||
@@ -2580,6 +2584,9 @@ wmEventHandler *WM_event_add_ui_handler(
|
||||
handler->ui_menu = NULL;
|
||||
}
|
||||
|
||||
if (accept_dbl_click) {
|
||||
handler->flag |= WM_HANDLER_ACCEPT_DBL_CLICK;
|
||||
}
|
||||
|
||||
BLI_addhead(handlers, handler);
|
||||
|
||||
|
@@ -187,6 +187,8 @@ 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);
|
||||
|
||||
|
@@ -464,6 +464,14 @@ wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type,
|
||||
return kmi;
|
||||
}
|
||||
|
||||
wmKeyMapItem *WM_keymap_add_menu_pie(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier, bool force_click)
|
||||
{
|
||||
wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_menu_pie", type, val, modifier, keymodifier);
|
||||
RNA_string_set(kmi->ptr, "name", idname);
|
||||
RNA_boolean_set(kmi->ptr, "force_click", force_click);
|
||||
return kmi;
|
||||
}
|
||||
|
||||
bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
|
||||
{
|
||||
if (BLI_findindex(&keymap->items, kmi) != -1) {
|
||||
|
@@ -2049,6 +2049,41 @@ static void WM_OT_call_menu(wmOperatorType *ot)
|
||||
RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the menu");
|
||||
}
|
||||
|
||||
static int wm_call_pie_menu_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
char idname[BKE_ST_MAXNAME];
|
||||
RNA_string_get(op->ptr, "name", idname);
|
||||
|
||||
uiPieMenuInvoke(C, idname, event);
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void WM_OT_call_menu_pie(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Call Pie Menu";
|
||||
ot->idname = "WM_OT_call_menu_pie";
|
||||
ot->description = "Call (draw) a pre-defined pie menu";
|
||||
|
||||
ot->invoke = wm_call_pie_menu_invoke;
|
||||
ot->exec = wm_call_pie_menu_exec;
|
||||
ot->poll = WM_operator_winactive;
|
||||
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
|
||||
RNA_def_string(ot->srna, "name", NULL, BKE_ST_MAXNAME, "Name", "Name of the pie menu");
|
||||
}
|
||||
|
||||
/* ************ window / screen operator definitions ************** */
|
||||
|
||||
/* this poll functions is needed in place of WM_operator_winactive
|
||||
@@ -4427,6 +4462,7 @@ void wm_operatortype_init(void)
|
||||
WM_operatortype_append(WM_OT_splash);
|
||||
WM_operatortype_append(WM_OT_search_menu);
|
||||
WM_operatortype_append(WM_OT_call_menu);
|
||||
WM_operatortype_append(WM_OT_call_menu_pie);
|
||||
WM_operatortype_append(WM_OT_radial_control);
|
||||
#if defined(WIN32)
|
||||
WM_operatortype_append(WM_OT_console_toggle);
|
||||
|
@@ -81,8 +81,9 @@ enum {
|
||||
|
||||
/* handler flag */
|
||||
enum {
|
||||
WM_HANDLER_BLOCKING = 1, /* after this handler all others are ignored */
|
||||
WM_HANDLER_DO_FREE = 2 /* handler tagged to be freed in wm_handlers_do() */
|
||||
WM_HANDLER_BLOCKING = (1 << 0), /* after this handler all others are ignored */
|
||||
WM_HANDLER_DO_FREE = (1 << 1), /* handler tagged to be freed in wm_handlers_do() */
|
||||
WM_HANDLER_ACCEPT_DBL_CLICK = (1 << 2), /* handler accepts double key press events */
|
||||
};
|
||||
|
||||
/* wm_event_system.c */
|
||||
|
@@ -622,6 +622,13 @@ struct wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idn
|
||||
struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon) RET_NULL
|
||||
void uiPupMenuEnd(struct bContext *C, struct uiPopupMenu *head) RET_NONE
|
||||
struct uiLayout *uiPupMenuLayout(struct uiPopupMenu *head) RET_NULL
|
||||
struct uiLayout *uiPieMenuLayout(struct uiPieMenu *pie) RET_NULL
|
||||
void uiPieMenuInvoke(struct bContext *C, const char *idname, const struct wmEvent *event) RET_NONE
|
||||
struct uiPieMenu *uiPieMenuBegin(struct bContext *C, const char *title, int icon, const struct wmEvent *event) RET_NULL
|
||||
void uiPieMenuEnd(struct bContext *C, uiPieMenu *pie) RET_NONE
|
||||
struct uiLayout *uiLayoutRadial(struct uiLayout *layout) RET_NULL
|
||||
void uiPieOperatorEnumInvoke(struct bContext *C, const char *title, const char *opname,
|
||||
const char *propname, const struct wmEvent *event) RET_NONE
|
||||
|
||||
/* RNA COLLADA dependency */
|
||||
int collada_export(struct Scene *sce,
|
||||
|
Reference in New Issue
Block a user