Compare commits

...

77 Commits

Author SHA1 Message Date
ack-err
3a654c7d0d Did not rename operator properties properly in all cases. 2013-09-19 19:53:48 +00:00
ack-err
13be174b2e Fixed drag and drop for custom panels, added copying of operator properties. Also did minor code cleanup:
* combined add & delete panel icons in the tool shelf
* delete some of my old commented out code
* fixed drop poll for the toolbar
* changed default value for the layout property 'single_unit'
2013-09-19 19:32:49 +00:00
ack-err
7e495c7d87 Failed attempt at refreshing popup blocks in commented code. 2013-09-16 16:00:19 +00:00
ack-err
6d5ba79f58 Incorrectly restored UI_EMBOSS, which caused the pullout buttons on areas to be drawn incorrectly. 2013-09-13 11:48:48 +00:00
ack-err
689c91b05f Adds an option in the right-click menu for dividers to remove the divider from the menubar. 2013-09-13 09:49:49 +00:00
ack-err
51fbcf519c Fixes a small bug whereby an RNA pointer was improperly created. Also removes the option to remove a button from a non-custom panel that was erroneously shown. 2013-09-13 09:07:40 +00:00
ack-err
2750ec3d36 Added an option to pin the operator redo panel. When it is pinned it stays open when the toolbar is closed. 2013-09-12 12:51:54 +00:00
ack-err
f3cd07cd8f Dividers can now be dragged. Buttons display a bit of text if there is no icon yet. 2013-09-12 11:43:52 +00:00
ack-err
6406f0f3c2 Dividers can be folded, but not dragged yet. 2013-09-11 15:14:22 +00:00
ack-err
9cdee6a0bf Added dividers and made the tool shelf context dependent 2013-09-11 12:13:20 +00:00
ack-err
3e77afd1b4 Implemented drag and drop for the icon shelf. Removed code for menubar menus that was commented out. 2013-09-10 18:32:38 +00:00
ack-err
0e15b28abb Small tweaks to the custom panel button dragging. 2013-09-10 12:20:03 +00:00
ack-err
cc5c3c65e4 Added a separate SVG file for operator icons. 2013-09-09 22:59:26 +00:00
ack-err
8ad8c253cf Buttons in the icon shelf are now icon-only. The region and buttons are 1.5 * the normal button size. Adding and removing buttons take into account the operator properties. 2013-09-06 14:32:59 +00:00
ack-err
1fce345840 Custom buttons in the menubar copy over the operator properties from the operator button that was dragged there. 2013-09-06 11:47:28 +00:00
ack-err
29d494d083 When an operator button is dragged the but->opptr is copied to the drag event so that it can then be copied to in the drag&drop copy() functions. 2013-09-05 19:46:41 +00:00
ack-err
6255447154 Started to implement operator to icon pairing.
* wmOperatorType has an extra icon() method that is used to determine which icon to use based on the operator properties set for a button.
* wmOperatorType has a default_icon field, exposed to python as bl_icon, that is used if the icon() function is not set.
* Buttons have to have a but->icon value of ICON_AUTOMATIC, which is -1.
2013-09-05 17:25:26 +00:00
ack-err
1565fbff6f The toolbar did not properly redraw when a panel was hidden in case the region overlap was off. 2013-09-04 15:02:59 +00:00
ack-err
8826b1b187 Hidden panels did not survive a save and load. This fixes that by making sure the panels' types are set. 2013-09-04 14:58:18 +00:00
ack-err
f151c98bde The popup menu to hide panels now shows the toggles in the right order. 2013-09-04 14:40:04 +00:00
ack-err
ca63536a41 Implemented a menu in the toolbar header that allows individual panels to be hidden. 2013-09-04 14:34:09 +00:00
ack-err
a8ee1b7f54 Drag polling and drag operator naming does now respect and prefer overlapping regions. 2013-09-04 11:56:14 +00:00
ack-err
a8db9bcf5f Menu is closed immediately when an operator button is dragged. 2013-09-03 18:31:51 +00:00
ack-err
29acbff903 The operator redo panel now stays open when the toolbar is hidden. This only works when region overlap is turned on in the user preferences. 2013-09-03 15:26:24 +00:00
ack-err
74bcc074af The operator redo panel is in its old place again. The size of it's region is automatically adjusted. 2013-09-03 11:41:18 +00:00
ack-err
53177d1650 Commented out menubar text menus. It now displays only custom buttons. 2013-09-03 09:11:07 +00:00
ack-err
76b91a29f5 Resolved conflicts in icon file. 2013-09-02 18:50:57 +00:00
ack-err
d2815ece39 Merged trunk. 2013-09-02 17:55:22 +00:00
ack-err
db292ba7ac * Tweaked the layout of the toolbar panels, added a compact representation for brush and texture previews, and slightly tweaked the organisation of regions in the view3d. 2013-09-02 16:39:52 +00:00
ack-err
ce1c83a5cf Fixed another strict compilation error, mixed declarations and code. 2013-09-01 15:58:53 +00:00
ack-err
8729239ba6 Fixed a strict compilation error, mixed declarations and code. 2013-09-01 15:51:21 +00:00
ack-err
8a56c889c0 Fixed some compilation errors for strict compilation. 2013-09-01 15:45:56 +00:00
ack-err
bc47687213 Fixed bug whereby bContext wasn't declared. 2013-09-01 15:26:47 +00:00
ack-err
2a38a84df7 Brushes are presented in a more space efficient manner. Color picker is now not a full blown widget, but a simple one.
* Fixed a bug whereby a variable wasn't declared at the start of a block.
2013-08-31 14:07:05 +00:00
ack-err
92d7d11062 Work in progress: polishing and redoing some of the panel layouts for the view3d. 2013-08-30 16:25:56 +00:00
ack-err
facf2cd856 Operator buttons in custom panels can now be reordered by dragging up and down. 2013-08-30 11:54:30 +00:00
ack-err
f6eee435bd Implemented the first parts of the draggable operator buttons for custom panels. 2013-08-29 15:35:59 +00:00
ack-err
b4bff20a41 A bit of cleanup and an extra check so that the option to remove a button does not show up for normal menu entries. 2013-08-28 16:03:56 +00:00
ack-err
9b597b954f Added the option to remove operator buttons from the menubar in the right click menu. 2013-08-28 15:58:36 +00:00
ack-err
329adf15e9 Added the option to remove operator buttons from custom panels in the right click menu. 2013-08-28 15:25:01 +00:00
ack-err
f43a42409c Added a right click menu to the custom panel headers. This can be used to rename a panel and to remove it. 2013-08-28 13:43:34 +00:00
ack-err
548953ebeb Fixed a regression whereby the redo panel's size was lagging behind. 2013-08-27 16:44:11 +00:00
ack-err
82a5690ff0 Not possible to add the same operator twice. Added checks for both drag & drop and the menu. 2013-08-27 16:27:28 +00:00
ack-err
33dd7102ad Redo panel is hidden when the containing area is too small. 2013-08-27 15:43:26 +00:00
ack-err
13e8ede337 Can only add an operator to a custom panel or to the menubar if it isn't already present. 2013-08-27 15:29:14 +00:00
ack-err
12388139f9 Handling notifiers in a better way and removed the redraw loop for the operator redo panel. 2013-08-27 14:19:26 +00:00
ack-err
ee9d4579c1 Positioning of the redo panel is better. There is still a draw loop, which needs to be solved. 2013-08-21 14:37:27 +00:00
ack-err
0fcc95cd99 Added a separate floating operator redo panel. Positioning is not complete. 2013-08-20 18:51:06 +00:00
ack-err
c35efb4b1f Added drop handler for custom panels to the toolbar. N.B. the drop->copy function has changed everywhere so that bContext and wmEvent can be passed to it. 2013-08-20 15:33:36 +00:00
ack-err
20e6c810b7 Added drop handler to the menubar. This makes it possible to drag any operator button to the custom menubar. 2013-08-19 13:41:05 +00:00
ack-err
cecb600a0f Makes operator buttons draggable. 2013-08-19 12:17:31 +00:00
ack-err
d37943d428 Fix for the problem where custom panels would not work as popups. 2013-08-17 17:05:44 +00:00
ack-err
8834459baf Popup panels aren't implemented as an operator anymore. Also, popup panels now KEEP_OPEN. 2013-08-17 13:22:21 +00:00
ack-err
8904c1a031 Custom icon shelf buttons are now context sensitive (i.e. different buttons in different modes). 2013-08-17 12:04:58 +00:00
ack-err
bfca99a84d The custom icons are now in the RGN_TYPE_MENU_BAR instead of in their own region. The menubar region now snaps to once or twice the header size. 2013-08-17 11:54:23 +00:00
ack-err
b67df628f8 Started on custom panels and icon shelf that can be defined at runtime.
* currently saves in blend file
* interface is very rough still
* text-buttons only
* paint/sculpt modes have not yet been transitioned to the menubar approach
2013-08-16 14:12:52 +00:00
ack-err
e436f31e05 Working on custom panels for the toolbars. This adds an operator that adds a PanelType to the current region. 2013-08-12 22:04:10 +00:00
ack-err
94a5d7489f The VIEW3D editor gets an extra, extensive toolbar. The idea is that this frees up space from the left sidebar for tool options and custom panels.
The extra menubar is meant to provide a place for many non-modal operators in a flatter hierarchy than the current header menu (less clicks, better visibility). The left sidebar is then meant to house custom panels and more activity based panels.

* fixed a bug in the undo/operator stack integration code whereby operators were freed in certain cases
* removed Select and Special menus from the header, and placed the underlying menus in the extra toolbar
* removed some of the sidebar panels, will work on replacing these with more activity based panels
* moved all grease pencil buttons and options into a single panel for the toolbar
2013-08-11 12:59:51 +00:00
ack-err
29082fae71 Wasn't cleaning up after myself properly. This fixes memory leaks.
There's still a memory leak that I have to look at more closely:

Error: Not freed memory blocks: 2
Data from SCR len: 336 0x10d8b54b8
Data from SCR len: 272 0x10d8b5648
2013-07-26 16:50:50 +00:00
ack-err
637e66077e Toolbar popup panels work. There are still some bugs with laying out and drawing text. 2013-07-26 16:14:24 +00:00
ack-err
94401da0b7 Small bug fix. Was declaring UndoElem *uel not at the start of the function. 2013-07-26 10:20:02 +00:00
ack-err
599ff8ee92 Drawing little widgets on toolbar panels so that they can be opened in a popup. Handler is a stub for now. The plan is to execute an operator that displays the panel in a popup window. 2013-07-25 18:44:39 +00:00
ack-err
a3c110e800 Added icons for object mode toolbar.
* duplicate
* duplicate linked
* add 
* delete
* ruler

I'm happy for someone to make proper icons for this.
2013-07-25 13:34:35 +00:00
ack-err
e6662f5570 Added shortcut parameter to "operator" function and aligning icon on the left is a shortcut is to be shown, but no label. 2013-07-25 10:34:30 +00:00
ack-err
ecc53fb6f8 Quick experiment to put mode switching buttons at the top of the toolbar. 2013-07-24 18:06:41 +00:00
ack-err
4834fae5d3 Some initial changes to the toolbar. Buttons can be double height, shortcuts show, many panels instead of a few (only object and edit mode). 2013-07-24 15:51:05 +00:00
ack-err
61bfa2b3e8 Extended uiLayout to make it possible to have taller buttons. Buttons in a row or a column layout can be from one to five times the normal height. 2013-07-23 18:33:26 +00:00
ack-err
6a22944311 Quick test to see how to implement default operator properties in a button's right click popup menu.
Some not so nice, rough corners:
* default properties are stored in a wmOperator in wmOperatorType and duplicated in default_properties.
* wmOperators in wmOperatorType aren't cleaned on exit yet.
* the widgets in the popup are not properly aligned.
* lots of properties are ignored upon executing an operator.
2013-07-22 09:32:07 +00:00
ack-err
88728a4b98 Stripping shortcut before adding it again. Without a shortcut appears twice on a button upon a mouse over. 2013-07-21 15:14:33 +00:00
ack-err
1e26319c7b Shortcuts on buttons disappear if the buttons' labels and their shortcuts would overlap. 2013-07-21 15:07:22 +00:00
ack-err
36ac9f4fef Added shortcuts to buttons in regions of type RGN_TYPE_TOOLS.
To do:
* take care of overlapping text
* add a preference to turn showing the shortcuts off
2013-07-21 14:27:19 +00:00
ack-err
74baa2c697 The operator redo panel now uses a two column layout. Labels on the left, widgets on the right. This increases readability and is part of an attempt to minimise scrolling. 2013-07-15 15:25:34 +00:00
ack-err
cd0c7edc99 Properly declaring variables at start of code blocks. 2013-07-07 16:13:36 +00:00
ack-err
15c669d51c Explicitly creating ListBase and assigning its fields before passing to WM_operator_build_stack. 2013-07-07 15:30:27 +00:00
ack-err
95fe4ca034 Keeps the operator stack synchronised with the undo stack so that the redo panel displays the right operator after an undo.
N.B. This is an updated version of patch #35059 in the tracker, which had a nasty bug in it still.

This patch aims to introduce functionality that keeps the two undo stacks (object mode, and edit mode) synchronised with the operator stack in the window manager. This allows for the operator redo panel to be initialised to the last operator that was performed to arrive at the current state after undos and redos are performed. This is achieved by keeping pointers to the operators in the UndoElem structs and rebuilding the wmWindowManager's operator stack after each undo or redo.

The changes throughout the code aim to achieve that a) wmOperator structs are passed to the undo systems to be stored in the UndoElem structures (changes in undo_push_X functions), b) wmOperator structs that are referenced from UndoElem structs are only freed by the undo system, and that c) the operators that are repeated instead of redone (repeat last, repeat from history) are copied rather than moved to the back of the operator stack.

Operators that have a flag OPTYPE_UNDO are registered in the undo system and the undo system is responsible only for these operators. Other operators are freed after application. Even though all OPTYPE_UNDO operators are registered in the undo system, only OPTYPE_REGISTER operators are included when generating the window managers operator stack.

N.B. The following changes aren't very nice and I would like to point them out explicitly.
- The undo system, which is part of blender's core, is now more strongly connected to window managing subsystem than before
- The UndoElem structs (one for object mode undo, and one for edit mode undo) are not exposed, but mapped to a third UndoElem in wm.c. This was done to avoid bringing too much WM logic into blender.c. Better but more involved solutions exist.

Further changes should include doing away with the operator stack entirely and use the undo system as the backend data model for it.
2013-07-05 13:10:53 +00:00
ack-err
115157812c merged trunk 2013-07-01 13:30:19 +00:00
8929c1f33d gsoc 2013 branch soc-2013-ui_replay 2013-06-12 04:05:18 +00:00
87 changed files with 51942 additions and 823 deletions

View File

@@ -6,3 +6,6 @@ BASEDIR=$(dirname $0)
inkscape $BASEDIR/blender_icons.svg --export-dpi=90 --without-gui --export-png=$BASEDIR/blender_icons16.png
inkscape $BASEDIR/blender_icons.svg --export-dpi=180 --without-gui --export-png=$BASEDIR/blender_icons32.png
inkscape $BASEDIR/blender_operator_icons.svg --export-dpi=90 --without-gui --export-png=$BASEDIR/blender_operator_icons16.png
inkscape $BASEDIR/blender_operator_icons.svg --export-dpi=180 --without-gui --export-png=$BASEDIR/blender_operator_icons32.png

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

View File

@@ -743,6 +743,10 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
filter_ext=lambda ext: ext.lower() in {".py", ".xml"})
class MenuBar(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
class Region(StructRNA):
__slots__ = ()

View File

@@ -76,6 +76,7 @@ _modules = [
"space_userpref",
"space_view3d",
"space_view3d_toolbar",
"space_view3d_menubar",
]
import bpy

View File

@@ -73,39 +73,45 @@ class UnifiedPaintPanel():
def brush_texture_settings(layout, brush, sculpt):
tex_slot = brush.texture_slot
layout.label(text="Brush Mapping:")
col = layout.column(align=True)
row = col.row()
row.label(text="Mapping:")
# map_mode
if sculpt:
layout.row().prop(tex_slot, "map_mode", text="")
layout.separator()
row.prop(tex_slot, "map_mode", text="")
else:
layout.row().prop(tex_slot, "tex_paint_map_mode", text="")
layout.separator()
row.prop(tex_slot, "tex_paint_map_mode", text="")
if tex_slot.map_mode == 'STENCIL':
if brush.texture and brush.texture.type == 'IMAGE':
layout.operator("brush.stencil_fit_image_aspect")
layout.operator("brush.stencil_reset_transform")
col.separator()
# angle and texture_angle_source
col = layout.column()
col.active = brush.brush_capabilities.has_texture_angle_source
col.label(text="Angle:")
row = col.row()
row.active = brush.brush_capabilities.has_texture_angle_source
row.label(text="Angle:")
sub = row.column()
if brush.brush_capabilities.has_random_texture_angle:
if sculpt:
if brush.sculpt_capabilities.has_random_texture_angle:
col.prop(brush, "texture_angle_source_random", text="")
sub.prop(brush, "texture_angle_source_random", text="")
else:
col.prop(brush, "texture_angle_source_no_random", text="")
sub.prop(brush, "texture_angle_source_no_random", text="")
else:
col.prop(brush, "texture_angle_source_random", text="")
sub.prop(brush, "texture_angle_source_random", text="")
else:
col.prop(brush, "texture_angle_source_no_random", text="")
col = layout.column()
col.active = brush.brush_capabilities.has_texture_angle
col.prop(tex_slot, "angle", text="")
sub.prop(brush, "texture_angle_source_no_random", text="")
# row = layout.column()
sub.active = brush.brush_capabilities.has_texture_angle
sub.prop(tex_slot, "angle", text="")
col = layout.column(align=True)
col.separator()
if tex_slot.map_mode == 'STENCIL':
if brush.texture and brush.texture.type == 'IMAGE':
col.operator("brush.stencil_fit_image_aspect")
col.operator("brush.stencil_reset_transform")
# scale and offset
split = layout.split()

View File

@@ -37,7 +37,7 @@ class INFO_HT_header(Header):
if context.area.show_menus:
sub = row.row(align=True)
sub.menu("INFO_MT_file")
sub.menu("INFO_MT_add")
# sub.menu("INFO_MT_add")
if rd.use_game_engine:
sub.menu("INFO_MT_game")
else:

File diff suppressed because it is too large Load Diff

View File

@@ -28,16 +28,24 @@ class View3DPanel():
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
# ********** common tools for two or more modes ****************
# **************** standard tool clusters ******************
def history_panel(mode):
class cls(View3DPanel, Panel):
bl_context = mode
bl_label = "History"
# History/Repeat tools
def draw_repeat_tools(context, layout):
col = layout.column(align=True)
col.label(text="Repeat:")
col.operator("screen.repeat_last")
col.operator("screen.repeat_history", text="History...")
def draw(self, context):
layout = self.layout
# col = layout.column(align=True, button_height=1.5)
# col.operator("screen.redo_last", text="Change last")
col = layout.column(align=True)
col.operator("screen.repeat_last")
col.operator("screen.repeat_history", text="History...")
cls.__name__ = "VIEW3D_PT_tools_%s_history" % mode
return cls
# Keyframing tools
def draw_keyframing_tools(context, layout):
@@ -47,76 +55,74 @@ def draw_keyframing_tools(context, layout):
row.operator("anim.keyframe_insert_menu", text="Insert")
row.operator("anim.keyframe_delete_v3d", text="Remove")
# Grease Pencil tools
def draw_gpencil_tools(context, layout):
col = layout.column(align=True)
col.label(text="Grease Pencil:")
row = col.row(align=True)
row.operator("gpencil.draw", text="Draw").mode = 'DRAW'
row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
row = col.row(align=True)
row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY'
row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
row = col.row(align=True)
row.prop(context.tool_settings, "use_grease_pencil_sessions")
col.operator("view3d.ruler")
# ********** default tools for object-mode ****************
class VIEW3D_PT_tools_objectmode(View3DPanel, Panel):
# VIEW3D_PT_tools_objectmode_modes = switch_panel("objectmode");
class VIEW3D_PT_tools_objectmode_transform(View3DPanel, Panel):
bl_context = "objectmode"
bl_label = "Object Tools"
bl_label = "Transform"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.label(text="Transform:")
col.operator("transform.translate")
col.operator("transform.rotate")
col.operator("transform.resize", text="Scale")
col = layout.column(align=True)
row = col.row(align=True, button_height=1.5)
row.operator("transform.translate", text="", single_unit=False, icon='MAN_TRANS', shortcut=False)
row.operator("transform.rotate", text="", single_unit=False, icon='MAN_ROT', shortcut=False)
row.operator("transform.resize", text="", single_unit=False, icon='MAN_SCALE', shortcut=False)
col.operator("object.origin_set", text="Origin")
class VIEW3D_PT_tools_objectmode_add(View3DPanel, Panel):
bl_context = "objectmode"
bl_label = "Add & Delete"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.label(text="Object:")
col.operator("object.duplicate_move")
col.operator("object.delete")
row = col.row(align=True, button_height=1.5)
row.operator("wm.call_menu", text="", single_unit=False, shortcut=False, icon='ADD').name = 'INFO_MT_add'
row.operator("object.duplicate_move", text="", shortcut=False, single_unit=False, icon='DUP')
row.operator("object.duplicate_move_linked", text="", shortcut=False, single_unit=False, icon='DUP_LINKED')
row.operator("object.delete", text="", shortcut=False, single_unit=False, icon='DELETE')
col = layout.column(align=True)
col.operator("object.join")
active_object = context.active_object
if active_object and active_object.type in {'MESH', 'CURVE', 'SURFACE'}:
class VIEW3D_PT_tools_objectmode_adjust(View3DPanel, Panel):
bl_context = "objectmode"
bl_label = "Adjust"
col = layout.column(align=True)
col.label(text="Shading:")
row = col.row(align=True)
row.operator("object.shade_smooth", text="Smooth")
row.operator("object.shade_flat", text="Flat")
def draw(self, context):
layout = self.layout
#active_object = context.active_object
#if active_object and active_object.type in {'MESH', 'CURVE', 'SURFACE'}:
col = layout.column(align=True)
col.operator("object.shade_smooth", text="Shade smooth")
col.operator("object.shade_flat", text="Shade flat")
VIEW3D_PT_tools_objectmode_history = history_panel("objectmode")
draw_keyframing_tools(context, layout)
class VIEW3D_PT_tools_objectmode_animation(View3DPanel, Panel):
bl_context = "objectmode"
bl_label = "Animation"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.label(text="Motion Paths:")
row = col.row(align=True)
row.operator("object.paths_calculate", text="Calculate")
row.operator("object.paths_clear", text="Clear")
row = col.row(align=True, button_height=1.5)
draw_repeat_tools(context, layout)
draw_gpencil_tools(context, layout)
row.operator("anim.keyframe_insert_menu", text="", single_unit=False, shortcut=False, icon='KEY_HLT')
row.operator("anim.keyframe_delete_v3d", text="", single_unit=False, shortcut=False, icon='KEY_DEHLT')
col.operator("object.paths_calculate", text="Calculate motion")
col.operator("object.paths_clear", text="Clear motion")
class VIEW3D_PT_tools_rigidbody(View3DPanel, Panel):
bl_context = "objectmode"
bl_label = "Rigid Body Tools"
bl_label = "Rigid Body"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
@@ -139,86 +145,118 @@ class VIEW3D_PT_tools_rigidbody(View3DPanel, Panel):
col.label(text="Constraints:")
col.operator("rigidbody.connect", text="Connect")
# ********** default tools for editmode_mesh ****************
# VIEW3D_PT_tools_editmode_modes = switch_panel("mesh_edit");
class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
class VIEW3D_PT_tools_editmode_transform(View3DPanel, Panel):
bl_context = "mesh_edit"
bl_label = "Mesh Tools"
bl_label = "Transform"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.label(text="Transform:")
col.operator("transform.translate")
col.operator("transform.rotate")
col.operator("transform.resize", text="Scale")
row = col.row(align=True, button_height=1.5)
row.operator("transform.translate", text="", single_unit=False, icon='MAN_TRANS', shortcut=False)
row.operator("transform.rotate", text="", single_unit=False, icon='MAN_ROT', shortcut=False)
row.operator("transform.resize", text="", single_unit=False, icon='MAN_SCALE', shortcut=False)
col.operator("transform.shrink_fatten", text="Shrink/Fatten")
col.operator("transform.push_pull", text="Push/Pull")
col = layout.column(align=True)
col.label(text="Deform:")
row = col.row(align=True)
row.operator("transform.edge_slide", text="Slide Edge")
row.operator("transform.vert_slide", text="Vertex")
col.operator("mesh.noise")
col.operator("mesh.vertices_smooth")
col.operator("transform.edge_slide", text="Slide edge")
col.operator("transform.vert_slide", text="Slide vertex")
col = layout.column(align=True)
col.label(text="Add:")
col.operator("mesh.vertices_smooth", text="Smooth vertices")
col.menu("VIEW3D_MT_edit_mesh_extrude")
col.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Region")
col.operator("view3d.edit_mesh_extrude_individual_move", text="Extrude Individual")
col.operator("mesh.subdivide")
col.operator("mesh.loopcut_slide")
col.operator("mesh.duplicate_move", text="Duplicate")
row = col.row(align=True)
row.operator("mesh.spin")
row.operator("mesh.screw")
class VIEW3D_PT_tools_editmode_add(View3DPanel, Panel):
bl_context = "mesh_edit"
bl_label = "Add & Delete"
row = col.row(align=True)
props = row.operator("mesh.knife_tool", text="Knife")
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
row = col.row(align=True, button_height=1.5)
row.operator("wm.call_menu", text="", single_unit=False, shortcut=False, icon='ADD').name = 'INFO_MT_mesh_add'
row.operator("mesh.duplicate_move", text="", single_unit=False, shortcut=False, icon='DUP')
row.operator("wm.call_menu", text="", single_unit=False, shortcut=False, icon='DELETE').name = 'VIEW3D_MT_edit_mesh_delete'
class VIEW3D_PT_tools_editmode_mesh(View3DPanel, Panel):
bl_context = "mesh_edit"
bl_label = "Mesh"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
row = col.row(align=True, button_height=1.5)
row.operator("view3d.edit_mesh_extrude_move_normal", text="", single_unit=False, shortcut=False)
row.operator("view3d.edit_mesh_extrude_individual_move", text="", single_unit=False, shortcut=False)
col.operator("wm.call_menu", text="Extrude...", single_unit=False, shortcut=False).name = 'VIEW3D_MT_edit_mesh_extrude'
col = layout.column(align=True)
row = col.row(align=True, button_height=1.5)
props = row.operator("mesh.knife_tool", text="", single_unit=False, shortcut=False, icon='KNIFE')
props.use_occlude_geometry = True
props.only_selected = False
props = row.operator("mesh.knife_tool", text="Select")
row.operator("mesh.loopcut_slide", text="", single_unit=False, shortcut=False, icon='LOOPCUT')
props = col.operator("mesh.knife_tool", text="Knife select")
props.use_occlude_geometry = False
props.only_selected = True
col.operator("mesh.knife_project")
col.operator("mesh.bisect")
col.operator("mesh.subdivide")
col.operator("mesh.spin")
col.operator("mesh.screw")
col.operator("mesh.bisect") # NOTE: new op?
col = layout.column(align=True)
col.label(text="Remove:")
col.menu("VIEW3D_MT_edit_mesh_delete")
col.operator_menu_enum("mesh.merge", "type")
col.operator("mesh.remove_doubles")
# col.operator_enum("mesh.merge", "type")
col.operator("mesh.merge", text="Merge...")
class VIEW3D_PT_tools_editmode_adjust(View3DPanel, Panel):
bl_context = "mesh_edit"
bl_label = "Adjust"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.operator("mesh.faces_shade_smooth", text="Smooth faces")
col.operator("mesh.faces_shade_flat", text="Flat faces")
col = layout.column(align=True)
col.label(text="Normals:")
col.operator("mesh.normals_make_consistent", text="Recalculate")
col.operator("mesh.flip_normals", text="Flip Direction")
col.operator("mesh.normals_make_consistent", text="Recalculate normals")
col.operator("mesh.flip_normals", text="Flip normals")
class VIEW3D_PT_tools_editmode_uv(View3DPanel, Panel):
bl_context = "mesh_edit"
bl_label = "UV & Seams"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.label(text="UV Mapping:")
col.menu("VIEW3D_MT_uv_map", text="Unwrap")
col.operator("mesh.mark_seam").clear = False
col.operator("mesh.mark_seam", text="Clear Seam").clear = True
col.operator("wm.call_menu", text="Unwrap...", single_unit=False, shortcut=False).name = 'VIEW3D_MT_uv_map'
col.operator("mesh.mark_seam", text="Mark seam").clear = False
col.operator("mesh.mark_seam", text="Clear seam").clear = True
col = layout.column(align=True)
col.label(text="Shading:")
row = col.row(align=True)
row.operator("mesh.faces_shade_smooth", text="Smooth")
row.operator("mesh.faces_shade_flat", text="Flat")
draw_repeat_tools(context, layout)
draw_gpencil_tools(context, layout)
VIEW3D_PT_tools_editmode_history = history_panel("mesh_edit")
# print(VIEW3D_PT_tools_editmode_history.bl_context)
class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
bl_context = "mesh_edit"
bl_label = "Mesh Options"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
@@ -252,6 +290,7 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
# ********** default tools for editmode_curve ****************
# VIEW3D_PT_tools_curvemode_modes = switch_panel("curve_edit");
class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
bl_context = "curve_edit"
@@ -300,6 +339,7 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
# ********** default tools for editmode_surface ****************
# VIEW3D_PT_tools_surfacemode_modes = switch_panel("surface_edit");
class VIEW3D_PT_tools_surfaceedit(View3DPanel, Panel):
bl_context = "surface_edit"
@@ -332,6 +372,7 @@ class VIEW3D_PT_tools_surfaceedit(View3DPanel, Panel):
# ********** default tools for editmode_text ****************
# VIEW3D_PT_tools_textmode_modes = switch_panel("text_edit");
class VIEW3D_PT_tools_textedit(View3DPanel, Panel):
bl_context = "text_edit"
@@ -362,6 +403,7 @@ class VIEW3D_PT_tools_textedit(View3DPanel, Panel):
# ********** default tools for editmode_armature ****************
# VIEW3D_PT_tools_armaturemode_modes = switch_panel("armature_edit");
class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
bl_context = "armature_edit"
@@ -391,7 +433,6 @@ class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
draw_gpencil_tools(context, layout)
class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
bl_context = "armature_edit"
bl_label = "Armature Options"
@@ -403,6 +444,7 @@ class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
# ********** default tools for editmode_mball ****************
# VIEW3D_PT_tools_mballmode_modes = switch_panel("mball_edit");
class VIEW3D_PT_tools_mballedit(View3DPanel, Panel):
bl_context = "mball_edit"
@@ -423,6 +465,7 @@ class VIEW3D_PT_tools_mballedit(View3DPanel, Panel):
# ********** default tools for editmode_lattice ****************
# VIEW3D_PT_tools_latticemode_modes = switch_panel("lattice_edit");
class VIEW3D_PT_tools_latticeedit(View3DPanel, Panel):
bl_context = "lattice_edit"
@@ -444,9 +487,9 @@ class VIEW3D_PT_tools_latticeedit(View3DPanel, Panel):
draw_gpencil_tools(context, layout)
# ********** default tools for pose-mode ****************
# VIEW3D_PT_tools_posemode_modes = switch_panel("posemode");
class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
bl_context = "posemode"
@@ -489,7 +532,6 @@ class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
draw_gpencil_tools(context, layout)
class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
bl_context = "posemode"
bl_label = "Pose Options"
@@ -501,12 +543,14 @@ class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
# ********** default tools for paint modes ****************
# VIEW3D_PT_tools_imagepaint_modes = switch_panel("imagepaint");
# VIEW3D_PT_tools_weightpaint_modes = switch_panel("weightpaint");
# VIEW3D_PT_tools_vertexpaint_modes = switch_panel("vertexpaint");
class View3DPaintPanel(UnifiedPaintPanel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
bl_label = "Brush"
@@ -523,6 +567,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
if not context.particle_edit_object:
col = layout.split().column()
# col.template_ID_preview_compact(settings, "brush", new="brush.add", rows=5, cols=8)
col.template_ID_preview(settings, "brush", new="brush.add", rows=3, cols=8)
# Particle Mode #
@@ -532,7 +577,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
layout.column().prop(settings, "tool", expand=True)
if tool != 'NONE':
col = layout.column()
col = layout.column(align=True)
col.prop(brush, "size", slider=True)
if tool != 'ADD':
col.prop(brush, "strength", slider=True)
@@ -556,7 +601,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
elif context.sculpt_object and brush:
capabilities = brush.sculpt_capabilities
col = layout.column()
col = layout.column(align=True)
col.separator()
@@ -575,7 +620,6 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# strength, use_strength_pressure, and use_strength_attenuation
if capabilities.has_strength:
col.separator()
row = col.row(align=True)
if capabilities.has_space_attenuation:
@@ -589,27 +633,22 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# auto_smooth_factor and use_inverse_smooth_pressure
if capabilities.has_auto_smooth:
col.separator()
row = col.row(align=True)
row.prop(brush, "auto_smooth_factor", slider=True)
row.prop(brush, "use_inverse_smooth_pressure", toggle=True, text="")
# normal_weight
if capabilities.has_normal_weight:
col.separator()
row = col.row(align=True)
row.prop(brush, "normal_weight", slider=True)
# crease_pinch_factor
if capabilities.has_pinch_factor:
col.separator()
row = col.row(align=True)
row.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
# use_original_normal and sculpt_plane
if capabilities.has_sculpt_plane:
col.separator()
row = col.row(align=True)
if brush.use_original_normal:
@@ -624,7 +663,6 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# plane_offset, use_offset_pressure, use_plane_trim, plane_trim
if capabilities.has_plane_offset:
row = col.row(align=True)
row.prop(brush, "plane_offset", slider=True)
row.prop(brush, "use_offset_pressure", text="")
@@ -674,14 +712,11 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.operator("sculpt.set_persistent_base")
col = layout.column(align=True)
col.label(text="Overlay:")
row = col.row(align=True)
if brush.use_cursor_overlay:
row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
else:
row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
row.prop(brush, "use_cursor_overlay", toggle=True, text="",
icon=('RESTRICT_VIEW_OFF' if brush.use_cursor_overlay else 'RESTRICT_VIEW_ON'))
sub = row.row(align=True)
sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
@@ -695,6 +730,8 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.template_color_picker(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
col = layout.column(align=True)
row = col.row(align=True)
self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
self.prop_unified_size(row, context, brush, "use_pressure_size")
@@ -703,29 +740,26 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_strength(row, context, brush, "strength", text="Strength")
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
col.prop(brush, "blend", text="Blend")
col.prop(brush, "blend", text="")
col = layout.column()
col.active = (brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'})
col.prop(brush, "use_alpha")
col.prop(brush, "use_alpha", text="Use Alpha")
col = layout.column(align=True)
col.label(text="Overlay:")
row = col.row(align=True)
if brush.use_cursor_overlay:
row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
else:
row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
row.prop(brush, "use_cursor_overlay", toggle=True, text="",
icon=('RESTRICT_VIEW_OFF' if brush.use_cursor_overlay else 'RESTRICT_VIEW_ON'))
sub = row.row(align=True)
sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
sub.prop(brush, "cursor_overlay_alpha", text="Overlay")
sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
# Weight Paint Mode #
elif context.weight_paint_object and brush:
col = layout.column()
col = layout.column(align=True)
row = col.row(align=True)
self.prop_unified_weight(row, context, brush, "weight", slider=True, text="Weight")
@@ -738,9 +772,9 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_strength(row, context, brush, "strength", text="Strength")
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
col.prop(brush, "vertex_tool", text="Blend")
col.prop(brush, "vertex_tool", text="")
col = layout.column()
col = layout.column(align=True)
col.prop(toolsettings, "use_auto_normalize", text="Auto Normalize")
col.prop(toolsettings, "use_multipaint", text="Multi-Paint")
@@ -750,6 +784,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.template_color_picker(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
col = layout.column(align=True)
row = col.row(align=True)
self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
self.prop_unified_size(row, context, brush, "use_pressure_size")
@@ -758,27 +793,24 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_strength(row, context, brush, "strength", text="Strength")
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
col.prop(brush, "vertex_tool", text="")
# XXX - TODO
#row = col.row(align=True)
#row.prop(brush, "jitter", slider=True)
#row.prop(brush, "use_pressure_jitter", toggle=True, text="")
col.prop(brush, "vertex_tool", text="Blend")
col = layout.column(align=True)
col.label(text="Overlay:")
# col.label(text="Overlay:")
row = col.row(align=True)
if brush.use_cursor_overlay:
row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
else:
row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
row.prop(brush, "use_cursor_overlay", toggle=True, text="",
icon=('RESTRICT_VIEW_OFF' if brush.use_cursor_overlay else 'RESTRICT_VIEW_ON'))
sub = row.row(align=True)
sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
sub.prop(brush, "cursor_overlay_alpha", text="Overlay")
sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
bl_label = "Texture"
bl_options = {'DEFAULT_CLOSED'}
@@ -798,65 +830,27 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
col = layout.column()
col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
col.template_ID_preview_compact(brush, "texture", new="texture.new", rows=3, cols=8)
col.separator()
brush_texture_settings(col, brush, context.sculpt_object)
# use_texture_overlay and texture_overlay_alpha
col = layout.column(align=True)
col.active = brush.brush_capabilities.has_overlay
col.label(text="Overlay:")
row = col.row(align=True)
if tex_slot.map_mode != 'STENCIL':
if brush.use_primary_overlay:
row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
else:
row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
row.prop(brush, "use_primary_overlay", toggle=True, text="",
icon='RESTRICT_VIEW_OFF' if brush.use_primary_overlay else 'RESTRICT_VIEW_ON')
sub = row.row(align=True)
sub.prop(brush, "texture_overlay_alpha", text="Alpha")
sub.prop(brush, "texture_overlay_alpha", text="Overlay")
sub.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
bl_context = "imagepaint"
bl_label = "Texture Mask"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
brush = context.tool_settings.image_paint.brush
return (context.image_paint_object and brush)
def draw(self, context):
layout = self.layout
brush = context.tool_settings.image_paint.brush
tex_slot_alpha = brush.mask_texture_slot
col = layout.column()
col.template_ID_preview(brush, "mask_texture", new="texture.new", rows=3, cols=8)
brush_mask_texture_settings(col, brush)
col = layout.column(align=True)
col.active = brush.brush_capabilities.has_overlay
col.label(text="Overlay:")
row = col.row(align=True)
if tex_slot_alpha.map_mode != 'STENCIL':
if brush.use_secondary_overlay:
row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
else:
row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
sub = row.row(align=True)
sub.prop(brush, "mask_overlay_alpha", text="Alpha")
sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
bl_label = "Stroke"
bl_options = {'DEFAULT_CLOSED'}
@@ -879,31 +873,34 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
col = layout.column()
col.label(text="Stroke Method:")
row = col.row()
row.label(text="Method:")
if context.sculpt_object:
col.prop(brush, "sculpt_stroke_method", text="")
row.prop(brush, "sculpt_stroke_method", text="")
else:
col.prop(brush, "stroke_method", text="")
row.prop(brush, "stroke_method", text="")
col = layout.column(align=True)
if brush.use_anchor:
col.separator()
# col.separator()
col.prop(brush, "use_edge_to_edge", "Edge To Edge")
if brush.use_airbrush:
col.separator()
# col.separator()
col.prop(brush, "rate", text="Rate", slider=True)
if brush.use_space:
col.separator()
# col.separator()
row = col.row(align=True)
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
# col.separator()
if context.sculpt_object:
if brush.sculpt_capabilities.has_jitter:
col.separator()
row = col.row(align=True)
if brush.use_relative_jitter:
@@ -914,9 +911,9 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
row.prop(brush, "jitter_absolute")
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
if brush.sculpt_capabilities.has_smooth_stroke:
col = layout.column()
# smooth stroke
col = layout.column(align=True)
col.separator()
col.prop(brush, "use_smooth_stroke")
sub = col.column()
@@ -924,8 +921,6 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
else:
col.separator()
row = col.row(align=True)
if brush.use_relative_jitter:
row.prop(brush, "use_relative_jitter", text="", icon='LOCKED')
@@ -935,7 +930,8 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
row.prop(brush, "jitter_absolute")
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
col = layout.column()
# smooth stroke
col = layout.column(align=True)
col.separator()
col.prop(brush, "use_smooth_stroke")
@@ -945,7 +941,6 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
bl_label = "Curve"
bl_options = {'DEFAULT_CLOSED'}
@@ -972,6 +967,42 @@ class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
bl_context = "imagepaint"
bl_label = "Texture Mask"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
brush = context.tool_settings.image_paint.brush
return (context.image_paint_object and brush)
def draw(self, context):
layout = self.layout
brush = context.tool_settings.image_paint.brush
tex_slot_alpha = brush.mask_texture_slot
col = layout.column()
col.template_ID_preview(brush, "mask_texture", new="texture.new", rows=3, cols=8)
brush_mask_texture_settings(col, brush)
col = layout.column(align=True)
col.active = brush.brush_capabilities.has_overlay
col.label(text="Overlay:")
row = col.row()
if tex_slot_alpha.map_mode != 'STENCIL':
if brush.use_secondary_overlay:
row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
else:
row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
sub = row.row()
sub.prop(brush, "mask_overlay_alpha", text="Alpha")
sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
class VIEW3D_PT_sculpt_topology(Panel, View3DPaintPanel):
bl_label = "Topology"
@@ -1002,7 +1033,6 @@ class VIEW3D_PT_sculpt_topology(Panel, View3DPaintPanel):
col.prop(sculpt, "symmetrize_direction")
col.operator("sculpt.symmetrize")
class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
@@ -1032,7 +1062,6 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
self.unified_paint_settings(layout, context)
class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
bl_label = "Symmetry"
bl_options = {'DEFAULT_CLOSED'}
@@ -1056,7 +1085,6 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
layout.column().prop(sculpt, "radial_symmetry", text="Radial")
layout.prop(sculpt, "use_symmetry_feather", text="Feather")
class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
bl_label = "Appearance"
bl_options = {'DEFAULT_CLOSED'}
@@ -1103,7 +1131,6 @@ class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
# ********** default tools for weight-paint ****************
class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
bl_context = "weightpaint"
bl_label = "Weight Tools"
@@ -1111,7 +1138,7 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
def draw(self, context):
layout = self.layout
col = layout.column()
col = layout.column(align=True)
col.operator("object.vertex_group_normalize_all", text="Normalize All")
col.operator("object.vertex_group_normalize", text="Normalize")
col.operator("object.vertex_group_mirror", text="Mirror")
@@ -1124,10 +1151,10 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
col.operator("object.vertex_group_fix", text="Fix Deforms")
col.operator("paint.weight_gradient")
class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
bl_context = "weightpaint"
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
@@ -1161,10 +1188,10 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
# ********** default tools for vertex-paint ****************
class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
class VIEW3D_PT_tools_vertexpaint_options(Panel, View3DPaintPanel):
bl_context = "vertexpaint"
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
@@ -1252,7 +1279,6 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
col.operator("paint.project_image", text="Apply Camera Image")
col.operator("image.save_dirty", text="Save All Edited")
class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
@@ -1267,7 +1293,6 @@ class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
col = layout.column()
self.unified_paint_settings(col, context)
class VIEW3D_MT_tools_projectpaint_clone(Menu):
bl_label = "Clone Layer"
@@ -1279,7 +1304,6 @@ class VIEW3D_MT_tools_projectpaint_clone(Menu):
props.data_path = "active_object.data.uv_texture_clone_index"
props.value = i
class VIEW3D_MT_tools_projectpaint_stencil(Menu):
bl_label = "Mask Layer"
@@ -1290,7 +1314,6 @@ class VIEW3D_MT_tools_projectpaint_stencil(Menu):
props.data_path = "active_object.data.uv_texture_stencil_index"
props.value = i
class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
"""Default tools for particle mode"""
bl_context = "particlemode"

View File

@@ -62,6 +62,7 @@ struct ReportList;
struct Scene;
struct Main;
struct ID;
struct wmOperator;
int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *reports);
@@ -91,10 +92,12 @@ int blender_test_break(void);
/* global undo */
extern void BKE_write_undo(struct bContext *C, const char *name);
extern void BKE_write_undo_op(struct bContext *C, const char *name, struct wmOperator *op);
extern void BKE_undo_step(struct bContext *C, int step);
extern void BKE_undo_op(struct bContext *C, const struct wmOperator *op);
extern void BKE_undo_name(struct bContext *C, const char *name);
extern int BKE_undo_valid(const char *name);
extern void BKE_reset_undo(void);
extern void BKE_reset_undo(struct bContext *C);
extern void BKE_undo_number(struct bContext *C, int nr);
extern const char *BKE_undo_get_name(int nr, int *active);
extern int BKE_undo_save_file(const char *filename);

View File

@@ -36,6 +36,7 @@
struct ARegion;
struct Header;
struct ListBase;
struct OperatorListItem;
struct Menu;
struct Panel;
struct Scene;
@@ -150,6 +151,9 @@ typedef struct ARegionType {
/* header type definitions */
ListBase headertypes;
/* toolbar menu type definitions */
ListBase menubartypes;
/* hardcoded constraints, smaller than these values region is not visible */
int minsizex, minsizey;
/* when new region opens (region prefsizex/y are zero then */
@@ -257,6 +261,29 @@ typedef struct Menu {
struct uiLayout *layout; /* runtime for drawing */
} Menu;
/* menu bar types */
typedef struct MenuBar {
struct MenuBarType *type; /* runtime */
struct uiLayout *layout; /* runtime for drawing */
} MenuBar;
typedef struct MenuBarType {
struct MenuBarType *next, *prev;
char idname[BKE_ST_MAXNAME]; /* unique name */
char context[BKE_ST_MAXNAME];
int space_type;
int region_type;
/* draw entirely, view changes should be handled here */
void (*draw)(const struct bContext *, struct MenuBar *);
/* RNA integration */
ExtensionRNA ext;
} MenuBarType;
/* spacetypes */
struct SpaceType *BKE_spacetype_from_id(int spaceid);
struct ARegionType *BKE_regiontype_from_id(struct SpaceType *st, int regionid);
@@ -277,6 +304,7 @@ void BKE_screen_area_free(struct ScrArea *sa);
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
struct ARegion *BKE_spacelink_find_region_type(struct SpaceLink *sl, int type);
struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min);
void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene);
@@ -291,5 +319,8 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac);
void BKE_screen_free(struct bScreen *sc);
unsigned int BKE_screen_visible_layers(struct bScreen *screen, struct Scene *scene);
/* custom operator button items */
void BKE_operator_list_item_free(struct OperatorListItem *oli);
#endif

View File

@@ -94,6 +94,7 @@
#include "RNA_access.h"
#include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie
#include "WM_types.h" // This is temporarily necessary until the undo stacks are integrated and operators are an integral part of it ~ ack-err
#include "IMB_colormanagement.h"
@@ -558,8 +559,11 @@ int blender_test_break(void)
#define UNDO_DISK 0
/* N.B. the pointer to the wmOperator needs to be third so that it
* maps correctly to the UndoElem in wm.c. This is far from pretty. */
typedef struct UndoElem {
struct UndoElem *next, *prev;
wmOperator * op;
char str[FILE_MAX];
char name[BKE_UNDO_STR_MAX];
MemFile memfile;
@@ -574,6 +578,7 @@ static int read_undosave(bContext *C, UndoElem *uel)
{
char mainstr[sizeof(G.main->name)];
int success = 0, fileflags;
ListBase included_ops;
/* This is needed so undoing/redoing doesn't crash with threaded previews going */
WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C));
@@ -592,6 +597,10 @@ static int read_undosave(bContext *C, UndoElem *uel)
BLI_strncpy(G.main->name, mainstr, sizeof(G.main->name)); /* restore */
G.fileflags = fileflags;
included_ops.first = undobase.first;
included_ops.last = uel;
WM_operator_build_stack(C, &included_ops, true);
if (success) {
/* important not to update time here, else non keyed tranforms are lost */
DAG_on_visible_update(G.main, FALSE);
@@ -600,13 +609,18 @@ static int read_undosave(bContext *C, UndoElem *uel)
return success;
}
/* name can be a dynamic string */
void BKE_write_undo(bContext *C, const char *name)
{
BKE_write_undo_op(C, name, NULL);
}
/* name can be a dynamic string */
void BKE_write_undo_op(bContext *C, const char *name, wmOperator *op)
{
uintptr_t maxmem, totmem, memused;
int nr /*, success */ /* UNUSED */;
UndoElem *uel;
if ((U.uiflag & USER_GLOBALUNDO) == 0) {
return;
}
@@ -620,6 +634,10 @@ void BKE_write_undo(bContext *C, const char *name)
uel = undobase.last;
BLI_remlink(&undobase, uel);
BLO_free_memfile(&uel->memfile);
/* Don't remove the op if it is a repeat, and the
* uel->op is the same as the function's argument op. */
if(uel->op && uel->op != op)
WM_operator_free(uel->op);
MEM_freeN(uel);
}
@@ -627,6 +645,9 @@ void BKE_write_undo(bContext *C, const char *name)
curundo = uel = MEM_callocN(sizeof(UndoElem), "undo file");
BLI_strncpy(uel->name, name, sizeof(uel->name));
BLI_addtail(&undobase, uel);
if (op && op->type && op->type->flag & OPTYPE_REGISTER && op->type->flag & OPTYPE_UNDO) {
uel->op = op;
}
/* and limit amount to the maximum */
nr = 0;
@@ -642,6 +663,8 @@ void BKE_write_undo(bContext *C, const char *name)
BLI_remlink(&undobase, first);
/* the merge is because of compression */
BLO_merge_memfile(&first->memfile, &first->next->memfile);
if(first->op)
WM_operator_free(first->op);
MEM_freeN(first);
}
}
@@ -697,10 +720,16 @@ void BKE_write_undo(bContext *C, const char *name)
BLI_remlink(&undobase, first);
/* the merge is because of compression */
BLO_merge_memfile(&first->memfile, &first->next->memfile);
if (first->op) {
WM_operator_free(first->op);
first->op = NULL;
}
MEM_freeN(first);
}
}
}
WM_operator_build_stack(C, &undobase, true);
}
/* 1 = an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */
@@ -735,18 +764,22 @@ void BKE_undo_step(bContext *C, int step)
}
}
void BKE_reset_undo(void)
void BKE_reset_undo(bContext *C)
{
UndoElem *uel;
uel = undobase.first;
while (uel) {
BLO_free_memfile(&uel->memfile);
if(uel->op)
WM_operator_free(uel->op);
uel = uel->next;
}
BLI_freelistN(&undobase);
curundo = NULL;
WM_operator_build_stack(C, &undobase, false);
}
/* based on index nr it does a restore */
@@ -756,17 +789,39 @@ void BKE_undo_number(bContext *C, int nr)
BKE_undo_step(C, 0);
}
/* go back to the last occurance of name in stack */
void BKE_undo_name(bContext *C, const char *name)
/* go back to the last occurance of the given name, or the
* given operator */
static void undo_op_name(bContext *C, const wmOperator *op, const char *name)
{
UndoElem *uel = BLI_rfindstring(&undobase, name, offsetof(UndoElem, name));
ListBase included_ops;
UndoElem *uel;
included_ops.first = undobase.first;
included_ops.last = curundo ? curundo : undobase.last;
if(op)
uel = BLI_findptr(&included_ops, op, offsetof(UndoElem, op));
else
uel = BLI_rfindstring(&included_ops, name, offsetof(UndoElem, name));
if (uel && uel->prev) {
curundo = uel->prev;
BKE_undo_step(C, 0);
}
}
/* go back to the last occurance of name in stack */
void BKE_undo_name(bContext *C, const char *name)
{
undo_op_name(C, NULL, name);
}
/* go back to the last occurance of the given operator */
void BKE_undo_op(bContext *C, const wmOperator *op)
{
undo_op_name(C, op, NULL);
}
/* name optional */
int BKE_undo_valid(const char *name)
{

View File

@@ -75,6 +75,7 @@ static void spacetype_free(SpaceType *st)
BLI_freelistN(&art->paneltypes);
BLI_freelistN(&art->headertypes);
BLI_freelistN(&art->menubartypes);
}
BLI_freelistN(&st->regiontypes);
@@ -268,7 +269,9 @@ void BKE_spacedata_draw_locks(int set)
/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *ar)
{
Panel *pa;
uiList *uilst;
OperatorListItem *oli;
if (st) {
ARegionType *art = BKE_regiontype_from_id(st, ar->regiontype);
@@ -286,6 +289,12 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
MEM_freeN(ar->v2d.tab_offset);
ar->v2d.tab_offset = NULL;
}
for (pa = ar->panels.first; pa; pa = pa->next) {
for (oli = pa->operators.first; oli; oli = oli->next) {
BKE_operator_list_item_free(oli);
}
}
BLI_freelistN(&ar->panels);
@@ -306,6 +315,10 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
}
}
BLI_freelistN(&ar->ui_lists);
for (oli = ar->operators.first; oli; oli = oli->next) {
BKE_operator_list_item_free(oli);
}
}
/* not area itself */
@@ -364,6 +377,15 @@ unsigned int BKE_screen_visible_layers(bScreen *screen, Scene *scene)
return layer;
}
/* Including the OperatorListItem */
void BKE_operator_list_item_free(OperatorListItem *oli) {
if (oli->properties) {
IDP_FreeProperty(oli->properties);
MEM_freeN(oli->properties);
}
MEM_freeN(oli);
}
/* ***************** Utilities ********************** */
/* Find a region of the specified type from the given area */
@@ -394,6 +416,20 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa)
return NULL;
}
/* Find a region of the specified type from the given area */
ARegion *BKE_spacelink_find_region_type(SpaceLink *sl, int type)
{
if (sl) {
ARegion *ar;
for (ar = sl->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == type)
return ar;
}
}
return NULL;
}
/* note, using this function is generally a last resort, you really want to be
* using the context when you can - campbell
* -1 for any type */

View File

@@ -6109,6 +6109,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
{
Panel *pa;
uiList *ui_list;
OperatorListItem *oli;
link_list(fd, &ar->panels);
@@ -6117,6 +6118,14 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
pa->runtime_flag = 0;
pa->activedata = NULL;
pa->type = NULL;
link_list(fd, &pa->operators);
for (oli = pa->operators.first; oli; oli = oli->next) {
oli->properties = newdataadr(fd, oli->properties);
if (oli->properties)
IDP_DirectLinkProperty(oli->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
link_list(fd, &ar->ui_lists);
@@ -6128,6 +6137,14 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
if (ui_list->properties)
IDP_DirectLinkProperty(ui_list->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
link_list(fd, &ar->operators);
for (oli = ar->operators.first; oli; oli = oli->next) {
oli->properties = newdataadr(fd, oli->properties);
if (oli->properties)
IDP_DirectLinkProperty(oli->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
if (spacetype == SPACE_EMPTY) {
/* unkown space type, don't leak regiondata */
@@ -6164,6 +6181,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
ar->swap = 0;
ar->do_draw = FALSE;
ar->regiontimer = NULL;
ar->dragdata = NULL;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
}
@@ -9555,7 +9573,53 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
// TODO: what is the right version here?
if (MAIN_VERSION_OLDER(main, 268, 3)) {
bScreen *sc;
for (sc = main->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
ARegion *ar;
ARegion *before = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
if (before && sa->spacetype == SPACE_VIEW3D) {
/* add operators menubar */
ar = BKE_area_find_region_type(sa, RGN_TYPE_MENU_BAR);
if (ar == NULL) {
ar = MEM_callocN(sizeof(ARegion), "tool operators menu bar for view3d");
BLI_insertlinkbefore(&sa->regionbase, before, ar);
ar->regiontype = RGN_TYPE_MENU_BAR;
ar->alignment = RGN_ALIGN_TOP;
}
}
for (sl = sa->spacedata.first; sl; sl = sl->next) {
ARegion *before = BKE_spacelink_find_region_type(sl, RGN_TYPE_TOOLS);
if (before && sl->spacetype == SPACE_VIEW3D) {
/* add operators menubar */
ar = BKE_spacelink_find_region_type(sl, RGN_TYPE_MENU_BAR);
if (ar == NULL) {
ar = MEM_callocN(sizeof(ARegion), "tool operators menu bar for view3d");
BLI_insertlinkbefore(&sl->regionbase, before, ar);
ar->regiontype = RGN_TYPE_MENU_BAR;
ar->alignment = RGN_ALIGN_TOP;
}
}
}
}
}
}
if (!MAIN_VERSION_ATLEAST(main, 268, 1)) {
Brush *brush;
for (brush = main->brush.first; brush; brush = brush->id.next) {
@@ -9618,6 +9682,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */

View File

@@ -236,15 +236,14 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
BLI_addtail(lb, ar);
ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_LEFT;
ar->flag = RGN_FLAG_HIDDEN;
/* tool properties */
//ar->flag = RGN_FLAG_HIDDEN;
/* tool props */
ar = MEM_callocN(sizeof(ARegion), "tool properties for view3d");
BLI_addtail(lb, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
ar->alignment = RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV;
ar->flag = RGN_FLAG_HIDDEN;
ar->alignment = RGN_SPLIT_PREV | RGN_ALIGN_BOTTOM;
/* buttons/list view */
ar = MEM_callocN(sizeof(ARegion), "buttons for view3d");
@@ -253,6 +252,9 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
ar->regiontype = RGN_TYPE_UI;
ar->alignment = RGN_ALIGN_RIGHT;
ar->flag = RGN_FLAG_HIDDEN;
/* The tool properties are added in readfile.c */
#if 0
case SPACE_BUTS:
/* context UI region */
@@ -271,7 +273,6 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
BLI_addtail(lb, ar);
ar->winrct = sa->totrct;
ar->regiontype = RGN_TYPE_WINDOW;
if (sl) {

View File

@@ -2368,8 +2368,26 @@ static void write_windowmanagers(WriteData *wd, ListBase *lb)
}
}
static void write_operator_list_item(WriteData *wd, OperatorListItem *oli)
{
writestruct(wd, DATA, "OperatorListItem", 1, oli);
if (oli->properties) {
IDP_WriteProperty(oli->properties, wd);
}
}
static void write_panel(WriteData *wd, Panel *pa)
{
OperatorListItem *oli;
writestruct(wd, DATA, "Panel", 1, pa);
for (oli = pa->operators.first; oli; oli = oli->next)
write_operator_list_item(wd, oli);
}
static void write_region(WriteData *wd, ARegion *ar, int spacetype)
{
{
writestruct(wd, DATA, "ARegion", 1, ar);
if (ar->regiondata) {
@@ -2474,17 +2492,21 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
Panel *pa;
uiList *ui_list;
ARegion *ar;
OperatorListItem *oli;
writestruct(wd, DATA, "ScrArea", 1, sa);
for (ar= sa->regionbase.first; ar; ar= ar->next) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
write_region(wd, ar, sa->spacetype);
for (pa= ar->panels.first; pa; pa= pa->next)
writestruct(wd, DATA, "Panel", 1, pa);
for (pa = ar->panels.first; pa; pa = pa->next)
write_panel(wd, pa);
for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next)
write_uilist(wd, ui_list);
for (oli = ar->operators.first; oli; oli = oli->next)
write_operator_list_item(wd, oli);
}
sl= sa->spacedata.first;

View File

@@ -684,28 +684,50 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
static int armature_parent_set_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
PointerRNA ptr;
EditBone *actbone = CTX_data_active_bone(C);
uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE);
uiLayout *layout = uiPupMenuLayout(pup);
int allchildbones = 0;
PropertyRNA *prop;
uiPopupMenu *pup;
uiLayout *layout;
CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
{
if (ebone != actbone) {
if (ebone->parent != actbone) allchildbones = 1;
}
WM_operator_properties_create_ptr(&ptr, op->type);
prop = RNA_struct_find_property(&ptr, "type");
if (prop == NULL) {
printf("%s: %s has no enum property set\n", __func__, op->type->idname);
}
CTX_DATA_END;
uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
/* ob becomes parent, make the associated menus */
if (allchildbones)
uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
else if (RNA_property_type(prop) != PROP_ENUM) {
printf("%s: %s \"%s\" is not an enum property\n",
__func__, op->type->idname, RNA_property_identifier(prop));
}
else if (RNA_property_is_set(op->ptr, prop)) {
const int retval = op->type->exec(C, op);
OPERATOR_RETVAL_CHECK(retval);
return retval;
} else {
int allchildbones = 0;
pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE);
layout = uiPupMenuLayout(pup);
uiPupMenuEnd(C, pup);
CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
{
if (ebone != actbone) {
if (ebone->parent != actbone) allchildbones = 1;
}
}
CTX_DATA_END;
uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
/* ob becomes parent, make the associated menus */
if (allchildbones)
uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
uiPupMenuEnd(C, pup);
}
return OPERATOR_CANCELLED;
}

View File

@@ -29,6 +29,7 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
#include "DNA_windowmanager_types.h"
#include "MEM_guardedalloc.h"
@@ -714,10 +715,10 @@ static void *get_armature_edit(bContext *C)
}
/* and this is all the undo system needs to know */
void undo_push_armature(bContext *C, const char *name)
void undo_push_armature(bContext *C, const char *name, wmOperator *op)
{
// XXX solve getdata()
undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL, op);
}
/* *************************************************************** */

View File

@@ -7364,9 +7364,9 @@ static void *get_data(bContext *C)
}
/* and this is all the undo system needs to know */
void undo_push_curve(bContext *C, const char *name)
void undo_push_curve(bContext *C, const char *name, wmOperator *op)
{
undo_editmode_push(C, name, get_data, free_undoCurve, undoCurve_to_editCurve, editCurve_to_undoCurve, NULL);
undo_editmode_push(C, name, get_data, free_undoCurve, undoCurve_to_editCurve, editCurve_to_undoCurve, NULL, op);
}
void ED_curve_beztcpy(EditNurb *editnurb, BezTriple *dst, BezTriple *src, int count)

View File

@@ -1796,7 +1796,7 @@ static void *get_undoFont(bContext *C)
}
/* and this is all the undo system needs to know */
void undo_push_font(bContext *C, const char *name)
void undo_push_font(bContext *C, const char *name, wmOperator *op)
{
undo_editmode_push(C, name, get_undoFont, free_undoFont, undoFont_to_editFont, editFont_to_undoFont, NULL);
undo_editmode_push(C, name, get_undoFont, free_undoFont, undoFont_to_editFont, editFont_to_undoFont, NULL, op);
}

View File

@@ -56,6 +56,14 @@ if(WITH_BLENDER)
#../../../../release/datafiles/blender_icons32.png
#180 SRC)
data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC)
#svg_to_png(../../../../release/datafiles/blender_operator_icons.svg
#../../../../release/datafiles/blender_operator_icons16.png
#90 SRC)
data_to_c_simple(../../../../release/datafiles/blender_operator_icons16.png SRC)
#svg_to_png(../../../../release/datafiles/blender_operator_icons.svg
#../../../../release/datafiles/blender_operator_icons32.png
#180 SRC)
data_to_c_simple(../../../../release/datafiles/blender_operator_icons32.png SRC)
#svg_to_png(../../../../release/datafiles/prvicons.svg
#../../../../release/datafiles/prvicons.png
#90 SRC)

View File

@@ -286,6 +286,35 @@ static void draw_gpencil_space_specials(const bContext *C, uiLayout *layout)
}
/* Draw the contents for a grease-pencil panel*/
static void draw_gpencil_operator_buttons(const bContext *C, uiLayout *layout)
{
PointerRNA ptr;
uiLayout *row;
wmOperatorType *ot;
ot = WM_operatortype_find("GPENCIL_OT_draw", 0);
row = uiLayoutRowWithButtonHeight(layout, TRUE, 1.5f);
ptr = uiItemFullO_ptr(row, ot, "", ICON_AUTOMATIC, NULL, uiLayoutGetOperatorContext(layout), UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&ptr, "mode", GP_PAINTMODE_DRAW);
ptr = uiItemFullO_ptr(row, WM_operatortype_find("GPENCIL_OT_draw", 0), "", ICON_AUTOMATIC, NULL, uiLayoutGetOperatorContext(layout), UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT);
ptr = uiItemFullO_ptr(row, WM_operatortype_find("GPENCIL_OT_draw", 0), "", ICON_AUTOMATIC, NULL, uiLayoutGetOperatorContext(layout), UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&ptr, "mode", GP_PAINTMODE_DRAW_POLY);
ptr = uiItemFullO_ptr(row, WM_operatortype_find("GPENCIL_OT_draw", 0), "", ICON_AUTOMATIC, NULL, uiLayoutGetOperatorContext(layout), UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&ptr, "mode", GP_PAINTMODE_ERASER);
row = uiLayoutRow(layout, TRUE);
RNA_pointer_create(NULL, &RNA_ToolSettings, CTX_data_tool_settings(C), &ptr);
//prop = RNA_struct_find_property(&ptr, "use_grease_pencil_sessions");
//uiItemFullR
uiItemR(row, &ptr, "use_grease_pencil_sessions", 0, "Continuous drawing", ICON_NONE);
}
static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, PointerRNA *ctx_ptr)
{
PointerRNA gpd_ptr;
@@ -305,49 +334,55 @@ static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, Poin
/* TODO: show some info about who owns this? */
uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink");
if (gpd != NULL) {
/* draw gpd drawing settings first ------------------------------------- */
col = uiLayoutColumn(layout, TRUE);
/* label */
uiItemL(col, IFACE_("Pencil Settings:"), ICON_NONE);
/* check whether advanced 3D-View drawing space options can be used */
if (is_v3d) {
if (gpd->flag & (GP_DATA_DEPTH_STROKE | GP_DATA_DEPTH_VIEW))
v3d_stroke_opts = STROKE_OPTS_V3D_ON;
else
v3d_stroke_opts = STROKE_OPTS_V3D_OFF;
}
/* drawing space options */
row = uiLayoutRow(col, TRUE);
uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, ICON_NONE);
uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, ICON_NONE);
if (sc == NULL) {
row = uiLayoutRow(col, TRUE);
uiLayoutSetActive(row, v3d_stroke_opts);
uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE);
uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE);
row = uiLayoutRow(col, FALSE);
uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON);
uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE);
}
}
/* add new layer button - can be used even when no data, since it can add a new block too */
col = uiLayoutColumn(layout, TRUE);
uiItemL(col, IFACE_("Pencil Layers:"), ICON_NONE);
uiItemO(col, IFACE_("New Layer"), ICON_NONE, "GPENCIL_OT_layer_add");
row = uiLayoutRow(col, TRUE);
uiItemO(row, IFACE_("Delete Frame"), ICON_NONE, "GPENCIL_OT_active_frame_delete");
uiItemO(row, IFACE_("Convert"), ICON_NONE, "GPENCIL_OT_convert");
/* sanity checks... */
if (gpd == NULL)
return;
/* draw each layer --------------------------------------------- */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
col = uiLayoutColumn(layout, TRUE);
gp_drawui_layer(col, gpd, gpl, is_v3d);
}
/* draw gpd drawing settings first ------------------------------------- */
col = uiLayoutColumn(layout, TRUE);
/* label */
uiItemL(col, IFACE_("Drawing Settings:"), ICON_NONE);
/* check whether advanced 3D-View drawing space options can be used */
if (is_v3d) {
if (gpd->flag & (GP_DATA_DEPTH_STROKE | GP_DATA_DEPTH_VIEW))
v3d_stroke_opts = STROKE_OPTS_V3D_ON;
else
v3d_stroke_opts = STROKE_OPTS_V3D_OFF;
}
/* drawing space options */
row = uiLayoutRow(col, TRUE);
uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, ICON_NONE);
uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, ICON_NONE);
if (sc == NULL) {
row = uiLayoutRow(col, TRUE);
uiLayoutSetActive(row, v3d_stroke_opts);
uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE);
uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE);
row = uiLayoutRow(col, FALSE);
uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON);
uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE);
/* sanity checks... */
if (gpd != NULL)
{
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
col = uiLayoutColumn(layout, TRUE);
gp_drawui_layer(col, gpd, gpl, is_v3d);
}
}
}
@@ -367,6 +402,9 @@ void gpencil_panel_standard(const bContext *C, Panel *pa)
/* if (v3d->flag2 & V3D_DISPGP)... etc. */
/* draw tool buttons */
draw_gpencil_operator_buttons(C, pa->layout);
draw_gpencil_space_specials(C, pa->layout);
/* get pointer to Grease Pencil Data */

View File

@@ -70,6 +70,8 @@
#include "WM_api.h"
#include "WM_types.h"
#include "UI_resources.h"
#include "gpencil_intern.h"
/* ******************************************* */
@@ -2030,6 +2032,21 @@ static EnumPropertyItem prop_gpencil_drawmodes[] = {
{0, NULL, 0, NULL, NULL}
};
static int gpencil_draw_icon(const bContext *UNUSED(C), PointerRNA *opptr)
{
if (opptr) {
switch (RNA_enum_get(opptr, "mode")) {
case GP_PAINTMODE_DRAW: return OPICON_GREASE_DRAW;
case GP_PAINTMODE_DRAW_STRAIGHT: return OPICON_GREASE_LINE;
case GP_PAINTMODE_DRAW_POLY: return OPICON_GREASE_POLY;
case GP_PAINTMODE_ERASER: return OPICON_GREASE_ERASE;
}
}
return ICON_GREASEPENCIL;
}
void GPENCIL_OT_draw(wmOperatorType *ot)
{
/* identifiers */
@@ -2043,6 +2060,7 @@ void GPENCIL_OT_draw(wmOperatorType *ot)
ot->modal = gpencil_draw_modal;
ot->cancel = gpencil_draw_cancel;
ot->poll = gpencil_draw_poll;
ot->icon = gpencil_draw_icon;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;

View File

@@ -52,6 +52,8 @@ void sdrawXORline4(int nr, int x0, int y0, int x1, int y1);
void fdrawXORellipse(float xofs, float yofs, float hw, float hh);
void fdrawXORcirc(float xofs, float yofs, float rad);
void fdrawellipses(float xofs, float yofs, float rad);
void fdrawcheckerboard(float x1, float y1, float x2, float y2);
/* OpenGL stipple defines */

View File

@@ -155,7 +155,7 @@ void create_vgroups_from_armature(struct ReportList *reports, struct Scene *scen
void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone); /* if bone is already in list, pass it as param to ignore it */
void ED_armature_bone_rename(struct bArmature *arm, const char *oldnamep, const char *newnamep);
void undo_push_armature(struct bContext *C, const char *name);
void undo_push_armature(struct bContext *C, const char *name, struct wmOperator *op);
/* low level selection functions which handle */
int ED_armature_ebone_selectflag_get(const EditBone *ebone);

View File

@@ -56,7 +56,7 @@ void CU_select_all(struct Object *obedit);
void CU_select_swap(struct Object *obedit);
void undo_push_curve(struct bContext *C, const char *name);
void undo_push_curve(struct bContext *C, const char *name, struct wmOperator *op);
ListBase *object_editcurve_get(struct Object *ob);
void load_editNurb(struct Object *obedit);
@@ -72,7 +72,7 @@ int isNurbsel(struct Nurb *nu);
int join_curve_exec(struct bContext *C, struct wmOperator *op);
/* editfont.h */
void undo_push_font(struct bContext *C, const char *name);
void undo_push_font(struct bContext *C, const char *name, struct wmOperator *op);
void make_editText(struct Object *obedit);
void load_editText(struct Object *obedit);
void free_editText(struct Object *obedit);

View File

@@ -48,6 +48,12 @@ extern char datatoc_blender_icons16_png[];
extern int datatoc_blender_icons32_png_size;
extern char datatoc_blender_icons32_png[];
extern int datatoc_blender_operator_icons16_png_size;
extern char datatoc_blender_operator_icons16_png[];
extern int datatoc_blender_operator_icons32_png_size;
extern char datatoc_blender_operator_icons32_png[];
extern int datatoc_prvicons_png_size;
extern char datatoc_prvicons_png[];

View File

@@ -35,6 +35,7 @@ struct bContext;
struct MetaBall;
struct Object;
struct wmKeyConfig;
struct wmOperator;
void ED_operatortypes_metaball(void);
void ED_keymap_metaball(struct wmKeyConfig *keyconf);
@@ -47,7 +48,7 @@ void free_editMball(struct Object *obedit);
void make_editMball(struct Object *obedit);
void load_editMball(struct Object *obedit);
void undo_push_mball(struct bContext *C, const char *name);
void undo_push_mball(struct bContext *C, const char *name, struct wmOperator *op);
void ED_mball_transform(struct MetaBall *mb, float *mat);

View File

@@ -120,7 +120,7 @@ void EDBM_selectmode_flush(struct BMEditMesh *em);
void EDBM_deselect_flush(struct BMEditMesh *em);
void EDBM_select_flush(struct BMEditMesh *em);
void undo_push_mesh(struct bContext *C, const char *name);
void undo_push_mesh(struct bContext *C, const char *name, struct wmOperator *op);
bool EDBM_vert_color_check(struct BMEditMesh *em);

View File

@@ -170,7 +170,7 @@ void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *o
/* object_lattice.c */
bool mouse_lattice(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
void undo_push_lattice(struct bContext *C, const char *name);
void undo_push_lattice(struct bContext *C, const char *name, struct wmOperator *op);
/* object_lattice.c */

View File

@@ -63,6 +63,8 @@ void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar);
void ED_region_panels(const struct bContext *C, struct ARegion *ar, int vertical, const char *context, int contextnr);
void ED_region_header_init(struct ARegion *ar);
void ED_region_header(const struct bContext *C, struct ARegion *ar);
void ED_region_menubar(const struct bContext *C, struct ARegion *ar);
void ED_region_menubar_init(struct ARegion *ar);
void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar);
void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float fill_color[4]);
void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy);

View File

@@ -72,8 +72,8 @@ void undo_editmode_push(struct bContext *C, const char *name,
void (*freedata)(void *),
void (*to_editmode)(void *, void *, void *),
void *(*from_editmode)(void *, void *),
int (*validate_undo)(void *, void *));
int (*validate_undo)(void *, void *),
struct wmOperator * op);
void undo_editmode_clear(void);

View File

@@ -44,6 +44,7 @@ struct Main;
struct ListBase;
struct ARegion;
struct ARegionType;
struct OperatorListItem;
struct ScrArea;
struct wmWindow;
struct wmWindowManager;
@@ -79,6 +80,7 @@ typedef struct uiBut uiBut;
typedef struct uiBlock uiBlock;
typedef struct uiPopupBlockHandle uiPopupBlockHandle;
typedef struct uiLayout uiLayout;
typedef struct uiHandleRegionDragData uiHandleRegionDragData;
/* Defines */
@@ -130,6 +132,7 @@ typedef struct uiLayout uiLayout;
/* block->flag bits 12-15 are identical to but->flag bits */
#define UI_BLOCK_LIST_ITEM (1 << 19)
#define UI_BLOCK_SHORTCUTS (1 << 20)
/* uiPopupBlockHandle->menuretval */
#define UI_RETURN_CANCEL (1 << 0) /* cancel all menus cascading */
@@ -179,6 +182,9 @@ typedef struct uiLayout uiLayout;
#define UI_BUT_VEC_SIZE_LOCK (1 << 30) /* used to flag if color hsv-circle should keep luminance */
#define UI_BUT_COLOR_CUBIC (1 << 31) /* cubic saturation for the color wheel */
#define UI_BUT2_EXTRA_TEXT (1 << 0)
#define UI_PANEL_WIDTH 340
#define UI_COMPACT_PANEL_WIDTH 160
@@ -270,6 +276,16 @@ typedef enum {
#define UI_GRAD_V_ALT 9
/* Panel flags */
#define PNL_LAST_ADDED 1
#define PNL_ACTIVE 2
#define PNL_WAS_ACTIVE 4
#define PNL_ANIM_ALIGN 8
#define PNL_NEW_ADDED 16
#define PNL_FIRST 32
#define PNL_CUSTOM_PANEL 64
#define PNL_PINNED 128
/* Drawing
*
* Functions to draw various shapes, taking theme settings into account.
@@ -372,6 +388,7 @@ void uiDrawBlock(const struct bContext *C, struct uiBlock *block);
uiBlock *uiGetBlock(const char *name, struct ARegion *ar);
void uiBlockSetEmboss(uiBlock *block, char dt);
void uiBlockSetPanel(uiBlock *block, struct Panel *pa);
void uiFreeBlock(const struct bContext *C, uiBlock *block);
void uiFreeBlocks(const struct bContext *C, struct ListBase *lb);
@@ -417,6 +434,7 @@ void uiButSetDragID(uiBut *but, struct ID *id);
void uiButSetDragRNA(uiBut *but, struct PointerRNA *ptr);
void uiButSetDragPath(uiBut *but, const char *path);
void uiButSetDragName(uiBut *but, const char *name);
void uiButSetDragOp(uiBut *but, const struct wmOperatorType *ot);
void uiButSetDragValue(uiBut *but);
void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
@@ -647,14 +665,23 @@ bool autocomplete_end(AutoComplete *autocpl, char *autoname);
* could use a good cleanup, though how they will function in 2.5 is
* not clear yet so we postpone that. */
void uiCollapseAllPanels(struct ScrArea *sa, struct ARegion *ar, const char *context);
void uiBeginPanels(const struct bContext *C, struct ARegion *ar);
void uiEndPanels(const struct bContext *C, struct ARegion *ar, int *x, int *y);
void uiDrawPanels(const struct bContext *C, struct ARegion *ar);
struct Panel *uiGetExistingPanel(struct ARegion *ar, struct PanelType *pt);
struct Panel *uiBeginPanel(struct ScrArea *sa, struct ARegion *ar, uiBlock *block, struct PanelType *pt, int *open);
void uiEndPanel(uiBlock *block, int width, int height);
void uiScalePanels(struct ARegion *ar, float new_width);
void uiPanelAddOperator(struct bContext *C, struct Panel *pa, struct wmOperatorType *ot, PointerRNA *opptr);
void uiPanelFree(struct Panel *pa);
int uiPanelClosed(struct Panel *pa);
struct PanelType *uiCreateCustomPanelType(struct ScrArea *sa, struct ARegion *ar, const char *context, const char *name, const char *label);
/* Handlers
*
* Handlers that can be registered in regions, areas and windows for
@@ -712,6 +739,8 @@ void UI_exit(void);
#define UI_ITEM_R_FULL_EVENT (1 << 6)
#define UI_ITEM_R_NO_BG (1 << 7)
#define UI_ITEM_R_IMMEDIATE (1 << 8)
#define UI_ITEM_O_SINGLE_UNIT (1 << 9)
#define UI_ITEM_O_SHORTCUT (1 << 10)
/* uiLayoutOperatorButs flags */
#define UI_LAYOUT_OP_SHOW_TITLE 1
@@ -749,6 +778,7 @@ const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing
void uiLayoutOperatorButs(const struct bContext *C, struct uiLayout *layout, struct wmOperator *op,
bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
const char label_align, const short flag);
void uiLayoutOperatorTypeDefaultsButs(const struct bContext *C, struct uiLayout *layout, struct wmOperator *op);
struct MenuType *uiButGetMenuType(uiBut *but);
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext);
@@ -772,7 +802,9 @@ float uiLayoutGetScaleY(uiLayout *layout);
/* layout specifiers */
uiLayout *uiLayoutRow(uiLayout *layout, int align);
uiLayout *uiLayoutRowWithButtonHeight(uiLayout *layout, int align, float button_height);
uiLayout *uiLayoutColumn(uiLayout *layout, int align);
uiLayout *uiLayoutColumnWithButtonHeight(uiLayout *layout, int align, float button_height);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align);
uiLayout *uiLayoutBox(uiLayout *layout);
uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *ui_list, struct PointerRNA *ptr, struct PropertyRNA *prop,
@@ -791,6 +823,8 @@ void uiTemplateIDBrowse(uiLayout *layout, struct bContext *C, struct PointerRNA
const char *newop, const char *openop, const char *unlinkop);
void uiTemplateIDPreview(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
const char *newop, const char *openop, const char *unlinkop, int rows, int cols);
void uiTemplateIDPreviewCompact(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname,
const char *newop, const char *openop, const char *unlinkop, int rows, int cols);
void uiTemplateAnyID(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
const char *proptypename, const char *text);
void uiTemplatePathBuilder(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
@@ -873,6 +907,12 @@ void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc
void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, const char *propname, const char *name, int icon);
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon);
/* OperatorListItem utilities */
struct OperatorListItem *uiOperatorListItemPresent(ListBase *lb, const char *idname, IDProperty *properties, const char *context);
struct OperatorListItem *uiRegionDraggedOperatorListItem(struct ARegion *ar);
int uiRegionDraggedNewIndex(struct ARegion *ar);
/* UI Operators */
void UI_buttons_operatortypes(void);

View File

@@ -0,0 +1,54 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file UI_opicons.h
* \ingroup editorui
*/
/* Note: this is included twice with different #defines for DEF_ICON
* once from UI_resources.h for the internal icon enum and
* once for interface_api.c for the definition of the RNA enum for the icons */
/* OPICON_ prefix added */
DEF_FIRST_OPICON(RENDER_FRAME)
DEF_OPICON(RENDER_ANIM)
DEF_OPICON(RENDER)
DEF_OPICON(RULER)
DEF_OPICON(ADD)
DEF_OPICON(DELETE)
DEF_OPICON(DUP)
DEF_OPICON(DUP_LINKED)
DEF_OPICON(LOOPCUT)
DEF_OPICON(GREASE_DRAW)
DEF_OPICON(GREASE_LINE)
DEF_OPICON(GREASE_POLY)
DEF_OPICON(GREASE_ERASE)
DEF_OPICON(GREASE)
DEF_OPICON(BRUSH)
DEF_OPICON(KNIFE)

View File

@@ -32,21 +32,38 @@
#ifndef __UI_RESOURCES_H__
#define __UI_RESOURCES_H__
#define ICON_AUTOMATIC -1
#define ICON_GRID_COLS 26
#define ICON_GRID_ROWS 30
#define OPICON_GRID_COLS 26
#define OPICON_GRID_ROWS 30
#define OPICON_OFFSET 0x3FFF
/* elubie: TODO: move the typedef for icons to UI_interface_icons.h */
/* and add/replace include of UI_resources.h by UI_interface_icons.h */
#define DEF_ICON(name) ICON_##name,
#define DEF_VICO(name) VICO_##name,
#define DEF_OPICON(name) OPICON_##name,
#define DEF_FIRST_OPICON(name) OPICON_##name = OPICON_OFFSET,
typedef enum {
/* ui */
#include "UI_icons.h"
#include "UI_opicons.h"
BIFICONID_LAST
} BIFIconID;
/* operator icons are offset by 0x3FFF */
#define BIFICONID_FIRST (ICON_NONE)
#define BIFICONID_FIRST_OP (BIFICONID_FIRST + OPICON_OFFSET)
#undef DEF_ICON
#undef DEF_VICO
#undef DEF_OPICON
#undef DEF_FIRST_OPICON
enum {
TH_REDALERT,
@@ -245,6 +262,7 @@ enum {
struct bTheme;
struct PointerRNA;
struct bContext;
// THE CODERS API FOR THEMES:
@@ -312,4 +330,6 @@ const unsigned char *UI_ThemeGetColorPtr(struct bTheme *btheme, int spacetype, i
void UI_make_axis_color(const unsigned char *src_col, unsigned char *dst_col, const char axis);
int UI_data_mode_icon(const struct bContext *C);
#endif /* __UI_RESOURCES_H__ */

View File

@@ -1021,7 +1021,7 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
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);
ui_but_add_shortcut(but, buf, TRUE);
}
else if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
ui_but_add_shortcut(but, buf, FALSE);
@@ -1080,7 +1080,7 @@ void uiEndBlock(const bContext *C, uiBlock *block)
ui_menu_block_set_keyaccels(block); /* could use a different flag to check */
}
if (block->flag & UI_BLOCK_LOOP) {
if (block->flag & UI_BLOCK_SHORTCUTS) {
ui_menu_block_set_keymaps(C, block);
}
@@ -1199,7 +1199,8 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
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_draw_aligned_panel(&style, block, &rect, ar && ar->regiontype == RGN_TYPE_TOOLS);
/* widgets */
for (but = block->buttons.first; but; but = but->next) {
@@ -2352,6 +2353,11 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor
block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
block->auto_open = TRUE;
block->flag |= UI_BLOCK_LOOP; /* tag as menu */
block->flag |= UI_BLOCK_SHORTCUTS;
}
/* Add shortcuts to toolbar */
if (region && region->type && region->type->regionid == RGN_TYPE_TOOLS) {
block->flag |= UI_BLOCK_SHORTCUTS;
}
return block;
@@ -2367,6 +2373,11 @@ void uiBlockSetEmboss(uiBlock *block, char dt)
block->dt = dt;
}
void uiBlockSetPanel(uiBlock *block, Panel *pa)
{
block->panel = pa;
}
void ui_check_but(uiBut *but)
{
/* if something changed in the button */
@@ -3613,6 +3624,12 @@ void uiButSetDragName(uiBut *but, const char *name)
but->dragpoin = (void *)name;
}
void uiButSetDragOp(uiBut *but, const wmOperatorType *ot)
{
but->dragtype = WM_DRAG_OP;
but->dragpoin = (void *)ot;
}
/* value from button itself */
void uiButSetDragValue(uiBut *but)
{

View File

@@ -64,6 +64,7 @@
#include "BKE_tracking.h"
#include "BKE_unit.h"
#include "BKE_paint.h"
#include "BKE_screen.h"
#include "ED_screen.h"
#include "ED_util.h"
@@ -905,7 +906,7 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
{
wmDrag *drag;
drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but), but->opptr, but->opcontext);
if (but->imb)
WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
}
@@ -2491,7 +2492,14 @@ int ui_button_open_menu_direction(uiBut *but)
static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
/* first handle click on icondrag type button */
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
return WM_UI_HANDLER_BREAK;
}
else if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_WAIT_RELEASE);
return WM_UI_HANDLER_BREAK;
}
@@ -2515,6 +2523,26 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons
return WM_UI_HANDLER_BREAK;
}
}
else if (data->state == BUTTON_STATE_WAIT_DRAG) {
/* this function also ends state */
if (ui_but_start_drag(C, but, data, event)) {
data->escapecancel = TRUE;
return WM_UI_HANDLER_BREAK;
}
/* If the mouse has been pressed and released, getting to
* this point without triggering a drag, then clear the
* drag state for this button and continue to pass on the event */
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_CONTINUE;
}
/* while waiting for a drag to be triggered, always block
* other events from getting handled */
return WM_UI_HANDLER_BREAK;
}
return WM_UI_HANDLER_CONTINUE;
}
@@ -2573,7 +2601,6 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
data->escapecancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
}
@@ -5039,6 +5066,76 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
uiPupBlock(C, menu_add_shortcut, but);
}
//static void ui_but_menu_set_last_properties(bContext *UNUSED(C), void *arg_op, int UNUSED(arg_event))
//{
// wmOperator *op = (wmOperator*)arg_op;
// WM_operator_default_properties_store(op);
//}
// TODO: this should make use of the new comparison method, perhaps based on sort order
static void remove_from_custom_panel(bContext *UNUSED(C), void *arg_pa, void *arg_optype)
{
Panel *pa = arg_pa;
wmOperatorType *ot = arg_optype;
OperatorListItem *oli;
oli = BLI_findstring(&pa->operators, ot->idname, offsetof(OperatorListItem, optype_idname));
BLI_remlink(&pa->operators, oli);
BKE_operator_list_item_free(oli);
}
static void remove_from_icon_shelf(bContext *C, void *arg_ot, void *arg_opptr)
{
ARegion *ar = CTX_wm_region(C);
wmOperatorType *ot = arg_ot;
PointerRNA *opptr = (PointerRNA*)arg_opptr;
OperatorListItem *oli;
for (oli = ar->operators.first; oli; oli = oli->next) {
if (strcmp(oli->optype_idname, ot->idname) == 0 && IDP_EqualsProperties(opptr->data, oli->properties)) {
BLI_remlink(&ar->operators, oli);
BKE_operator_list_item_free(oli);
}
}
ED_region_tag_redraw(ar);
}
static void remove_from_icon_shelf_divider(bContext *C, void *arg_oli, void *UNUSED(arg2))
{
ARegion *ar = CTX_wm_region(C);
OperatorListItem *oli = (OperatorListItem*)arg_oli;
BLI_remlink(&ar->operators, oli);
BKE_operator_list_item_free(oli);
ED_region_tag_redraw(ar);
}
static void add_divider_to_icon_shelf(bContext *C, void *arg_ot, void *arg_opptr)
{
ARegion *ar = CTX_wm_region(C);
wmOperatorType *ot = arg_ot;
PointerRNA *opptr = (PointerRNA*)arg_opptr;
OperatorListItem *oli = uiOperatorListItemPresent(&ar->operators, ot->idname, opptr->data, CTX_data_mode_string(C));
OperatorListItem *div;
/*
* Only add a divider if:
* - the current button is not a divider
* - the current button does not have a divider in front of it already
*/
if (oli && !(oli->flag & OLI_DIVIDER) &&
!(oli->prev != NULL && ((OperatorListItem*)(oli->prev))->flag & OLI_DIVIDER)) {
div = MEM_callocN(sizeof(OperatorListItem), "OperatorListItem divider");
div->flag |= OLI_DIVIDER;
BLI_strncpy(div->context, CTX_data_mode_string(C), MAX_NAME);
BLI_insertlinkbefore(&ar->operators, oli, div);
}
ED_region_tag_redraw(ar);
}
static bool ui_but_menu(bContext *C, uiBut *but)
{
@@ -5046,6 +5143,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiLayout *layout;
bool is_array, is_array_component;
uiStringInfo label = {BUT_GET_LABEL, NULL};
ARegion *ar = CTX_wm_region(C);
/* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/
/* return 0;*/
@@ -5234,6 +5332,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
wmKeyMapItem *kmi = NULL;
int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, 1, &km);
uiItemS(layout);
if (kmi_id)
kmi = WM_keymap_item_find_id(km, kmi_id);
@@ -5259,8 +5359,66 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
uiItemS(layout);
{
uiBut *opp_but;
Panel *pa = but->block->panel;
/* Remove the operator from the custom enclosure */
if (ar->regiontype == RGN_TYPE_TOOLS && pa && pa->flag & PNL_CUSTOM_PANEL) {
opp_but = uiDefIconTextBut(block, BUT, 0, ICON_NONE,
CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove From Panel"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
uiButSetFunc(opp_but, remove_from_custom_panel, pa, but->optype);
uiItemS(layout);
}
else if (ar->regiontype == RGN_TYPE_MENU_BAR) {
/* Only show the option to add a divider for a button, not a divider */
if (uiOperatorListItemPresent(&ar->operators, but->optype->idname, but->opptr->data, CTX_data_mode_string(C))) {
opp_but = uiDefIconTextBut(block, BUT, 0, ICON_NONE,
CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Divider to the Left"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
uiButSetFunc(opp_but, add_divider_to_icon_shelf, but->optype, but->opptr);
opp_but = uiDefIconTextBut(block, BUT, 0, ICON_NONE,
CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove From Icon Shelf"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
uiButSetFunc(opp_but, remove_from_icon_shelf, but->optype, but->opptr);
}
uiItemS(layout);
}
if (ar->regiontype != RGN_TYPE_MENU_BAR) {
opp_but = uiDefIconTextBut(block, BUT, 0, ICON_NONE,
CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Icon Shelf"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
uiButSetFunc(opp_but, add_to_icon_shelf, but->optype, but->opptr);
}
uiItemMenuF(layout, IFACE_("Add to Custom Panel..."), ICON_NONE, add_to_custom_panel_menu, but->optype);
}
uiItemS(layout);
}
/* Divider butons */
if (ar->regiontype == RGN_TYPE_MENU_BAR) {
if (but->func_arg1) {
uiBut *div_but;
uiBlock *block = uiLayoutGetBlock(layout);
int w = uiLayoutGetWidth(layout);
div_but = uiDefIconTextBut(block, BUT, 0, ICON_NONE,
CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove From Icon Shelf"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
/* N.B. the but->func_arg1 is set to the divider OperatorListItem. */
uiButSetFunc(div_but, remove_from_icon_shelf_divider, but->func_arg1, NULL);
uiItemS(layout);
}
}
/* Show header tools for header buttons. */
{
ARegion *ar = CTX_wm_region(C);
@@ -5557,7 +5715,7 @@ static bool ui_but_contains_pt(uiBut *but, int mx, int my)
return BLI_rctf_isect_pt(&but->rect, mx, my);
}
static uiBut *ui_but_find_activated(ARegion *ar)
uiBut *ui_but_find_activated(ARegion *ar)
{
uiBlock *block;
uiBut *but;
@@ -7540,6 +7698,152 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB
/* *************** UI event handlers **************** */
static void ui_do_drag_button(const bContext *C, const wmEvent *event, ARegion *ar)
{
uiHandleRegionDragData *data = ar->dragdata;
int cur_index = BLI_findindex(&ar->operators, data->oli);
OperatorListItem *oli_iter = data->oli;
int dx, dunits, dunits_iter, extra_units = 0, maxindex;
// Calculate the new index of the button based on the drag offset
dx = event->x - data->startx;
dunits = dx / (UI_UNIT_X * 1.5); // TODO: make sure this factor corresponds to menubar button sizes
// Offset the new index by the interleaved list items that aren't shown in the current contex
dunits_iter = dunits;
while (dunits_iter != 0) {
oli_iter = dunits < 0 ? oli_iter->prev : oli_iter->next;
if (oli_iter == NULL) break;
// TODO: also take into account closed groups
if (strcmp(oli_iter->context, CTX_data_mode_string(C)) != 0)
extra_units += (dunits < 0 ? -1 : 1);
dunits_iter += (dunits < 0 ? 1 : -1);
}
data->newindex = (cur_index + dunits) + extra_units;
maxindex = (BLI_countlist(&ar->operators) - 1);
CLAMP(data->newindex, 0, maxindex);
ED_region_tag_redraw(ar);
}
static void ui_do_drag_button_finish(const bContext *UNUSED(C), const wmEvent *UNUSED(event), ARegion *ar)
{
uiHandleRegionDragData *data = ar->dragdata;
int cur_index = BLI_findindex(&ar->operators, data->oli);
OperatorListItem *oli_target = BLI_findlink(&ar->operators, data->newindex);
if (data->newindex < cur_index) {
BLI_remlink(&ar->operators, data->oli);
BLI_insertlinkbefore(&ar->operators, oli_target, data->oli);
}
else if (data->newindex > cur_index) {
BLI_remlink(&ar->operators, data->oli);
BLI_insertlinkafter(&ar->operators, oli_target, data->oli);
}
ED_region_tag_redraw(ar);
}
static void region_activate_drag_state(const bContext *C, ARegion *ar, uiHandleRegionDragState state);
static int ui_handler_region_drag_shelf(bContext *C, const wmEvent *event, void *userdata)
{
ARegion *ar = userdata;
uiHandleRegionDragData *data;
int retval = WM_UI_HANDLER_CONTINUE;
if (event->type == MOUSEMOVE) {
if (ar->dragdata) {
data = ar->dragdata;
if (data->state == REGION_STATE_DRAG_BUTTON) {
ui_do_drag_button(C, event, ar);
}
else if (data->state == REGION_STATE_DRAG_BUTTON_WAITING) {
if (ABS(data->startx - event->x) > UI_UNIT_X) {
region_activate_drag_state(C, ar, REGION_STATE_DRAG_BUTTON);
}
}
}
retval = WM_UI_HANDLER_BREAK;
}
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
if (ar->dragdata) {
data = ar->dragdata;
if (data->state == REGION_STATE_DRAG_BUTTON) {
ui_do_drag_button_finish(C, event, ar);
retval = WM_UI_HANDLER_BREAK;
}
}
region_activate_drag_state(C, ar, REGION_STATE_DRAG_EXIT);
}
return retval;
}
static void ui_handler_region_drag_shelf_remove(bContext *UNUSED(C), void *UNUSED(userdata))
{
// ARegion *ar = userdata;
// region_activate_drag_state(C, ar, REGION_STATE_DRAG_EXIT);
}
static void region_activate_drag_state(const bContext *C, ARegion *ar, uiHandleRegionDragState state)
{
uiHandleRegionDragData *data = ar->dragdata;
wmWindow *win = CTX_wm_window(C);
if (data && data->state == state)
return;
if (state == REGION_STATE_DRAG_EXIT) {
if (data) {
/* deactivate the button when we've dragged, otherwise we'll get a
* global drag */
if (data->state == REGION_STATE_DRAG_BUTTON) {
uiBut *but = ui_but_find_activated(ar);
if (but)
ui_button_active_free(C, but);
}
MEM_freeN(data);
ar->dragdata = NULL;
}
WM_event_remove_ui_handler(&win->modalhandlers, ui_handler_region_drag_shelf, ui_handler_region_drag_shelf_remove, ar, FALSE);
}
else if (state == REGION_STATE_DRAG_BUTTON_WAITING) {
if (!data) {
OperatorListItem *oli = NULL;
uiBut *but = ui_but_find_activated(ar);
if (but->optype || but->func_arg1) {
if (but->optype)
oli = uiOperatorListItemPresent(&ar->operators, but->optype->idname, but->opptr ? but->opptr->data : NULL, CTX_data_mode_string(C));
else
oli = (OperatorListItem*)but->func_arg1;
if (oli) {
data = MEM_callocN(sizeof(uiHandleRegionDragData), "uiHandleRegionDragData");
data->state = REGION_STATE_DRAG_BUTTON_WAITING;
data->startx = win->eventstate->x;
data->starty = win->eventstate->y;
data->oli = oli;
ar->dragdata = (void*)data;
WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_region_drag_shelf, ui_handler_region_drag_shelf_remove, ar);
}
}
}
}
else if (state == REGION_STATE_DRAG_BUTTON) {
if (data) data->state = state;
}
ED_region_tag_redraw(ar);
}
static int ui_handler_region(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *ar;
@@ -7555,22 +7859,33 @@ static int ui_handler_region(bContext *C, const wmEvent *event, void *UNUSED(use
/* either handle events for already activated button or try to activate */
but = ui_but_find_activated(ar);
/* capture button drags in the MENU_BAR region so that we can do custom drag and drop */
if (ar->regiontype == RGN_TYPE_MENU_BAR) {
/* start drag */
if (but && event->type == LEFTMOUSE && event->val == KM_PRESS) {
region_activate_drag_state(C, ar, REGION_STATE_DRAG_BUTTON_WAITING);
}
}
retval = ui_handler_panel_region(C, event);
if (retval == WM_UI_HANDLER_CONTINUE)
retval = ui_handle_list_event(C, event, ar);
if (retval == WM_UI_HANDLER_CONTINUE) {
/* only if there's no drag going on inside the region */
if (retval == WM_UI_HANDLER_CONTINUE)
{
if (but)
retval = ui_handle_button_event(C, event, but);
else
retval = ui_handle_button_over(C, event, ar);
}
/* re-enable tooltips */
/* re-enable tooltips, only if there's no drag going on inside the region */
if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy))
ui_blocks_set_tooltips(ar, true);
if (ar->dragdata == NULL)
ui_blocks_set_tooltips(ar, true);
/* delayed apply callbacks */
ui_apply_but_funcs_after(C);

View File

@@ -77,9 +77,6 @@
#include "interface_intern.h"
#ifndef WITH_HEADLESS
#define ICON_GRID_COLS 26
#define ICON_GRID_ROWS 30
#define ICON_GRID_MARGIN 10
#define ICON_GRID_W 32
#define ICON_GRID_H 32
@@ -130,6 +127,7 @@ typedef struct IconTexture {
* scanning the filesystem each time the menu is drawn */
static struct ListBase iconfilelist = {NULL, NULL};
static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
static IconTexture opicongltex = {0, 0, 0, 0.0f, 0.0f};
/* **************************************************** */
@@ -587,11 +585,78 @@ static void init_matcap_icons(void)
}
static void generate_mipmaps(ImBuf **b32buf, ImBuf **b16buf, IconTexture *gltex, int rows, int cols, int offset)
{
int x, y, icontype;
if (*b16buf && *b32buf) {
/* free existing texture if any */
if (gltex->id) {
glDeleteTextures(1, &gltex->id);
gltex->id = 0;
}
/* we only use a texture for cards with non-power of two */
if (GPU_non_power_of_two_support()) {
glGenTextures(1, &gltex->id);
if (gltex->id) {
int level = 2;
gltex->w = (*b32buf)->x;
gltex->h = (*b32buf)->y;
gltex->invw = 1.0f / (*b32buf)->x;
gltex->invh = 1.0f / (*b32buf)->y;
glBindTexture(GL_TEXTURE_2D, gltex->id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (*b32buf)->x, (*b32buf)->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, (*b32buf)->rect);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, (*b16buf)->x, (*b16buf)->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, (*b16buf)->rect);
while ((*b16buf)->x > 1) {
ImBuf *nbuf = IMB_onehalf(*b16buf);
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
level++;
IMB_freeImBuf(*b16buf);
*b16buf = nbuf;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
if (glGetError() == GL_OUT_OF_MEMORY) {
glDeleteTextures(1, &gltex->id);
gltex->id = 0;
}
}
}
}
if (gltex->id)
icontype = ICON_TYPE_TEXTURE;
else
icontype = ICON_TYPE_BUFFER;
if (*b32buf) {
for (y = 0; y < rows; y++) {
for (x = 0; x < cols; x++) {
def_internal_icon(*b32buf, offset + y * cols + x,
x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, ICON_GRID_W,
icontype);
}
}
}
}
static void init_internal_icons(void)
{
// bTheme *btheme = UI_GetTheme();
ImBuf *b16buf = NULL, *b32buf = NULL;
int x, y, icontype;
ImBuf *b16bufOps = NULL, *b32bufOps = NULL;
#if 0 // temp disabled
if ((btheme != NULL) && btheme->tui.iconfile[0]) {
@@ -612,6 +677,8 @@ static void init_internal_icons(void)
}
}
#endif
/* interface icons */
if (b16buf == NULL)
b16buf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons16_png,
datatoc_blender_icons16_png_size, IB_rect, NULL, "<blender icons>");
@@ -624,67 +691,8 @@ static void init_internal_icons(void)
if (b32buf)
IMB_premultiply_alpha(b32buf);
if (b16buf && b32buf) {
/* free existing texture if any */
if (icongltex.id) {
glDeleteTextures(1, &icongltex.id);
icongltex.id = 0;
}
/* we only use a texture for cards with non-power of two */
if (GPU_non_power_of_two_support()) {
glGenTextures(1, &icongltex.id);
if (icongltex.id) {
int level = 2;
icongltex.w = b32buf->x;
icongltex.h = b32buf->y;
icongltex.invw = 1.0f / b32buf->x;
icongltex.invh = 1.0f / b32buf->y;
glBindTexture(GL_TEXTURE_2D, icongltex.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
while (b16buf->x > 1) {
ImBuf *nbuf = IMB_onehalf(b16buf);
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
level++;
IMB_freeImBuf(b16buf);
b16buf = nbuf;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
if (glGetError() == GL_OUT_OF_MEMORY) {
glDeleteTextures(1, &icongltex.id);
icongltex.id = 0;
}
}
}
}
if (icongltex.id)
icontype = ICON_TYPE_TEXTURE;
else
icontype = ICON_TYPE_BUFFER;
generate_mipmaps(&b32buf, &b16buf, &icongltex, ICON_GRID_ROWS, ICON_GRID_COLS, BIFICONID_FIRST);
if (b32buf) {
for (y = 0; y < ICON_GRID_ROWS; y++) {
for (x = 0; x < ICON_GRID_COLS; x++) {
def_internal_icon(b32buf, BIFICONID_FIRST + y * ICON_GRID_COLS + x,
x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, ICON_GRID_W,
icontype);
}
}
}
def_internal_vicon(VICO_VIEW3D_VEC, vicon_view3d_draw);
def_internal_vicon(VICO_EDIT_VEC, vicon_edit_draw);
def_internal_vicon(VICO_EDITMODE_VEC_DEHLT, vicon_editmode_dehlt_draw);
@@ -695,10 +703,28 @@ static void init_internal_icons(void)
def_internal_vicon(VICO_MOVE_DOWN_VEC, vicon_move_down_draw);
def_internal_vicon(VICO_X_VEC, vicon_x_draw);
def_internal_vicon(VICO_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
IMB_freeImBuf(b16buf);
IMB_freeImBuf(b32buf);
/* operator icons */
if (b16bufOps == NULL)
b16bufOps = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_operator_icons16_png,
datatoc_blender_operator_icons16_png_size, IB_rect, NULL, "<blender operator icons>");
if (b16bufOps)
IMB_premultiply_alpha(b16bufOps);
if (b32bufOps == NULL)
b32bufOps = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_operator_icons32_png,
datatoc_blender_operator_icons32_png_size, IB_rect, NULL, "<blender operator icons>");
if (b32bufOps)
IMB_premultiply_alpha(b32bufOps);
generate_mipmaps(&b32bufOps, &b16bufOps, &opicongltex, OPICON_GRID_ROWS, OPICON_GRID_COLS, BIFICONID_FIRST_OP);
IMB_freeImBuf(b16bufOps);
IMB_freeImBuf(b32bufOps);
}
#endif /* WITH_HEADLESS */
@@ -808,6 +834,11 @@ void UI_icons_free(void)
glDeleteTextures(1, &icongltex.id);
icongltex.id = 0;
}
if (opicongltex.id) {
glDeleteTextures(1, &opicongltex.id);
opicongltex.id = 0;
}
free_iconfile_list(&iconfilelist);
BKE_icons_free();
@@ -1035,20 +1066,21 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
}
static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy,
int UNUSED(iw), int ih, float alpha, const float rgb[3])
int UNUSED(iw), int ih, float alpha, const float rgb[3],
IconTexture *icontex)
{
float x1, x2, y1, y2;
if (rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha);
else glColor4f(alpha, alpha, alpha, alpha);
x1 = ix * icongltex.invw;
x2 = (ix + ih) * icongltex.invw;
y1 = iy * icongltex.invh;
y2 = (iy + ih) * icongltex.invh;
x1 = ix * icontex->invw;
x2 = (ix + ih) * icontex->invw;
y1 = iy * icontex->invh;
y2 = (iy + ih) * icontex->invh;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
glBindTexture(GL_TEXTURE_2D, icontex->id);
/* sharper downscaling, has no effect when scale matches with a mip level */
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.5f);
@@ -1126,7 +1158,8 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al
/* texture image use premul alpha for correct scaling */
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
di->data.texture.w, di->data.texture.h, alpha, rgb);
di->data.texture.w, di->data.texture.h, alpha, rgb,
(icon_id >= BIFICONID_FIRST_OP ? &opicongltex : &icongltex));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else if (di->type == ICON_TYPE_BUFFER) {

View File

@@ -37,6 +37,7 @@
#include "RNA_types.h"
struct ARegion;
struct OperatorListItem;
struct bContext;
struct IDProperty;
struct uiHandleButtonData;
@@ -163,7 +164,7 @@ typedef struct {
struct uiBut {
struct uiBut *next, *prev;
int flag, drawflag;
int flag, flag2, drawflag;
eButType type;
eButPointerType pointype;
short bit, bitnr, retval, strwidth, alignnr;
@@ -458,6 +459,24 @@ struct uiPopupBlockHandle {
int direction;
};
typedef enum uiHandleRegionDragState {
REGION_STATE_DRAG_BUTTON_WAITING,
REGION_STATE_DRAG_BUTTON,
REGION_STATE_DRAG_EXIT
} uiHandleRegionDragState;
struct uiHandleRegionDragData {
/* keep track of dragging state */
uiHandleRegionDragState state;
/* info for dragging */
int startx, starty;
/* custom button */
OperatorListItem *oli;
int newindex;
};
uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
struct ARegion *ui_tooltip_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
@@ -497,7 +516,7 @@ struct AutoComplete;
/* interface_panel.c */
extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event);
extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, rcti *rect);
extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, rcti *rect, int toolbar);
/* interface_draw.c */
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
@@ -519,6 +538,7 @@ extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_execute_do(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_active_free(const struct bContext *C, uiBut *but);
extern uiBut *ui_but_find_activated(ARegion *ar);
extern bool ui_button_is_active(struct ARegion *ar);
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, int restore);

View File

@@ -146,6 +146,7 @@ struct uiLayout {
bool redalert;
bool keepaspect;
char alignment;
float button_height;
};
typedef struct uiLayoutItemFlow {
@@ -237,13 +238,14 @@ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, int
return (variable) ? UI_GetStringWidth(name) + (compact ? f5 : f10) + UI_UNIT_X : 10 * UI_UNIT_X; /* text only */
}
static void ui_item_size(uiItem *item, int *r_w, int *r_h)
static void ui_item_size(uiLayout *layout, uiItem *item, int *r_w, int *r_h)
{
if (item->type == ITEM_BUTTON) {
uiButtonItem *bitem = (uiButtonItem *)item;
if (r_w) *r_w = BLI_rctf_size_x(&bitem->but->rect);
if (r_h) *r_h = BLI_rctf_size_y(&bitem->but->rect);
if (r_h) *r_h = BLI_rctf_size_y(&bitem->but->rect) *
(layout->button_height ? layout->button_height : 1.0f);
}
else {
uiLayout *litem = (uiLayout *)item;
@@ -693,19 +695,28 @@ PointerRNA uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *nam
name = "";
}
/* Make sure that if it is indicated a button shouldn't be truncated to a
single X unit, and a shortcut should be shown, then make sure we get
the right width. */
if ((!(flag & UI_ITEM_O_SINGLE_UNIT) || flag & UI_ITEM_O_SHORTCUT)
&& block->flag & UI_BLOCK_SHORTCUTS)
w = ui_text_icon_width(layout, "|", icon, 0);
else if (flag & UI_ITEM_O_SINGLE_UNIT)
w = UI_UNIT_X;
else
w = ui_text_icon_width(layout, name, icon, 0);
if (layout->root->type == UI_LAYOUT_MENU && !icon)
icon = ICON_BLANK1;
/* create button */
uiBlockSetCurLayout(block, layout);
w = ui_text_icon_width(layout, name, icon, 0);
if (flag & UI_ITEM_R_NO_BG)
uiBlockSetEmboss(block, UI_EMBOSSN);
/* create the button */
if (icon) {
if (icon != 0) {
if (name[0]) {
but = uiDefIconTextButO_ptr(block, BUT, ot, context, icon, name, 0, 0, w, UI_UNIT_Y, NULL);
}
@@ -716,12 +727,24 @@ PointerRNA uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *nam
else {
but = uiDefButO_ptr(block, BUT, ot, context, name, 0, 0, w, UI_UNIT_Y, NULL);
}
/* Only show extra text when we're in a shortcut block and it was
indicated the shortcut should be shown */
if (flag & UI_ITEM_O_SHORTCUT && block->flag & UI_BLOCK_SHORTCUTS)
but->flag2 |= UI_BUT2_EXTRA_TEXT;
/* Make operator buttons draggable */
uiButSetDragOp(but, ot);
assert(but->optype != NULL);
/* text alignment for toolbar buttons */
if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon)
if ((layout->root->type == UI_LAYOUT_TOOLBAR) && (!icon || flag & UI_ITEM_O_SHORTCUT)) {
but->flag |= UI_TEXT_LEFT;
}
if (layout->root->type == UI_LAYOUT_TOOLBAR && !(flag & UI_ITEM_O_SHORTCUT) && !name[0])
but->flag &= ~UI_ICON_LEFT;
if (flag & UI_ITEM_R_NO_BG)
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -1801,6 +1824,41 @@ void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propn
ui_item_menu(layout, name, icon, menu_item_enum_rna_menu, NULL, lvl, RNA_property_description(prop), false);
}
/********************* OperatorListItem utilities ********************/
/* return 1 when an OperatorListItem with the same name and properties is already present in lb */
OperatorListItem *uiOperatorListItemPresent(ListBase *lb, const char *idname, IDProperty *properties, const char *context)
{
OperatorListItem *oli;
for (oli = lb->first; oli; oli = oli->next) {
if (strcmp(oli->optype_idname, idname) == 0) {
if (strcmp(oli->context, context) == 0) {
/* if no idprops are present, and the name is the same */
if (oli->properties == NULL && properties == NULL) {
return oli;
}
/* if one of the properties is set, then they are not equal */
else if (oli->properties == NULL || properties == NULL) {
continue;
}
else if (IDP_EqualsProperties(oli->properties, properties)) {
return oli;
}
}
else
continue;
}
else {
continue;
}
}
return NULL;
}
/**************************** Layout Items ***************************/
/* single-row layout */
@@ -1813,7 +1871,7 @@ static void ui_litem_estimate_row(uiLayout *litem)
litem->h = 0;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
litem->w += itemw;
litem->h = MAX2(itemh, litem->h);
@@ -1841,7 +1899,7 @@ static void ui_litem_layout_row(uiLayout *litem)
tot = 0;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
totw += itemw;
tot++;
}
@@ -1863,7 +1921,7 @@ static void ui_litem_layout_row(uiLayout *litem)
if (item->flag)
continue;
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
minw = ui_litem_min_width(itemw);
if (w - lastw > 0)
@@ -1895,7 +1953,7 @@ static void ui_litem_layout_row(uiLayout *litem)
x = litem->x;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
minw = ui_litem_min_width(itemw);
if (item->flag) {
@@ -1944,7 +2002,7 @@ static void ui_litem_estimate_column(uiLayout *litem)
litem->h = 0;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
litem->w = MAX2(litem->w, itemw);
litem->h += itemh;
@@ -1963,7 +2021,7 @@ static void ui_litem_layout_column(uiLayout *litem)
y = litem->y;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, NULL, &itemh);
ui_item_size(litem, item, NULL, &itemh);
y -= itemh;
ui_item_position(item, x, y, litem->w, itemh);
@@ -2045,7 +2103,7 @@ static void ui_litem_estimate_column_flow(uiLayout *litem)
toth = 0;
totitem = 0;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
maxw = MAX2(maxw, itemw);
toth += itemh;
totitem++;
@@ -2076,7 +2134,7 @@ static void ui_litem_estimate_column_flow(uiLayout *litem)
/* create column per column */
col = 0;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
y -= itemh + style->buttonspacey;
miny = min_ii(miny, y);
@@ -2109,7 +2167,7 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
toth = 0;
totitem = 0;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
toth += itemh;
totitem++;
}
@@ -2126,7 +2184,7 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
/* create column per column */
col = 0;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, NULL, &itemh);
ui_item_size(litem, item, NULL, &itemh);
itemw = ui_item_fit(1, x - litem->x, flow->totcol, w, col == flow->totcol - 1, litem->alignment, &offset);
y -= itemh;
@@ -2162,7 +2220,7 @@ static void ui_litem_estimate_absolute(uiLayout *litem)
for (item = litem->items.first; item; item = item->next) {
ui_item_offset(item, &itemx, &itemy);
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
minx = min_ii(minx, itemx);
miny = min_ii(miny, itemy);
@@ -2188,7 +2246,7 @@ static void ui_litem_layout_absolute(uiLayout *litem)
for (item = litem->items.first; item; item = item->next) {
ui_item_offset(item, &itemx, &itemy);
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
minx = min_ii(minx, itemx);
miny = min_ii(miny, itemy);
@@ -2210,7 +2268,7 @@ static void ui_litem_layout_absolute(uiLayout *litem)
for (item = litem->items.first; item; item = item->next) {
ui_item_offset(item, &itemx, &itemy);
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
if (scalex != 1.0f) {
newx = (itemx - minx) * scalex;
@@ -2260,7 +2318,7 @@ static void ui_litem_layout_split(uiLayout *litem)
colw = MAX2(colw, 0);
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, NULL, &itemh);
ui_item_size(litem, item, NULL, &itemh);
ui_item_position(item, x, y - itemh, colw, itemh);
x += colw;
@@ -2289,7 +2347,7 @@ static void ui_litem_estimate_overlap(uiLayout *litem)
litem->h = 0;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
litem->w = MAX2(itemw, litem->w);
litem->h = MAX2(itemh, litem->h);
@@ -2305,7 +2363,7 @@ static void ui_litem_layout_overlap(uiLayout *litem)
y = litem->y;
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_size(litem, item, &itemw, &itemh);
ui_item_position(item, x, y - itemh, litem->w, itemh);
litem->h = MAX2(litem->h, itemh);
@@ -2316,10 +2374,11 @@ static void ui_litem_layout_overlap(uiLayout *litem)
}
/* layout create functions */
uiLayout *uiLayoutRow(uiLayout *layout, int align)
static uiLayout *ui_layout_row(uiLayout *layout, int align, float button_height)
{
uiLayout *litem;
litem = MEM_callocN(sizeof(uiLayout), "uiLayoutRow");
litem->item.type = ITEM_LAYOUT_ROW;
litem->root = layout->root;
@@ -2330,14 +2389,25 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align)
litem->space = (align) ? 0 : layout->root->style->buttonspacex;
litem->redalert = layout->redalert;
litem->w = layout->w;
litem->button_height = button_height;
BLI_addtail(&layout->items, litem);
uiBlockSetCurLayout(layout->root->block, litem);
return litem;
}
uiLayout *uiLayoutColumn(uiLayout *layout, int align)
uiLayout *uiLayoutRowWithButtonHeight(uiLayout *layout, int align, float button_height)
{
return ui_layout_row(layout, align, button_height);
}
uiLayout *uiLayoutRow(uiLayout *layout, int align)
{
return ui_layout_row(layout, align, 1.0f);
}
static uiLayout *ui_layout_column(uiLayout *layout, int align, float button_height)
{
uiLayout *litem;
@@ -2351,6 +2421,7 @@ uiLayout *uiLayoutColumn(uiLayout *layout, int align)
litem->space = (litem->align) ? 0 : layout->root->style->buttonspacey;
litem->redalert = layout->redalert;
litem->w = layout->w;
litem->button_height = button_height;
BLI_addtail(&layout->items, litem);
uiBlockSetCurLayout(layout->root->block, litem);
@@ -2358,6 +2429,16 @@ uiLayout *uiLayoutColumn(uiLayout *layout, int align)
return litem;
}
uiLayout *uiLayoutColumn(uiLayout *layout, int align)
{
return ui_layout_column(layout, align, 1.0f);
}
uiLayout *uiLayoutColumnWithButtonHeight(uiLayout *layout, int align, float button_height)
{
return ui_layout_column(layout, align, button_height);
}
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
{
uiLayoutItemFlow *flow;
@@ -2601,7 +2682,7 @@ static void ui_item_scale(uiLayout *litem, const float scale[2])
int x, y, w, h;
for (item = litem->items.last; item; item = item->prev) {
ui_item_size(item, &w, &h);
ui_item_size(litem, item, &w, &h);
ui_item_offset(item, &x, &y);
if (scale[0] != 0.0f) {
@@ -3107,6 +3188,69 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,
}
}
void uiLayoutOperatorTypeDefaultsButs(const bContext *C, uiLayout *layout, wmOperator *op)
{
char *h = BLI_sprintfN("Default parameters: %s", RNA_struct_ui_name(op->type->srna));
uiItemL(layout, h, ICON_NONE);
MEM_freeN(h);
// use operator's custom panel
if (op->type->ui) {
op->layout = layout;
op->type->ui((bContext *)C, op);
op->layout = NULL;
}
// autogenerate panel
else {
wmWindowManager *wm = CTX_wm_manager(C);
PointerRNA ptr;
int empty;
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
empty = uiDefAutoButsRNA(layout, &ptr, NULL, 'V') == 0;
if (empty) {
uiItemL(layout, IFACE_("No Properties"), ICON_NONE);
}
}
#ifdef USE_OP_RESET_BUT
/* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled
* but this is not so important if this button is drawn in those cases
* (which isn't all that likely anyway) - campbell */
if (op->properties->len) {
uiBlock *block;
uiBut *but;
uiLayout *col; /* needed to avoid alignment errors with previous buttons */
col = uiLayoutColumn(layout, FALSE);
block = uiLayoutGetBlock(col);
but = uiDefIconTextBut(block, BUT, 0, ICON_FILE_REFRESH, IFACE_("Reset"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Reset operator defaults"));
uiButSetFunc(but, ui_layout_operator_buts__reset_cb, op, NULL);
}
#endif
/* set various special settings for buttons */
{
uiBut *but;
for (but = uiLayoutGetBlock(layout)->buttons.first; but; but = but->next) {
/* no undo for buttons for operator redo panels */
uiButClearFlag(but, UI_BUT_UNDO);
/* if button is operator's default property, and a text-field, enable focus for it
* - this is used for allowing operators with popups to rename stuff with fewer clicks
*/
if ((but->rnaprop == op->type->prop) && (but->type == TEX)) {
uiButSetFocusOnEnter(CTX_wm_window(C), but);
}
}
}
}
/* this is a bit of a hack but best keep it in one place at least */
MenuType *uiButGetMenuType(uiBut *but)
{

View File

@@ -49,6 +49,8 @@
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_report.h"
#include "BKE_idprop.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -61,6 +63,8 @@
#include "UI_interface.h"
#include "UI_resources.h"
#include "RNA_access.h"
#include "interface_intern.h"
/*********************** defines and structs ************************/
@@ -68,19 +72,14 @@
#define ANIMATION_TIME 0.30
#define ANIMATION_INTERVAL 0.02
#define PNL_LAST_ADDED 1
#define PNL_ACTIVE 2
#define PNL_WAS_ACTIVE 4
#define PNL_ANIM_ALIGN 8
#define PNL_NEW_ADDED 16
#define PNL_FIRST 32
typedef enum uiHandlePanelState {
PANEL_STATE_DRAG,
PANEL_STATE_DRAG_SCALE,
PANEL_STATE_WAIT_UNTAB,
PANEL_STATE_ANIMATION,
PANEL_STATE_EXIT
PANEL_STATE_EXIT,
PANEL_STATE_DRAG_BUTTON_WAITING,
PANEL_STATE_DRAG_BUTTON
} uiHandlePanelState;
typedef struct uiHandlePanelData {
@@ -94,6 +93,11 @@ typedef struct uiHandlePanelData {
int startx, starty;
int startofsx, startofsy;
int startsizex, startsizey;
/* dragging custom button */
OperatorListItem *oli;
int newindex;
} uiHandlePanelData;
static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state);
@@ -162,21 +166,29 @@ static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa)
/****************************** panels ******************************/
static void panels_collapse_all(ScrArea *sa, ARegion *ar, Panel *from_pa)
void uiCollapseAllPanels(ScrArea *sa, ARegion *ar, const char *context)
{
Panel *pa;
PanelType *pt, *from_pt;
PanelType *pt;
int flag = ((panel_aligned(sa, ar) == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY);
for (pa = ar->panels.first; pa; pa = pa->next) {
pt = pa->type;
from_pt = from_pa->type;
/* close panels with headers in the same context */
if (pt && from_pt && !(pt->flag & PNL_NO_HEADER))
if (!pt->context[0] || strcmp(pt->context, from_pt->context) == 0)
pa->flag = flag;
if (pt && context && !(pt->flag & PNL_NO_HEADER))
if (!pt->context[0] || strcmp(pt->context, context) == 0) {
pa->flag |= flag;
pa->ofsx = 0;
pa->ofsy = 0;
pa->sizex = 0;
pa->sizey = 0;
pa->runtime_flag |= PNL_NEW_ADDED;
}
}
ED_region_tag_redraw(ar);
}
@@ -188,6 +200,20 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
pa->ofsy = papar->ofsy + papar->sizey - pa->sizey;
}
Panel *uiGetExistingPanel(ARegion *ar, PanelType *pt)
{
Panel *pa = NULL;
for (pa = ar->panels.first; pa; pa = pa->next)
if (strncmp(pa->panelname, pt->idname, UI_MAX_NAME_STR) == 0)
if (strncmp(pa->tabname, pt->idname, UI_MAX_NAME_STR) == 0) {
pa->type = pt;
break;
}
return pa;
}
Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int *open)
{
Panel *pa, *patab, *palast, *panext;
@@ -199,17 +225,11 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int
int align = panel_aligned(sa, ar);
/* check if Panel exists, then use that one */
for (pa = ar->panels.first; pa; pa = pa->next)
if (strncmp(pa->panelname, idname, UI_MAX_NAME_STR) == 0)
if (strncmp(pa->tabname, tabname, UI_MAX_NAME_STR) == 0)
break;
pa = uiGetExistingPanel(ar, pt);
newpanel = (pa == NULL);
if (!newpanel) {
pa->type = pt;
}
else {
if (newpanel) {
/* new panel */
pa = MEM_callocN(sizeof(Panel), "new panel");
pa->type = pt;
@@ -228,6 +248,12 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int
pa->sizex = 0;
pa->sizey = 0;
pa->runtime_flag |= PNL_NEW_ADDED;
// Mark the new panel as custom so we know we have to generate the PanelTypes upon loading
if (pt->flag & PNL_CUSTOM_PANELTYPE) {
pa->flag |= PNL_CUSTOM_PANEL;
BLI_strncpy(pa->context, pt->context, MAX_NAME);
}
BLI_addtail(&ar->panels, pa);
@@ -437,6 +463,28 @@ static void ui_draw_panel_scalewidget(rcti *rect)
glDisable(GL_BLEND);
}
static void ui_draw_panel_openwidget(const rctf *rect)
{
float xmin, xmax, dx;
float ymin, ymax, dy;
xmin = rect->xmin;
xmax = rect->xmax;
ymin = rect->ymin;
ymax = rect->ymax;
dx = (xmax - xmin);
dy = (ymax - ymin);
glEnable(GL_BLEND);
glColor4ub(0, 0, 0, 150);
fdrawellipses(xmin, ymin + dy / 2.f, dx / 10.f);
glDisable(GL_BLEND);
}
static void ui_draw_panel_dragwidget(const rctf *rect)
{
float xmin, xmax, dx;
@@ -484,6 +532,7 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, rcti *r
hrect = *rect;
if (dir == 'h') {
hrect.xmin = rect->xmin + pnl_icons;
hrect.xmax = hrect.xmin + BLI_rcti_size_x(&hrect) - (2*PNL_ICON) / block->aspect;
hrect.ymin += 2.0f / block->aspect;
uiStyleFontDraw(&style->paneltitle, &hrect, activename);
}
@@ -510,7 +559,7 @@ static void rectf_scale(rctf *rect, const float scale)
}
/* panel integrated in buttonswindow, tool/property lists etc */
void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect, int UNUSED(toolbar))
{
Panel *panel = block->panel;
rcti headrect;
@@ -573,6 +622,16 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
* (------)
*/
if (panel->flag & PNL_CLOSEDY) {
// Uncomment to only show popup ellipses in the toolbar.
//if (toolbar) {
/* draw popup widget */
itemrect.xmax = headrect.xmax - (1.0f + PNL_ICON) / block->aspect;
itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect);
itemrect.ymin = headrect.ymin;
itemrect.ymax = headrect.ymax;
rectf_scale(&itemrect, 0.7f);
ui_draw_panel_openwidget(&itemrect);
//}
}
else if (panel->flag & PNL_CLOSEDX) {
/* draw vertical title */
@@ -631,6 +690,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
(void)ofsx;
}
/************************** panel alignment *************************/
static int get_panel_header(Panel *pa)
@@ -871,9 +931,12 @@ static void ui_do_animate(const bContext *C, Panel *panel)
}
}
void uiBeginPanels(const bContext *UNUSED(C), ARegion *ar)
void uiBeginPanels(const bContext *C, ARegion *ar)
{
ScrArea *sa = CTX_wm_area(C);
const char *context = CTX_data_mode_string(C);
Panel *pa;
PanelType *pt;
/* set all panels as inactive, so that at the end we know
* which ones were used */
@@ -882,6 +945,14 @@ void uiBeginPanels(const bContext *UNUSED(C), ARegion *ar)
pa->runtime_flag = PNL_WAS_ACTIVE;
else
pa->runtime_flag = 0;
/* Only create a custom paneltype when the panel is a custom panel
* and it's the correct context. */
if (pa->type == NULL && pa->flag & PNL_CUSTOM_PANEL && strcmp(context, pa->context) == 0) {
/* recreate custom paneltypes for typeless panels */
pt = uiCreateCustomPanelType(sa, ar, context, pa->panelname, pa->drawname);
pa->type = pt;
}
}
}
@@ -1055,17 +1126,182 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
ED_region_tag_redraw(ar);
}
static void ui_do_drag_button(const bContext *C, const wmEvent *event, Panel *pa)
{
uiHandlePanelData *data = pa->activedata;
ARegion *ar = CTX_wm_region(C);
int cur_index = BLI_findindex(&pa->operators, data->oli);
int dy, dunits, maxindex;
// Calculate the new index of the button based on the drag offset
dy = event->y - data->starty;
dunits = dy / UI_UNIT_Y;
data->newindex = (cur_index - dunits);
maxindex = (BLI_countlist(&pa->operators) - 1);
CLAMP(data->newindex, 0, maxindex);
ED_region_tag_redraw(ar);
}
static void ui_do_drag_button_finish(const bContext *C, const wmEvent *UNUSED(event), Panel *pa)
{
uiHandlePanelData *data = pa->activedata;
ARegion *ar = CTX_wm_region(C);
int cur_index = BLI_findindex(&pa->operators, data->oli);
OperatorListItem *oli_target = BLI_findlink(&pa->operators, data->newindex);
if (data->newindex < cur_index) {
BLI_remlink(&pa->operators, data->oli);
BLI_insertlinkbefore(&pa->operators, oli_target, data->oli);
}
else if (data->newindex > cur_index) {
BLI_remlink(&pa->operators, data->oli);
BLI_insertlinkafter(&pa->operators, oli_target, data->oli);
}
ED_region_tag_redraw(ar);
}
/******************* region level panel interaction *****************/
static void panel_popup_draw(bContext *C, uiBlock *block, Panel *pa)
{
uiStyle *style = UI_GetStyleDraw();
Panel *pa_copy;
int xco, yco;
int w = UI_PANEL_WIDTH / 2;
int em = UI_UNIT_Y;
if (pa) {
/* Create a copy of the panel so that we can reset the ofset */
pa_copy = MEM_callocN(sizeof(Panel), "new panel");
memcpy(pa_copy, pa, sizeof(Panel));
pa_copy->ofsx = 0;
pa_copy->ofsy = 0;
pa_copy->sizex = 0;
pa_copy->sizey = 0;
uiBlockSetPanel(block, pa_copy);
pa_copy->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_TOOLBAR,
style->panelspace, 0, w - 2 * style->panelspace, em, style);
pa_copy->type->draw(C, pa_copy);
pa_copy->labelofs = 0;
uiBlockLayoutResolve(block, &xco, &yco);
yco -= 2 * style->panelspace;
uiEndPanel(block, w, 0);
uiBlockSetPanel(block, NULL);
/* N.B. don't use uiPanelFree because the operator list is shared with the original. */
MEM_freeN(pa_copy);
}
}
static uiBlock *panel_popup_create_block(bContext *C, ARegion *ar, void *pa_arg)
{
uiBlock *block;
Panel *pa = (Panel*)pa_arg;
block = uiBeginBlock(C, ar, "popup", UI_EMBOSS);
uiBlockClearFlag(block, UI_BLOCK_LOOP);
uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
panel_popup_draw(C, block, pa);
uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
uiEndBlock(C, block);
return block;
}
static void rename_custom_panel(bContext *C, void *but_arg, void *pa_arg)
{
uiBut *but = but_arg;
Panel *pa = pa_arg;
ARegion *ar = CTX_wm_region(C);
if (pa->type) {
BLI_strncpy(pa->type->label, but->drawstr, MAX_NAME);
BLI_strncpy(pa->drawname, but->drawstr, MAX_NAME);
}
ED_region_tag_redraw(ar);
}
static void delete_custom_panel(bContext *C, void *pa_arg, void *UNUSED(arg2))
{
Panel *pa = pa_arg;
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
if (pa->type && ar->type)
BLI_freelinkN(&ar->type->paneltypes, pa->type);
BLI_remlink(&ar->panels, pa);
uiPanelFree(pa);
/* make sure we don't leave gaps in the layout */
for (pa = ar->panels.first; pa; pa = pa->next) {
panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
}
ED_region_tag_redraw(ar);
}
static uiBlock *custom_panel_options_create_block(bContext *C, ARegion *ar, void *pa_arg)
{
uiBlock *block;
Panel *pa = (Panel*)pa_arg; // the custom panel
uiLayout *layout;
uiBut *but;
PointerRNA ptr;
uiStyle *style = UI_GetStyleDraw();
int xco, yco;
int w = UI_PANEL_WIDTH / 2;
int em = UI_UNIT_Y;
block = uiBeginBlock(C, ar, "panel options", UI_EMBOSS);
uiBlockClearFlag(block, UI_BLOCK_LOOP);
uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_TOOLBAR,
style->panelspace, 0, w - 2 * style->panelspace, em, style);
/* Rename panel */
RNA_pointer_create(NULL, &RNA_Panel, pa, &ptr);
but = uiDefButR(block, TEX, 1, "", 0, 0, w, UI_UNIT_Y,
&ptr, "text", -1, 0, 0, -1, -1, NULL);
uiButSetFunc(but, rename_custom_panel, but, pa);
/* Delete panel button */
but = uiDefIconTextBut(block, BUTM, 0, ICON_NONE, IFACE_("Delete Panel"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
uiButSetFunc(but, delete_custom_panel, pa, NULL);
uiBlockLayoutResolve(block, &xco, &yco);
uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
uiEndBlock(C, block);
return block;
}
/* this function is supposed to call general window drawing too */
/* also it supposes a block has panel, and isn't a menu */
static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event, int ctrl)
static void ui_handle_panel_header(bContext *C, uiBlock *block, int mx, int my, int event, int ctrl)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Panel *pa;
int align = panel_aligned(sa, ar), button = 0;
int x_popup = block->rect.xmax - ((2 * PNL_ICON) + 5) / block->aspect;
int x_drag = block->rect.xmax - (PNL_ICON + 5) / block->aspect;
/* mouse coordinates in panel space! */
@@ -1081,20 +1317,30 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
}
else if (block->panel->control & UI_PNL_CLOSE) {
/* whole of header can be used to collapse panel (except top-right corner) */
if (mx <= block->rect.xmax - 8 - PNL_ICON) button = 2;
//else if (mx <= block->rect.xmin + 10 + 2 * PNL_ICON + 2) button = 1;
if (mx <= x_drag) button = 2;
}
else if (mx <= block->rect.xmax - PNL_ICON - 12) {
button = 1;
}
if (button) {
if (button == 2) { /* close */
ED_region_tag_redraw(ar);
// only shows popups in toolbars
else if (block->panel->flag & PNL_CLOSEDY /*&& ar->regiontype == RGN_TYPE_TOOLS*/) {
if (mx <= x_popup) {
button = 1;
} else if (mx > x_popup && mx <= x_drag) {
button = 3; // popup!
} else if (mx > x_drag) {
button = 4; // drag
}
else { /* collapse */
} else {
if (mx > x_drag) {
button = 4; // drag
} else {
button = 1; // open
}
}
switch (button) {
case 1:
/* collapse */
if (ctrl)
panels_collapse_all(sa, ar, block->panel);
uiCollapseAllPanels(sa, ar, CTX_data_mode_string(C));
if (block->panel->flag & PNL_CLOSED) {
block->panel->flag &= ~PNL_CLOSED;
@@ -1118,15 +1364,23 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
else pa->flag &= ~PNL_CLOSED;
}
}
}
if (align)
panel_activate_state(C, block->panel, PANEL_STATE_ANIMATION);
else
case 2:
/* close */
ED_region_tag_redraw(ar);
}
else if (mx <= (block->rect.xmax - PNL_ICON - 12) + PNL_ICON + 2) {
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
if (align)
panel_activate_state(C, block->panel, PANEL_STATE_ANIMATION);
if (ar->regiontype == RGN_TYPE_TOOL_PROPS) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* The size of the redo panel region needs to be calculated again */
CTX_wm_screen(C)->do_refresh = TRUE;
}
break;
case 3:
uiPupBlock(C, panel_popup_create_block, block->panel);
break;
case 4:
default:
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
}
}
@@ -1180,24 +1434,49 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event)
}
/* XXX hardcoded key warning */
if ((inside || inside_header) && event->val == KM_PRESS) {
if (event->type == AKEY && !ELEM4(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
if (pa->flag & PNL_CLOSEDY) {
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
if (inside || inside_header) {
if (event->val == KM_PRESS) {
if (event->type == AKEY && !ELEM4(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
if (pa->flag & PNL_CLOSEDY) {
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
}
else
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
retval = WM_UI_HANDLER_BREAK;
continue;
}
else
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
retval = WM_UI_HANDLER_BREAK;
continue;
}
}
/* on active button, do not handle panels */
if (ui_button_is_active(ar))
/* This catches the drag events here so that we can do our own custom drag instead
* of having the drag & drop system handle the button/op drag. */
/* on active button, do a possible button drag for reordering, but panels should
* not be handled. */
if (ui_button_is_active(ar)) {
uiBut *but = ui_but_find_activated(ar);
uiHandlePanelData *data;
if (inside && but && pa->flag & PNL_CUSTOM_PANEL) {
// Are we starting a potential drag?
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
panel_activate_state(C, pa, PANEL_STATE_DRAG_BUTTON_WAITING);
// pass the oli that is being dragged
data = pa->activedata;
// TODO: also check for oli->properties equality
data->oli = BLI_findstring(&pa->operators, but->optype->idname, offsetof(OperatorListItem, optype_idname));
}
}
// Don't handle events for the panels if a button was activated
continue;
}
if (inside || inside_header) {
@@ -1266,6 +1545,9 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event)
}
#endif
}
else if (event->type == RIGHTMOUSE && pa->flag & PNL_CUSTOM_PANEL) {
uiPupBlock(C, custom_panel_options_create_block, block->panel);
}
}
}
}
@@ -1280,13 +1562,18 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata)
{
Panel *panel = userdata;
uiHandlePanelData *data = panel->activedata;
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
uiBut *but;
/* verify if we can stop */
if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
int align = panel_aligned(sa, ar);
if (data->state == PANEL_STATE_DRAG_BUTTON)
ui_do_drag_button_finish(C, event, panel);
if (align)
panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
else
@@ -1295,6 +1582,14 @@ static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata)
else if (event->type == MOUSEMOVE) {
if (data->state == PANEL_STATE_DRAG)
ui_do_drag(C, event, panel);
if (data->state == PANEL_STATE_DRAG_BUTTON_WAITING && ABS(data->starty - event->y) > (UI_UNIT_Y / 2)) {
panel_activate_state(C, panel, PANEL_STATE_DRAG_BUTTON);
but = ui_but_find_activated(ar);
ui_button_active_free(C, but);
return WM_UI_HANDLER_BREAK;
}
if (data->state == PANEL_STATE_DRAG_BUTTON)
ui_do_drag_button(C, event, panel);
}
else if (event->type == TIMER && event->customdata == data->animtimer) {
if (data->state == PANEL_STATE_ANIMATION)
@@ -1379,3 +1674,129 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
ED_region_tag_redraw(ar);
}
void uiPanelAddOperator(bContext *C, Panel *pa, wmOperatorType *ot, PointerRNA *opptr)
{
OperatorListItem *oli;
wmWindowManager *wm = CTX_wm_manager(C);
if (uiOperatorListItemPresent(&pa->operators, ot->idname, opptr->data, CTX_data_mode_string(C))) {
BKE_reportf(&wm->reports, RPT_INFO, "This operator (%s) is already present in this panel.", ot->idname);
return;
}
oli = MEM_callocN(sizeof(OperatorListItem), "panel type operator");
BLI_strncpy(oli->optype_idname, ot->idname, OP_MAX_TYPENAME);
BLI_strncpy(oli->context, CTX_data_mode_string(C), MAX_NAME);
if (opptr) {
PropertyRNA *prop;
prop = RNA_struct_find_property(opptr, "COPY_opcontext");
if(prop)
oli->opcontext = RNA_property_int_get(opptr, prop);
/* clear the properties that were only necessary for this operator execution */
/* TODO: see if this can all be done a little bit nicer by including a pointer as a property */
RNA_struct_idprops_unset(opptr, "COPY_opcontext");
RNA_struct_idprops_unset(opptr, "COPY_idname");
RNA_struct_idprops_unset(opptr, "COPY_paneltypeid");
oli->properties = IDP_CopyProperty(opptr->data);
}
BLI_addtail(&pa->operators, oli);
}
void uiPanelFree(Panel *pa)
{
if (pa == NULL) return;
OperatorListItem *oli;
while ((oli = (OperatorListItem*)BLI_pophead(&pa->operators))) {
BKE_operator_list_item_free(oli);
}
MEM_freeN(pa);
}
int uiPanelClosed(Panel *pa)
{
if (pa == NULL) return 0;
return (pa->flag & PNL_CLOSED || pa->flag & PNL_CLOSEDX || pa->flag & PNL_CLOSEDY);
}
static void custom_panel_draw_oli(const bContext *C, uiLayout *column, OperatorListItem *oli)
{
if (oli && column) {
wmOperatorType *ot = WM_operatortype_find(oli->optype_idname, TRUE);
int icon = ICON_NONE;
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
ptr.data = oli->properties;
icon = ot->icon ? ot->icon(C, &ptr) : ot->default_icon;
if (icon != ICON_NONE)
uiItemFullO_ptr(column, ot, ot->name, ICON_AUTOMATIC, IDP_CopyProperty(oli->properties), oli->opcontext, 0);
else
uiItemFullO_ptr(column, ot, ot->name, ICON_NONE, IDP_CopyProperty(oli->properties), oli->opcontext, 0);
}
}
static void custom_panel_draw(const bContext *C, Panel *pa)
{
uiHandlePanelData *data = pa->activedata;
uiLayout *layout = pa->layout;
uiLayout *column = uiLayoutColumn(layout, TRUE);
OperatorListItem *oli;
int drag_state = data ? (data->state == PANEL_STATE_DRAG_BUTTON) : 0;
int i = 0;
for (oli = pa->operators.first; oli; oli = oli->next) {
if (drag_state) {
// draw the new order of buttons
if (i == data->newindex) {
// Don't draw a separator for its current position
int cur_index = BLI_findindex(&pa->operators, data->oli);
// draw it before or after the button that currently has the new index
if (data->newindex == cur_index) {
custom_panel_draw_oli(C, column, oli);
}
else if (data->newindex < cur_index) {
custom_panel_draw_oli(C, column, data->oli);
custom_panel_draw_oli(C, column, oli);
}
else if (data->newindex > cur_index) {
custom_panel_draw_oli(C, column, oli);
custom_panel_draw_oli(C, column, data->oli);
}
}
// otherwise just draw normally
else if (oli != data->oli)
custom_panel_draw_oli(C, column, oli);
}
else
custom_panel_draw_oli(C, column, oli);
i++;
}
}
PanelType *uiCreateCustomPanelType(ScrArea *sa, ARegion *ar, const char *context, const char *name, const char *label)
{
PanelType *pt = MEM_callocN(sizeof(PanelType), "custom panel type");
// Create new panel type and add to the current editor's toolbar
BLI_strncpy(pt->idname, name, BKE_ST_MAXNAME);
strcpy(pt->label, label);
strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
// pt_new->draw_header = custom_panel_draw_header;
pt->draw = custom_panel_draw;
// pt_new->poll = custom_panel_poll;
pt->flag = PNL_CUSTOM_PANELTYPE;
pt->space_type = sa->type->spaceid;
pt->region_type = ar->regiontype;
BLI_strncpy(pt->context, context, BKE_ST_MAXNAME);
BLI_addtail(&ar->type->paneltypes, pt);
return pt;
}

View File

@@ -2829,3 +2829,36 @@ float *ui_block_hsv_get(uiBlock *block)
{
return block->_hsv;
}
/* OperatorListItem utility functions for dragging in the Menubar */
/* Retrieve the OperatorListItem that is being dragged */
OperatorListItem *uiRegionDraggedOperatorListItem(ARegion *ar)
{
OperatorListItem *oli = NULL;
uiHandleRegionDragData *data;
if (ar->dragdata) {
data = ar->dragdata;
if (data->state == REGION_STATE_DRAG_BUTTON) {
return data->oli;
}
}
return oli;
}
/* Retrieve the new index for the dropped OperatorListItem */
int uiRegionDraggedNewIndex(ARegion *ar)
{
uiHandleRegionDragData *data;
if (ar->dragdata) {
data = ar->dragdata;
if (data->state == REGION_STATE_DRAG_BUTTON) {
return data->newindex;
}
}
return 0;
}

View File

@@ -406,21 +406,21 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
// ListBase *lb; // UNUSED
ID *id, *idfrom;
int editable = RNA_property_editable(&template->ptr, template->prop);
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
id = idptr.data;
idfrom = template->ptr.id.data;
// lb = template->idlb;
block = uiLayoutGetBlock(layout);
uiBlockBeginAlign(block);
if (idptr.type)
type = idptr.type;
if (flag & UI_ID_PREVIEWS) {
template->preview = true;
but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6,
TIP_(template_id_browse_tip(type)));
if (type) {
@@ -436,32 +436,32 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
else if (flag & UI_ID_BROWSE) {
but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y,
TIP_(template_id_browse_tip(type)));
uiButSetDrawFlag(but, UI_BUT_DRAW_ENUM_ARROWS);
if (type) {
but->icon = RNA_struct_ui_icon(type);
/* default dragging of icon for id browse buttons */
uiButSetDragID(but, id);
uiButSetFlag(but, UI_HAS_ICON | UI_ICON_LEFT);
}
if ((idfrom && idfrom->lib) || !editable)
uiButSetFlag(but, UI_BUT_DISABLED);
}
/* text button with name */
if (id) {
char name[UI_MAX_NAME_STR];
const short user_alert = (id->us <= 0);
//text_idbutton(id, name);
name[0] = '\0';
but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y,
&idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type));
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
if (id->lib) {
if (id->flag & LIB_INDIRECT) {
but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
@@ -474,19 +474,19 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
if (!id_make_local(id, true /* test */) || (idfrom && idfrom->lib))
uiButSetFlag(but, UI_BUT_DISABLED);
}
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
}
if (id->us > 1) {
char numstr[32];
BLI_snprintf(numstr, sizeof(numstr), "%d", id->us);
but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y,
NULL, 0, 0, 0, 0,
TIP_("Display number of users of this data (click to make a single-user copy)"));
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
if (/* test only */
(id_copy(id, NULL, true) == false) ||
@@ -498,7 +498,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
uiButSetFlag(but, UI_BUT_DISABLED);
}
}
if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
if (id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
@@ -506,6 +506,195 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
}
}
if (flag & UI_ID_ADD_NEW) {
int w = id ? UI_UNIT_X : (flag & UI_ID_OPEN) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
/* i18n markup, does nothing! */
BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_DEFAULT,
BLF_I18NCONTEXT_ID_SCENE,
BLF_I18NCONTEXT_ID_OBJECT,
BLF_I18NCONTEXT_ID_MESH,
BLF_I18NCONTEXT_ID_CURVE,
BLF_I18NCONTEXT_ID_METABALL,
BLF_I18NCONTEXT_ID_MATERIAL,
BLF_I18NCONTEXT_ID_TEXTURE,
BLF_I18NCONTEXT_ID_IMAGE,
BLF_I18NCONTEXT_ID_LATTICE,
BLF_I18NCONTEXT_ID_LAMP,
BLF_I18NCONTEXT_ID_CAMERA,
BLF_I18NCONTEXT_ID_WORLD,
BLF_I18NCONTEXT_ID_SCREEN,
BLF_I18NCONTEXT_ID_TEXT,
);
BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_ID_SPEAKER,
BLF_I18NCONTEXT_ID_SOUND,
BLF_I18NCONTEXT_ID_ARMATURE,
BLF_I18NCONTEXT_ID_ACTION,
BLF_I18NCONTEXT_ID_NODETREE,
BLF_I18NCONTEXT_ID_BRUSH,
BLF_I18NCONTEXT_ID_PARTICLESETTINGS,
BLF_I18NCONTEXT_ID_GPENCIL,
BLF_I18NCONTEXT_ID_FREESTYLELINESTYLE,
);
if (newop) {
but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN,
(id) ? "" : CTX_IFACE_(template_id_context(type), "New"), 0, 0, w, UI_UNIT_Y, NULL);
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
}
else {
but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(template_id_context(type), "New"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
}
if ((idfrom && idfrom->lib) || !editable)
uiButSetFlag(but, UI_BUT_DISABLED);
}
/* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
* Only for images, sound and fonts */
if (id && BKE_pack_check(id)) {
but = uiDefIconButO(block, BUT, "FILE_OT_unpack_item", WM_OP_INVOKE_REGION_WIN, ICON_PACKAGE, 0, 0,
UI_UNIT_X, UI_UNIT_Y, TIP_("Packed File, click to unpack"));
uiButGetOperatorPtrRNA(but);
RNA_string_set(but->opptr, "id_name", id->name + 2);
RNA_int_set(but->opptr, "id_type", GS(id->name));
}
else if (flag & UI_ID_OPEN) {
int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
if (openop) {
but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"),
0, 0, w, UI_UNIT_Y, NULL);
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
}
else {
but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y,
NULL, 0, 0, 0, 0, NULL);
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
}
if ((idfrom && idfrom->lib) || !editable)
uiButSetFlag(but, UI_BUT_DISABLED);
}
/* delete button */
/* don't use RNA_property_is_unlink here */
if (id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK) == 0) {
if (unlinkop) {
but = uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
/* so we can access the template from operators, font unlinking needs this */
uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
}
else {
but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
TIP_("Unlink datablock "
"(Shift + Click to set users to zero, data will then not be saved)"));
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
if (RNA_property_flag(template->prop) & PROP_NEVER_NULL)
uiButSetFlag(but, UI_BUT_DISABLED);
}
if ((idfrom && idfrom->lib) || !editable)
uiButSetFlag(but, UI_BUT_DISABLED);
}
if (idcode == ID_TE)
uiTemplateTextureShow(layout, C, &template->ptr, template->prop);
uiBlockEndAlign(block);
}
static void template_ID_compact(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag,
const char *newop, const char *UNUSED(openop), const char *unlinkop)
{
uiBut *but;
uiBlock *block;
uiLayout *row, *col;
PointerRNA idptr;
ID *id, *idfrom;
int editable = RNA_property_editable(&template->ptr, template->prop);
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
id = idptr.data;
idfrom = template->ptr.id.data;
block = uiLayoutGetBlock(layout);
uiBlockBeginAlign(block);
if (idptr.type)
type = idptr.type;
template->preview = true;
row = uiLayoutRow(layout, TRUE);
/* left part of the brush */
col = uiLayoutColumn(row, TRUE);
but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 2, UI_UNIT_Y * 2,
TIP_(template_id_browse_tip(type)));
if (type) {
but->icon = RNA_struct_ui_icon(type);
if (id) but->icon = ui_id_icon_get(C, id, true);
uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW);
}
if ((idfrom && idfrom->lib) || !editable)
uiButSetFlag(but, UI_BUT_DISABLED);
uiItemS(row);
/* right part */
col = uiLayoutColumn(row, TRUE);
/* first row: text button with name */
row = uiLayoutRow(col, TRUE);
if (id) {
char name[UI_MAX_NAME_STR];
const short user_alert = id->us <= 0;
//text_idbutton(id, name);
name[0] = '\0';
but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y,
&idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type));
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
/* second row */
row = uiLayoutRow(col, TRUE);
if (id->us > 1) {
char numstr[32];
BLI_snprintf(numstr, sizeof(numstr), "%d", id->us);
but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y,
NULL, 0, 0, 0, 0,
TIP_("Display number of users of this data (click to make a single-user copy)"));
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
if (/* test only */
(id_copy(id, NULL, true) == false) ||
(idfrom && idfrom->lib) ||
(editable == FALSE) ||
/* object in editmode - don't change data */
(idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT)))
{
uiButSetFlag(but, UI_BUT_DISABLED);
}
}
if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
if (id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
uiDefButR(block, TOG, 0, "F", 0, 0, 6 * UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
}
}
if (flag & UI_ID_ADD_NEW) {
int w = id ? UI_UNIT_X : (flag & UI_ID_OPEN) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
@@ -551,35 +740,6 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
if ((idfrom && idfrom->lib) || !editable)
uiButSetFlag(but, UI_BUT_DISABLED);
}
/* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
* Only for images, sound and fonts */
if (id && BKE_pack_check(id)) {
but = uiDefIconButO(block, BUT, "FILE_OT_unpack_item", WM_OP_INVOKE_REGION_WIN, ICON_PACKAGE, 0, 0,
UI_UNIT_X, UI_UNIT_Y, TIP_("Packed File, click to unpack"));
uiButGetOperatorPtrRNA(but);
RNA_string_set(but->opptr, "id_name", id->name + 2);
RNA_int_set(but->opptr, "id_type", GS(id->name));
}
else if (flag & UI_ID_OPEN) {
int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
if (openop) {
but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"),
0, 0, w, UI_UNIT_Y, NULL);
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
}
else {
but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y,
NULL, 0, 0, 0, 0, NULL);
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
}
if ((idfrom && idfrom->lib) || !editable)
uiButSetFlag(but, UI_BUT_DISABLED);
}
/* delete button */
/* don't use RNA_property_is_unlink here */
@@ -610,7 +770,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
}
static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols)
const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols, int compact)
{
TemplateID *template;
PropertyRNA *prop;
@@ -644,7 +804,13 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const
*/
if (template->idlb) {
uiLayoutRow(layout, TRUE);
template_ID(C, layout, template, type, idcode, flag, newop, openop, unlinkop);
if (compact) {
template_ID_compact(C, layout, template, type, idcode, flag, newop, openop, unlinkop);
}
else {
template_ID(C, layout, template, type, idcode, flag, newop, openop, unlinkop);
}
}
MEM_freeN(template);
@@ -654,22 +820,30 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *pr
const char *openop, const char *unlinkop)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0);
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0, FALSE);
}
void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
const char *openop, const char *unlinkop)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0);
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0, FALSE);
}
void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
const char *openop, const char *unlinkop, int rows, int cols)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols);
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols, FALSE);
}
void uiTemplateIDPreviewCompact(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop,
const char *openop, const char *unlinkop, int rows, int cols)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop,
UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols, TRUE);
}
/************************ ID Chooser Template ***************************/
/* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use

View File

@@ -33,7 +33,6 @@
#include <string.h>
#include <assert.h>
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
@@ -54,6 +53,8 @@
#include "BLF_api.h"
#include "WM_types.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -1134,6 +1135,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
{
//int transopts; // UNUSED
char *cpoin = NULL;
unsigned char button_shortcut_color[4];
/* for underline drawing */
float font_xofs, font_yofs;
@@ -1213,7 +1215,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
#endif
/* cut string in 2 parts - only for menu entries */
if ((but->block->flag & UI_BLOCK_LOOP)) {
if ((but->block->flag & UI_BLOCK_SHORTCUTS)) {
if (ELEM3(but->type, NUM, TEX, NUMSLI) == 0) {
cpoin = strchr(but->drawstr, '|');
if (cpoin) *cpoin = 0;
@@ -1256,10 +1258,19 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
}
/* part text right aligned */
if (cpoin) {
/* part text right aligned
* only draw if there's enough space */
if (but->flag2 & UI_BUT2_EXTRA_TEXT && cpoin &&
(BLI_rcti_size_x(rect) - BLF_width(fstyle->uifont_id, but->str)) >= 5) {
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax -= ui_but_draw_menu_icon(but) ? UI_DPI_ICON_SIZE : 0.25f * U.widget_unit;
/* If this is not a menu, and therefore a normal button, then change the alpha of the shortcut */
if (!(but->block->flag & UI_BLOCK_LOOP)) {
memcpy(button_shortcut_color, wcol->text, 4);
button_shortcut_color[3] /= 2;
glColor4ubv(button_shortcut_color);
}
uiStyleFontDraw(fstyle, rect, cpoin + 1);
*cpoin = '|';
}
@@ -3202,6 +3213,21 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
ThemeUI *tui = &btheme->tui;
uiFontStyle *fstyle = &style->widget;
uiWidgetType *wt = NULL;
/* in case we have an automatic icon, let's set it here */
if (but->icon && but->icon == ICON_AUTOMATIC) {
int icon = ICON_NONE;
if (but->optype) {
if (but->optype->icon && but->opptr) {
icon = but->optype->icon(C, but->opptr);
}
else if (but->optype->default_icon) {
icon = but->optype->default_icon;
}
}
but->icon = icon;
}
/* handle menus separately */
if (but->dt == UI_EMBOSSP) {

View File

@@ -40,6 +40,7 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -49,6 +50,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_texture.h"
#include "BKE_context.h"
#include "BIF_gl.h"
@@ -1358,6 +1360,29 @@ void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3]
}
}
int UI_data_mode_icon(const bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
if (obedit) {
return ICON_EDITMODE_HLT;
}
else {
Object *ob = CTX_data_active_object(C);
if (ob) {
if (ob->mode & OB_MODE_POSE) return ICON_POSE_HLT;
else if (ob->mode & OB_MODE_SCULPT) return ICON_SCULPTMODE_HLT;
else if (ob->mode & OB_MODE_WEIGHT_PAINT) return ICON_WPAINT_HLT;
else if (ob->mode & OB_MODE_VERTEX_PAINT) return ICON_VPAINT_HLT;
else if (ob->mode & OB_MODE_TEXTURE_PAINT) return ICON_TPAINT_HLT;
else if (ob->mode & OB_MODE_PARTICLE_EDIT) return ICON_PARTICLEMODE;
}
}
return ICON_OBJECT_DATAMODE;
}
/* ************************************************************* */
/* patching UserDef struct and Themes */

View File

@@ -33,6 +33,7 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_math.h"
#include "BLI_alloca.h"
@@ -698,7 +699,7 @@ static void free_undo(void *me_v)
}
/* and this is all the undo system needs to know */
void undo_push_mesh(bContext *C, const char *name)
void undo_push_mesh(bContext *C, const char *name, wmOperator *op)
{
/* em->ob gets out of date and crashes on mesh undo,
* this is an easy way to ensure its OK
@@ -707,7 +708,7 @@ void undo_push_mesh(bContext *C, const char *name)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
em->ob = obedit;
undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL, op);
}
/**

View File

@@ -576,9 +576,9 @@ static void *get_data(bContext *C)
}
/* this is undo system for MetaBalls */
void undo_push_mball(bContext *C, const char *name)
void undo_push_mball(bContext *C, const char *name, wmOperator *op)
{
undo_editmode_push(C, name, get_data, free_undoMball, undoMball_to_editMball, editMball_to_undoMball, NULL);
undo_editmode_push(C, name, get_data, free_undoMball, undoMball_to_editMball, editMball_to_undoMball, NULL, op);
}
/* matrix is 4x4 */

View File

@@ -46,6 +46,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -886,8 +887,8 @@ static void *get_editlatt(bContext *C)
}
/* and this is all the undo system needs to know */
void undo_push_lattice(bContext *C, const char *name)
void undo_push_lattice(bContext *C, const char *name, wmOperator *op)
{
undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt);
undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt, op);
}

View File

@@ -71,6 +71,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
#include "UI_resources.h"
#include "RE_pipeline.h"
#include "RE_engine.h"
@@ -719,6 +721,8 @@ void RENDER_OT_render(wmOperatorType *ot)
ot->invoke = screen_render_invoke;
ot->modal = screen_render_modal;
ot->exec = screen_render_exec;
ot->default_icon = OPICON_RENDER;
/*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */

View File

@@ -45,6 +45,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_screen.h"
#include "BKE_idprop.h"
#include "RNA_access.h"
#include "RNA_types.h"
@@ -950,7 +951,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
/* clear state flags first */
ar->flag &= ~RGN_FLAG_TOO_SMALL;
/* user errors */
if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT)
if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT && alignment != RGN_ALIGN_FLOAT)
alignment = RGN_ALIGN_NONE;
/* prefsize, for header we stick to exception (prevent dpi rounding error) */
@@ -959,24 +960,19 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
if (ar->regiontype == RGN_TYPE_HEADER) {
prefsizey = ED_area_headersize();
}
else if (ar->regiontype == RGN_TYPE_MENU_BAR) {
prefsizey = ED_area_headersize() * 1.5f;
}
else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2);
}
else {
prefsizey = UI_DPI_FAC * (ar->sizey > 1 ? ar->sizey + 0.5f : ar->type->prefsizey);
}
if (ar->flag & RGN_FLAG_HIDDEN) {
/* hidden is user flag */
}
else if (alignment == RGN_ALIGN_FLOAT) {
/* XXX floating area region, not handled yet here */
}
else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) {
/* remainder is too small for any usage */
ar->flag |= RGN_FLAG_TOO_SMALL;
}
else if (alignment == RGN_ALIGN_NONE) {
/* typically last region */
ar->winrct = *remainder;
@@ -984,6 +980,18 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
}
else if (alignment == RGN_ALIGN_TOP || alignment == RGN_ALIGN_BOTTOM) {
if (ar->regiontype == RGN_TYPE_TOOL_PROPS) {
Panel *pa = NULL;
for (pa = ar->panels.first; pa; pa = pa->next) {
// TODO: is there a better way to test for the identity of a panel type?
if (pa->type && strcmp(pa->type->idname, "VIEW3D_PT_last_operator") == 0)
break;
}
prefsizey = ((pa && !uiPanelClosed(pa)) ? pa->sizey : 0) + 26;
}
if (rct_fits(remainder, 'v', prefsizey) < 0) {
ar->flag |= RGN_FLAG_TOO_SMALL;
}
@@ -1003,6 +1011,18 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
ar->winrct.ymax = ar->winrct.ymin + prefsizey - 1;
remainder->ymin = ar->winrct.ymax + 1;
}
/* Make sure we don't hide the tool props region when the toolbar is hidden.
* This only works nicely with overlapping regions. */
if (ar->overlap && ar->regiontype == RGN_TYPE_TOOL_PROPS && ar->prev && (ar->prev->flag & RGN_FLAG_HIDDEN || ar->prev->flag & RGN_FLAG_TOO_SMALL)) {
Panel *pa = NULL;
for (pa = ar->panels.first; pa; pa = pa->next) {
if (pa->type && strcmp(pa->type->idname, "VIEW3D_PT_last_operator") == 0)
break;
}
if (pa && pa->flag & PNL_PINNED)
ar->winrct.xmax = prefsizex - 1;
}
}
}
else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
@@ -1177,7 +1197,7 @@ static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
/* used for area initialize below */
static void region_subwindow(wmWindow *win, ARegion *ar)
{
{
if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
if (ar->swinid)
wm_subwindow_close(win, ar->swinid);
@@ -1241,6 +1261,30 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
}
}
static void reset_custom_paneltypes(ARegion *ar)
{
ARegionType *art = ar->type;
PanelType *pt, *pt_rem;
Panel *pa;
/* PanelTypes should only be created at runtime or from Panels loaded from a blend */
for (pt = art->paneltypes.first; pt;) {
pt_rem = pt;
pt = pt_rem->next;
if (pt_rem->flag & PNL_CUSTOM_PANELTYPE) {
BLI_remlink(&art->paneltypes, pt_rem);
MEM_freeN(pt_rem);
}
}
/* The ar->type needs to be set to NULL in case we're not loading another file. */
for (pa = ar->panels.first; pa; pa = pa->next) {
if (pa->flag & PNL_CUSTOM_PANEL) {
pa->type = NULL;
}
}
}
/* called in screen_refresh, or screens_init, also area size changes */
void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
@@ -1256,8 +1300,11 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
sa->type = BKE_spacetype_from_id(sa->spacetype);
}
for (ar = sa->regionbase.first; ar; ar = ar->next)
for (ar = sa->regionbase.first; ar; ar = ar->next) {
ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype);
reset_custom_paneltypes(ar);
}
/* area sizes */
area_calc_totrct(sa, WM_window_pixels_x(win), WM_window_pixels_y(win));
@@ -1552,7 +1599,7 @@ int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco)
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
uiBlockSetEmboss(block, UI_EMBOSS);
return xco + U.widget_unit;
}
@@ -1621,6 +1668,11 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
/* draw panel */
if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
/* If there's a panel for this paneltype, and that panel is hidden, then do not draw it. */
panel = uiGetExistingPanel(ar, pt);
if (panel && panel->hidden)
continue;
block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
panel = uiBeginPanel(sa, ar, block, pt, &open);
@@ -1803,6 +1855,132 @@ void ED_region_header_init(ARegion *ar)
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
}
void static menubar_fold_divider(bContext *UNUSED(C), void *arg1, void *UNUSED(arg2))
{
OperatorListItem *oli = arg1;
oli->flag ^= OLI_DIVIDER_CLOSED;
}
void static menubar_draw_oli(const bContext *C, uiLayout *row, OperatorListItem *oli, int *draw_buttons)
{
uiBlock *block = uiLayoutGetBlock(row);
uiBut *but;
if (oli && row) {
if (oli->flag & OLI_DIVIDER) {
uiItemS(row);
uiBlockSetEmboss(block, UI_EMBOSSN);
but = uiDefIconBut(block, BUT, -1, (oli->flag & OLI_DIVIDER_CLOSED ? ICON_DISCLOSURE_TRI_RIGHT : ICON_DISCLOSURE_TRI_DOWN), 0, 0, UI_UNIT_X/3, UI_UNIT_Y, NULL, 0, 0, 0, 0, "When checked shows the buttons to the right");
/* N.B. func_arg1 is also used for the drag system */
uiButSetFunc(but, menubar_fold_divider, oli, NULL);
/* Hack to make the button system not catch drag events for non-operator buttons */
uiButSetDragOp(but, (wmOperatorType*)oli);
uiBlockSetEmboss(block, UI_EMBOSS);
uiItemS(row);
*draw_buttons = !(oli->flag & OLI_DIVIDER_CLOSED);
}
else {
if (*draw_buttons) {
wmOperatorType *ot = WM_operatortype_find(oli->optype_idname, TRUE);
int icon = ICON_NONE;
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
ptr.data = oli->properties;
icon = ot->icon ? ot->icon(C, &ptr) : ot->default_icon;
if (icon != ICON_NONE)
uiItemFullO_ptr(row, ot, "", ICON_AUTOMATIC, IDP_CopyProperty(oli->properties), oli->opcontext, 0);
else
uiItemFullO_ptr(row, ot, ot->name, ICON_NONE, IDP_CopyProperty(oli->properties), oli->opcontext, UI_ITEM_O_SINGLE_UNIT);
}
}
}
}
void ED_region_menubar(const bContext *C, ARegion *ar)
{
uiStyle *style = UI_GetStyleDraw();
uiBlock *block;
uiLayout *layout, *row;
int maxco, xco, yco;
int headery = ED_area_headersize() * 1.5f;
OperatorListItem *oli_iter;
OperatorListItem *oli_dragged = uiRegionDraggedOperatorListItem(ar);
int newindex = uiRegionDraggedNewIndex(ar);
int i = 0;
int draw_buttons = 1;
/* clear */
UI_ThemeClearColor(TH_BACK);
glClear(GL_COLOR_BUFFER_BIT);
/* set view2d view matrix for scrolling (without scrollers) */
UI_view2d_view_ortho(&ar->v2d);
/* add all custom buttons to lower bar */
xco = maxco = 0.4f * UI_UNIT_X;
yco = headery - floor(0.2f * UI_UNIT_Y);
block = uiBeginBlock(C, ar, "menubar icons", UI_EMBOSS);
layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, UI_UNIT_Y, 1, style);
row = uiLayoutRow(layout, TRUE);
uiLayoutSetScaleX(row, 1.5f);
uiLayoutSetScaleY(row, 1.5f);
for (oli_iter = ar->operators.first; oli_iter; oli_iter = oli_iter->next) {
if (oli_dragged) {
// draw the new order of buttons
if (i == newindex) {
int cur_index = BLI_findindex(&ar->operators, oli_dragged);
// draw it before or after the button that currently has the new index
if (newindex == cur_index) {
menubar_draw_oli(C, row, oli_iter, &draw_buttons);
}
else if (newindex < cur_index) {
menubar_draw_oli(C, row, oli_dragged, &draw_buttons);
if (strcmp(oli_iter->context, CTX_data_mode_string(C)) == 0)
menubar_draw_oli(C, row, oli_iter, &draw_buttons);
}
else if (newindex > cur_index) {
if (strcmp(oli_iter->context, CTX_data_mode_string(C)) == 0)
menubar_draw_oli(C, row, oli_iter, &draw_buttons);
menubar_draw_oli(C, row, oli_dragged, &draw_buttons);
}
}
// otherwise just draw normally
else if (oli_iter != oli_dragged)
if (strcmp(oli_iter->context, CTX_data_mode_string(C)) == 0)
menubar_draw_oli(C, row, oli_iter, &draw_buttons);
}
else
if (strcmp(oli_iter->context, CTX_data_mode_string(C)) == 0)
menubar_draw_oli(C, row, oli_iter, &draw_buttons);
i++;
}
xco = uiLayoutGetWidth(row);
if (xco > maxco) maxco = xco;
uiBlockLayoutResolve(block, &xco, &yco);
uiEndBlock(C, block);
uiDrawBlock(C, block);
/* always as last */
UI_view2d_totRect_set(&ar->v2d, maxco + UI_UNIT_X + 80, headery);
/* restore view matrix? */
UI_view2d_view_restore(C);
}
void ED_region_menubar_init(ARegion *ar)
{
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
}
/* UI_UNIT_Y is defined as U variable now, depending dpi */
int ED_area_headersize(void)
{

View File

@@ -394,12 +394,26 @@ void fdrawXORcirc(float xofs, float yofs, float rad)
glPushMatrix();
glTranslatef(xofs, yofs, 0.0);
glutil_draw_lined_arc(0.0, M_PI * 2.0, rad, 20);
glutil_draw_filled_arc(0.0, M_PI * 2.0, rad, 20);
glPopMatrix();
set_inverted_drawing(0);
}
void fdrawellipses(float xofs, float yofs, float rad)
{
glEnable(GL_POINT_SMOOTH);
glPointSize(rad);
glPushMatrix();
glTranslatef(xofs + rad * 4.f, yofs, 0.0);
glBegin(GL_POINTS);
glVertex2f(0.f, 0.f);
glVertex2f(rad * 2.f, 0.f);
glVertex2f(rad * 4.f, 0.f);
glEnd();
glPopMatrix();
}
void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments)
{
int i;

View File

@@ -2607,9 +2607,13 @@ static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot)
static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op))
{
wmOperator *lastop = CTX_wm_manager(C)->operators.last;
if (lastop)
WM_operator_repeat(C, lastop);
wmOperator *newop;
if (lastop)
{
newop = WM_operator_copy(C, lastop, false);
WM_operator_call(C, newop);
}
return OPERATOR_CANCELLED;
}
@@ -2654,14 +2658,17 @@ static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
static int repeat_history_exec(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmOperator *newop;
op = BLI_findlink(&wm->operators, RNA_int_get(op->ptr, "index"));
if (op) {
/* let's put it as last operator in list */
BLI_remlink(&wm->operators, op);
BLI_addtail(&wm->operators, op);
WM_operator_repeat(C, op);
/* Let's copy the operator and add it to the end of the list.
* Conceptually we haven't changed the order of the operators, but
* we have applied the operator twice. The two applications should have
* two different wmOperator instances. This also makes it consistent with
* the link between the undobase lists. */
newop = WM_operator_copy(C, op, false);
WM_operator_call(C, newop);
}
return OPERATOR_FINISHED;
@@ -2688,7 +2695,7 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot)
static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
wmOperator *lastop = WM_operator_last_redo(C);
if (lastop)
WM_operator_redo_popup(C, lastop);
@@ -3848,7 +3855,7 @@ static int open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
return 0;
}
static void open_file_drop_copy(wmDrag *drag, wmDropBox *drop)
static void open_file_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", drag->path);

View File

@@ -118,18 +118,15 @@ void CLIP_OT_properties(wmOperatorType *ot)
static ARegion *clip_has_tools_region(ScrArea *sa)
{
ARegion *ar, *artool = NULL, *arprops = NULL, *arhead;
ARegion *ar, *artool = NULL, *arhead;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_TOOLS)
artool = ar;
if (ar->regiontype == RGN_TYPE_TOOL_PROPS)
arprops = ar;
}
/* tool region hide/unhide also hides props */
if (arprops && artool)
if (artool)
return artool;
if (artool == NULL) {
@@ -149,15 +146,6 @@ static ARegion *clip_has_tools_region(ScrArea *sa)
artool->flag = RGN_FLAG_HIDDEN;
}
if (arprops == NULL) {
/* add extra subdivided region for tool properties */
arprops = MEM_callocN(sizeof(ARegion), "tool props for clip");
BLI_insertlinkafter(&sa->regionbase, artool, arprops);
arprops->regiontype = RGN_TYPE_TOOL_PROPS;
arprops->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
}
return artool;
}
@@ -193,7 +181,7 @@ void CLIP_OT_tools(wmOperatorType *ot)
static void clip_panel_operator_redo_buts(const bContext *C, Panel *pa, wmOperator *op)
{
uiLayoutOperatorButs(C, pa->layout, op, NULL, 'V', 0);
uiLayoutOperatorButs(C, pa->layout, op, NULL, 'H', 0);
}
static void clip_panel_operator_redo_header(const bContext *C, Panel *pa)

View File

@@ -267,13 +267,15 @@ static SpaceLink *clip_new(const bContext *C)
ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_LEFT;
#if 0
/* tool properties */
ar = MEM_callocN(sizeof(ARegion), "tool properties for clip");
BLI_addtail(&sc->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
#endif
/* properties view */
ar = MEM_callocN(sizeof(ARegion), "properties for clip");
@@ -825,7 +827,7 @@ static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUS
return FALSE;
}
static void clip_drop_copy(wmDrag *drag, wmDropBox *drop)
static void clip_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
PointerRNA itemptr;
char dir[FILE_MAX], file[FILE_MAX];
@@ -855,7 +857,9 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
SpaceClip *sc = (SpaceClip *)sa->spacedata.first;
ARegion *ar_main = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
ARegion *ar_tools = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
#if 0
ARegion *ar_tool_props = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS);
#endif
ARegion *ar_preview = ED_clip_has_preview_region(C, sa);
ARegion *ar_properties = ED_clip_has_properties_region(sa);
ARegion *ar_channels = ED_clip_has_channels_region(sa);
@@ -967,6 +971,7 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
}
}
#if 0
if (tool_props_visible) {
if (ar_tool_props && (ar_tool_props->flag & RGN_FLAG_HIDDEN)) {
ar_tool_props->flag &= ~RGN_FLAG_HIDDEN;
@@ -990,6 +995,7 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
view_changed = TRUE;
}
}
#endif
if (preview_visible) {
if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
@@ -1529,6 +1535,7 @@ void ED_spacetype_clip(void)
BLI_addhead(&st->regiontypes, art);
#if 0
/* tool properties */
art = MEM_callocN(sizeof(ARegionType), "spacetype clip tool properties region");
art->regionid = RGN_TYPE_TOOL_PROPS;
@@ -1541,6 +1548,7 @@ void ED_spacetype_clip(void)
ED_clip_tool_props_register(art);
BLI_addhead(&st->regiontypes, art);
#endif
/* regions: header */
art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");

View File

@@ -171,7 +171,7 @@ static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED
return 0;
}
static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
static void id_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
char *text;
ID *id = drag->poin;
@@ -190,7 +190,7 @@ static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUS
return 0;
}
static void path_drop_copy(wmDrag *drag, wmDropBox *drop)
static void path_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
char pathname[FILE_MAX + 2];
BLI_snprintf(pathname, sizeof(pathname), "\"%s\"", drag->path);

View File

@@ -349,7 +349,7 @@ static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNU
return 0;
}
static void image_drop_copy(wmDrag *drag, wmDropBox *drop)
static void image_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", drag->path);

View File

@@ -666,7 +666,7 @@ static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
static void node_id_path_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;

View File

@@ -129,7 +129,7 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
return 0;
}
static void outliner_parent_drop_copy(wmDrag *drag, wmDropBox *drop)
static void outliner_parent_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
@@ -171,7 +171,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
return 0;
}
static void outliner_parent_clear_copy(wmDrag *drag, wmDropBox *drop)
static void outliner_parent_clear_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
RNA_string_set(drop->ptr, "dragged_obj", id->name + 2);
@@ -200,7 +200,7 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
return 0;
}
static void outliner_scene_drop_copy(wmDrag *drag, wmDropBox *drop)
static void outliner_scene_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
@@ -225,7 +225,7 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
return 0;
}
static void outliner_material_drop_copy(wmDrag *drag, wmDropBox *drop)
static void outliner_material_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;

View File

@@ -414,7 +414,7 @@ static int sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
return 0;
}
static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
static void sequencer_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
if (RNA_struct_find_property(drop->ptr, "filepath"))

View File

@@ -468,7 +468,7 @@ static int text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUS
return 0;
}
static void text_drop_copy(wmDrag *drag, wmDropBox *drop)
static void text_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", drag->path);

View File

@@ -42,10 +42,13 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_icons.h"
#include "BKE_object.h"
#include "BKE_screen.h"
#include "BKE_idprop.h"
#include "ED_render.h"
#include "ED_space_api.h"
@@ -56,6 +59,7 @@
#include "GPU_material.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -65,6 +69,7 @@
#include "RNA_access.h"
#include "UI_resources.h"
#include "UI_interface.h"
#include "view3d_intern.h" /* own include */
@@ -94,48 +99,37 @@ ARegion *view3d_has_buttons_region(ScrArea *sa)
return arnew;
}
ARegion *view3d_has_tools_region(ScrArea *sa)
{
ARegion *ar, *artool = NULL, *arprops = NULL, *arhead;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_TOOLS)
artool = ar;
if (ar->regiontype == RGN_TYPE_TOOL_PROPS)
arprops = ar;
}
/* tool region hide/unhide also hides props */
if (arprops && artool) return artool;
if (artool == NULL) {
/* add subdiv level; after header */
for (arhead = sa->regionbase.first; arhead; arhead = arhead->next)
if (arhead->regiontype == RGN_TYPE_HEADER)
break;
/* is error! */
if (arhead == NULL) return NULL;
artool = MEM_callocN(sizeof(ARegion), "tools for view3d");
BLI_insertlinkafter(&sa->regionbase, arhead, artool);
artool->regiontype = RGN_TYPE_TOOLS;
artool->alignment = RGN_ALIGN_LEFT;
artool->flag = RGN_FLAG_HIDDEN;
}
if (arprops == NULL) {
/* add extra subdivided region for tool properties */
arprops = MEM_callocN(sizeof(ARegion), "tool props for view3d");
BLI_insertlinkafter(&sa->regionbase, artool, arprops);
arprops->regiontype = RGN_TYPE_TOOL_PROPS;
arprops->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
}
return artool;
}
//ARegion *view3d_has_tools_region(ScrArea *sa)
//{
// ARegion *ar, *artool = NULL, *arhead;
//
// for (ar = sa->regionbase.first; ar; ar = ar->next) {
// if (ar->regiontype == RGN_TYPE_TOOLS)
// artool = ar;
// }
//
// /* tool region hide/unhide also hides props */
// if (artool) return artool;
//
// if (artool == NULL) {
// /* add subdiv level; after header */
// for (arhead = sa->regionbase.first; arhead; arhead = arhead->next)
// if (arhead->regiontype == RGN_TYPE_HEADER)
// break;
//
// /* is error! */
// if (arhead == NULL) return NULL;
//
// artool = MEM_callocN(sizeof(ARegion), "tools for view3d");
//
// BLI_insertlinkafter(&sa->regionbase, arhead, artool);
// artool->regiontype = RGN_TYPE_TOOLS;
// artool->alignment = RGN_ALIGN_LEFT;
// artool->flag = RGN_FLAG_HIDDEN;
// }
//
// return artool;
//}
/* ****************************************************** */
@@ -304,30 +298,35 @@ static SpaceLink *view3d_new(const bContext *C)
ar->regiontype = RGN_TYPE_HEADER;
ar->alignment = RGN_ALIGN_BOTTOM;
/* operators menubar */
ar = MEM_callocN(sizeof(ARegion), "tool operators menu bar for view3d");
BLI_addtail(&v3d->regionbase, ar);
ar->regiontype = RGN_TYPE_MENU_BAR;
ar->alignment = RGN_ALIGN_TOP;
/* tool shelf */
ar = MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
BLI_addtail(&v3d->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_LEFT;
ar->flag = RGN_FLAG_HIDDEN;
/* tool properties */
/* tool props, floating and therefore last! */
ar = MEM_callocN(sizeof(ARegion), "tool properties for view3d");
BLI_addtail(&v3d->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
ar->flag = RGN_FLAG_HIDDEN;
ar->alignment = RGN_SPLIT_PREV | RGN_ALIGN_BOTTOM;
/* buttons/list view */
/* object properties sidebar right */
ar = MEM_callocN(sizeof(ARegion), "buttons for view3d");
BLI_addtail(&v3d->regionbase, ar);
ar->regiontype = RGN_TYPE_UI;
ar->alignment = RGN_ALIGN_RIGHT;
ar->flag = RGN_FLAG_HIDDEN;
/* main area */
ar = MEM_callocN(sizeof(ARegion), "main area for view3d");
@@ -574,14 +573,14 @@ static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
return 0;
}
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_ob_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_group_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
@@ -589,14 +588,14 @@ static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_id_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_id_path_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
@@ -606,6 +605,87 @@ static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "filepath", drag->path);
}
static void view3d_menubar_drop_copy(const bContext *UNUSED(C), const wmEvent *UNUSED(event), wmDrag *drag, wmDropBox *drop)
{
wmOperatorType *ot = (wmOperatorType*)drag->poin;
/* replace the drop ptr with the passed ptr so it can be copied by the drag operator */
if (drag->ptr && drag->ptr->data) {
WM_operator_properties_free(drop->ptr);
drop->ptr->data = IDP_CopyProperty(drag->ptr->data);
}
/* temporarily set the properties for the drag operator in the copied ptr
* this is effectively piggy backing on the properties for the OperatorListItem */
RNA_string_set(drop->ptr, "COPY_idname", ot->idname);
RNA_int_set(drop->ptr, "COPY_opcontext", drag->opcontext);
}
static int view3d_menubar_drop_poll(bContext *C, wmDrag *drag, const wmEvent *UNUSED(event))
{
wmOperatorType *ot = (wmOperatorType*)drag->poin;
ARegion *ar = CTX_wm_region(C);
if (drag->type == WM_DRAG_OP && ot && ar && ar->regiontype == RGN_TYPE_MENU_BAR) {
/* check to see if an oli with the same properties is already present */
if (drag->ptr)
return !uiOperatorListItemPresent(&ar->operators, ot->idname, drag->ptr->data, CTX_data_mode_string(C));
}
return 0;
}
static Panel *over_panel(const bContext *C, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C); // This handler is only registered in the TOOLBAR region
const char *context = CTX_data_mode_string(C);
Panel *pa = NULL;
for (pa = ar->panels.first; pa; pa = pa->next) {
if (pa->flag & PNL_CUSTOM_PANEL && !uiPanelClosed(pa) && strcmp(context, pa->context) == 0) {
// adjust ys for region
int adjy = event->y - (ar->winrct.ymax - ar->sizey);
int paminy = ar->sizey + pa->ofsy;
int pamaxy = paminy + pa->sizey;
int overp = adjy < pamaxy && adjy > paminy;
if (overp)
return pa;
}
}
return NULL;
}
static void view3d_toolbar_drop_copy(const bContext *C, const wmEvent *event, wmDrag *drag, wmDropBox *drop)
{
wmOperatorType *ot = (wmOperatorType*)drag->poin;
Panel *pa = over_panel(C, event);
/* replace the drop ptr with the passed ptr so it can be copied by the drag operator */
if (drag->ptr && drag->ptr->data) {
WM_operator_properties_free(drop->ptr);
drop->ptr->data = IDP_CopyProperty(drag->ptr->data);
}
/* temporarily set the properties for the drag operator in the copied ptr
* this is effectively piggy backing on the properties for the OperatorListItem */
RNA_string_set(drop->ptr, "COPY_idname", ot->idname);
RNA_int_set(drop->ptr, "COPY_opcontext", drag->opcontext);
RNA_string_set(drop->ptr, "COPY_paneltypeid", pa->type ? pa->type->idname : "");
}
static int view3d_toolbar_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
wmOperatorType *ot = (wmOperatorType*)drag->poin;
Panel *pa = NULL;
OperatorListItem *present_p = NULL;
if (drag->type == WM_DRAG_OP && ot) {
pa = over_panel(C, event);
if (pa != NULL && drag->ptr && drag->ptr->data)
/* check to see if an oli with the same properties is already present */
present_p = uiOperatorListItemPresent(&pa->operators, ot->idname, drag->ptr->data, CTX_data_mode_string(C));
}
return pa != NULL && present_p == NULL;
}
/* region dropbox definition */
static void view3d_dropboxes(void)
@@ -618,6 +698,16 @@ static void view3d_dropboxes(void)
WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_MENU_BAR);
WM_dropbox_add(lb, "WM_OT_menubar_add_dragged_operator", view3d_menubar_drop_poll, view3d_menubar_drop_copy);
lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_TOOLS);
WM_dropbox_add(lb, "WM_OT_add_to_custom_panel", view3d_toolbar_drop_poll, view3d_toolbar_drop_copy);
}
@@ -713,7 +803,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
{
Scene *scene = sc->scene;
View3D *v3d = sa->spacedata.first;
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
@@ -1053,12 +1143,16 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
/* add handlers, stuff you only do once or on area/region changes */
static void view3d_tools_area_init(wmWindowManager *wm, ARegion *ar)
{
ListBase *lb;
wmKeyMap *keymap;
ED_region_panels_init(wm, ar);
keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_TOOLS);
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
@@ -1066,6 +1160,79 @@ static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1);
}
static void view3d_menubar_area_init(wmWindowManager *wm, ARegion *ar)
{
ListBase *lb;
wmKeyMap *keymap;
ED_region_menubar_init(ar);
keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_MENU_BAR);
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
static void view3d_menubar_area_draw(const bContext *C, ARegion *ar)
{
ED_region_menubar(C, ar);
}
static void view3d_menubar_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch (wmn->category) {
case NC_SCENE:
if (wmn->data == ND_MODE)
ED_region_tag_redraw(ar);
break;
}
}
static int view3d_props_sum_panel_heights(ARegion *ar)
{
Panel *pa;
int sum = 0;
for (pa = ar->panels.first; pa; pa = pa->next) {
sum += pa->sizey;
}
return sum;
}
static void view3d_props_area_draw(const bContext *C, ARegion *ar)
{
/* If in laying out and redrawing the panels this area contains we find that the
* panels have changed in height we'll need to redraw the area so that its height
* is automatically adapted. If */
int total_panel_height = view3d_props_sum_panel_heights(ar);
/* firstly, draw a clear divider */
ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1);
glEnable(GL_BLEND);
glColor4ub(0, 0, 0, 200);
fdrawline(0, BLI_rcti_size_y(&ar->winrct)+1, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)+1);
glColor4ub(255, 255, 255, 30);
fdrawline(0, BLI_rcti_size_y(&ar->winrct), BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
if (total_panel_height != view3d_props_sum_panel_heights(ar)) {
ED_area_tag_redraw(CTX_wm_area(C));
CTX_wm_screen(C)->do_refresh = TRUE;
}
}
static void view3d_props_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
ED_region_panels_init(wm, ar);
keymap = WM_keymap_find(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
static void view3d_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
{
/* context changes */
@@ -1077,6 +1244,8 @@ static void view3d_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
case NC_SCENE:
if (wmn->data == ND_MODE)
ED_region_tag_redraw(ar);
if (wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
break;
case NC_SPACE:
if (wmn->data == ND_SPACE_VIEW3D)
@@ -1318,24 +1487,31 @@ void ED_spacetype_view3d(void)
art->draw = view3d_tools_area_draw;
BLI_addhead(&st->regiontypes, art);
#if 0
/* unfinished still */
view3d_toolshelf_register(art);
#endif
view3d_toolbar_header_register(art);
view3d_grease_register(art);
/* regions: tool properties */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool properties region");
art->regionid = RGN_TYPE_TOOL_PROPS;
art->prefsizex = 0;
art->prefsizey = 120;
art->prefsizex = 160; /* XXX */
art->prefsizey = 50; /* XXX */
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = view3d_props_area_listener;
art->init = view3d_tools_area_init;
art->draw = view3d_tools_area_draw;
art->init = view3d_props_area_init;
art->draw = view3d_props_area_draw;
BLI_addhead(&st->regiontypes, art);
view3d_tool_props_register(art);
/* regions: operators menu bar */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d operators menu bar region");
art->regionid = RGN_TYPE_MENU_BAR;
art->prefsizey = ED_area_headersize();
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
art->listener = view3d_menubar_area_listener;
art->init = view3d_menubar_area_init;
art->draw = view3d_menubar_area_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: header */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");

View File

@@ -1154,13 +1154,13 @@ void view3d_buttons_register(ARegionType *art)
pt->poll = view3d_panel_transform_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
strcpy(pt->idname, "VIEW3D_PT_gpencil");
strcpy(pt->label, N_("Grease Pencil")); /* XXX C panels are not available through RNA (bpy.types)! */
strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
BLI_addtail(&art->paneltypes, pt);
// pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
// strcpy(pt->idname, "VIEW3D_PT_gpencil");
// strcpy(pt->label, N_("Grease Pencil")); /* XXX C panels are not available through RNA (bpy.types)! */
// strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
// pt->draw_header = gpencil_panel_standard_header;
// pt->draw = gpencil_panel_standard;
// BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
strcpy(pt->idname, "VIEW3D_PT_vgroup");

View File

@@ -207,6 +207,8 @@ void view3d_buttons_register(struct ARegionType *art);
void VIEW3D_OT_toolshelf(struct wmOperatorType *ot);
void view3d_toolshelf_register(struct ARegionType *art);
void view3d_tool_props_register(struct ARegionType *art);
void view3d_grease_register(struct ARegionType *art);
void view3d_toolbar_header_register(struct ARegionType *art);
/* view3d_snap.c */
bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]);

View File

@@ -56,9 +56,11 @@
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
#include "ED_screen.h"
#include "ED_util.h"
#include "ED_gpencil.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -73,30 +75,30 @@ static void view3d_panel_operator_redo_buts(const bContext *C, Panel *pa, wmOper
uiLayoutOperatorButs(C, pa->layout, op, NULL, 'V', 0);
}
static void view3d_panel_operator_redo_header(const bContext *C, Panel *pa)
{
wmOperator *op = WM_operator_last_redo(C);
if (op)
BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
else
BLI_strncpy(pa->drawname, IFACE_("Operator"), sizeof(pa->drawname));
}
static void view3d_panel_operator_redo_operator(const bContext *C, Panel *pa, wmOperator *op)
{
if (op->type->flag & OPTYPE_MACRO) {
for (op = op->macro.first; op; op = op->next) {
uiItemL(pa->layout, RNA_struct_ui_name(op->type->srna), ICON_NONE);
// uiItemL(pa->layout, RNA_struct_ui_name(op->type->srna), ICON_NONE);
view3d_panel_operator_redo_operator(C, pa, op);
}
}
else {
uiItemL(pa->layout, RNA_struct_ui_name(op->type->srna), ICON_NONE);
view3d_panel_operator_redo_buts(C, pa, op);
}
}
/* TODO de-duplicate redo panel functions - campbell */
static void view3d_panel_operator_redo_header(const bContext *UNUSED(C), Panel *pa)
{
uiLayout *layout = pa->layout;
uiBlockSetEmboss(uiLayoutGetBlock(layout), UI_EMBOSSN);
uiDefIconButBitS(uiLayoutGetBlock(layout), TOG, PNL_PINNED, 0, pa->flag & PNL_PINNED ? ICON_PINNED : ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &pa->flag, 0.f, 0.f, 0.f, 0.f, "When this panel is pinned it is not hidden when the toolbar is hidden");
uiBlockSetEmboss(uiLayoutGetBlock(layout), UI_EMBOSS);
}
static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
{
wmOperator *op = WM_operator_last_redo(C);
@@ -129,6 +131,150 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
CTX_wm_region_set((bContext *)C, ar);
}
static uiBlock *active_panel_menu_popup_create_block(bContext *C, ARegion *cur_ar, void *arg_ar);
static void active_panel_menu_popup_cb(bContext *C, void *UNUSED(arg_block), int UNUSED(event))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
// uiBlock *block = (uiBlock*)arg_block;
/* This results in a crash that has something to do with recursion
in the event handling system. I'm not quite sure it is possible
to refresh popup blocks.
*/
// uiPupBlockClose(C, block);
// uiPupBlock(C, active_panel_menu_popup_create_block, ar);
ED_region_tag_redraw(ar);
}
static int sort_panels_by_sortorder(void *o1, void *o2)
{
Panel *pa1 = (Panel*)o1;
Panel *pa2 = (Panel*)o2;
return pa1->sortorder > pa2->sortorder;
}
static uiBlock *active_panel_menu_popup_create_block(bContext *C, ARegion *cur_ar, void *arg_ar)
{
uiBlock *block;
Panel *pa;
ARegion *ar = (ARegion*)arg_ar;
uiLayout *layout, *col;
uiStyle *style = UI_GetStyle();
uiBut *but;
const char *context = CTX_data_mode_string(C);
int width = 10 * UI_UNIT_X;
int height = 12 * UI_UNIT_Y;
// bool all_showing = true;
block = uiBeginBlock(C, cur_ar, __func__, UI_EMBOSS);
uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
uiBlockSetHandleFunc(block, active_panel_menu_popup_cb, block);
layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, style->panelspace, 0, width - 2 * style->panelspace, height, style);
col = uiLayoutColumn(layout, TRUE);
CTX_wm_region_set(C, ar);
BLI_sortlist(&ar->panels, sort_panels_by_sortorder);
/*
The following code is meant to show 2 buttons:
1. - Show all => a button that is shown if 1 or more panels are hidden and unhides all panels when pressed.
- Hide all => a button that is shown if all panels are visible and hides all panels when pressed
2. Invert => a button that hides the visible panels and unhides the hidden ones when pressed.
However, it is not so easy to redraw a popup block and this
severly limits the usefulness of these buttons. The rest of the
buttons don't update accordingly and the panel would have to be
reopened again by the user. Without these extra buttons the panel
is conceptually clear, and I doubt that the extra buttons would
be very helpful.
*/
// for (pa = ar->panels.first; pa; pa = pa->next) {
// /* check to see if this panel should be considered */
// if (pa->type && !(pa->type->flag & PNL_NO_HEADER) &&
// (pa->type->context[0] ? strcmp(context, pa->type->context) == 0 : true) &&
// (pa->type->poll ? pa->type->poll(C, pa->type) : true)) {
// /* if any panel is not hidden, break */
// if (pa->hidden) {
// all_showing = false;
// break;
// }
// }
// }
//
// but = uiDefBut(block, BUT, 1, !all_showing ? "Show all" : "Hide all", 0, 0, width, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Show all panels");
// // TODO: set callback that shows or hides all panels.
for (pa = ar->panels.first; pa; pa = pa->next) {
/* Create a button with a callback for each panel that belongs fits the mode */
if (!pa->type || pa->type->flag & PNL_NO_HEADER
|| (context && pa->type->context[0] && strcmp(context, pa->type->context) != 0)
|| (pa->type->poll && !pa->type->poll(C, pa->type)))
continue;
uiLayoutRow(col, TRUE);
but = uiDefButBitI(block, OPTIONN, 1, 0, pa->drawname, 0, 0, width, UI_UNIT_Y, (int*)&pa->hidden, 0, 0, 0, 0, "Uncheck to hide panel");
}
CTX_wm_region_set(C, cur_ar);
uiBlockLayoutResolve(block, NULL, NULL);
uiPopupBoundsBlock(block, 4, 0, 0);
uiEndBlock(C, block);
return block;
}
static void active_panel_menu_popup(bContext *C, void *arg_ar, void *UNUSED(arg2))
{
uiPupBlock(C, active_panel_menu_popup_create_block, arg_ar);
}
static void collapse_all_panels(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
uiCollapseAllPanels(sa, ar, CTX_data_mode_string(C));
}
static void view3d_toolbar_header_draw(const bContext *C, Panel *pa)
{
ARegion *ar = CTX_wm_region(C);
uiLayout *layout = pa->layout;
uiLayout *row = uiLayoutRow(layout, TRUE);
const char *name = "";
int modeicon = UI_data_mode_icon(C);
Object *ob = CTX_data_active_object(C);
int modeselect = ob ? ob->mode : OB_MODE_OBJECT;
EnumPropertyItem *item = object_mode_items;
uiBut *but;
while (item->identifier) {
if (item->value == modeselect && item->identifier[0]) {
name = IFACE_(item->name);
break;
}
item++;
}
uiItemL(row, name, modeicon);
but = uiDefIconBut(uiLayoutGetBlock(row), BUT, 0, ICON_CHECKBOX_HLT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Show and hide panels");
uiButSetFunc(but, active_panel_menu_popup, ar, NULL);
but = uiDefIconBut(uiLayoutGetBlock(row), BUT, 0, ICON_TRIA_RIGHT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Collapse all panels in this toolbar");
uiButSetFunc(but, collapse_all_panels, pa, NULL);
uiDefIconButO(uiLayoutGetBlock(row), BUT, "WM_OT_create_custom_panel", WM_OP_INVOKE_DEFAULT, ICON_PLUS, 0, 0, UI_UNIT_X, UI_UNIT_Y, "Add a custom panel to this toolbar");
}
/* ******************* */
typedef struct CustomTool {
@@ -249,19 +395,60 @@ void view3d_tool_props_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel last operator");
strcpy(pt->idname, "VIEW3D_PT_last_operator");
strcpy(pt->label, N_("Operator"));
strcpy(pt->label, N_("Last Operator"));
strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = view3d_panel_operator_redo_header;
pt->draw = view3d_panel_operator_redo;
BLI_addtail(&art->paneltypes, pt);
}
static int view3d_grease_pencil_panel_poll(const bContext *C, PanelType *UNUSED(pt))
{
return ELEM9(CTX_data_mode_enum(C),
CTX_MODE_EDIT_MESH,
CTX_MODE_EDIT_CURVE,
CTX_MODE_EDIT_SURFACE,
CTX_MODE_EDIT_TEXT,
CTX_MODE_EDIT_ARMATURE,
CTX_MODE_EDIT_METABALL,
CTX_MODE_EDIT_LATTICE,
CTX_MODE_POSE,
CTX_MODE_OBJECT);
}
void view3d_grease_register(ARegionType *art)
{
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
strcpy(pt->idname, "VIEW3D_PT_gpencil");
strcpy(pt->label, N_("Grease Pencil")); /* XXX C panels are not available through RNA (bpy.types)! */
strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
pt->poll = view3d_grease_pencil_panel_poll;
BLI_addtail(&art->paneltypes, pt);
}
void view3d_toolbar_header_register(ARegionType *art)
{
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d toolbar header");
strcpy(pt->idname, "VIEW3D_PT_toolbar_header");
strcpy(pt->label, N_("No Label!"));
strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PNL_NO_HEADER;
pt->draw = view3d_toolbar_header_draw;
BLI_addtail(&art->paneltypes, pt);
}
/* ********** operator to open/close toolshelf region */
static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = view3d_has_tools_region(sa);
ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS); //view3d_has_tools_region(sa);
if (ar)
ED_region_toggle_hidden(C, ar);

View File

@@ -557,6 +557,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
ot->description = "Translate (move) selected items";
ot->idname = OP_TRANSLATION;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
ot->default_icon = ICON_MAN_TRANS;
/* api callbacks */
ot->invoke = transform_invoke;
@@ -577,6 +578,7 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
ot->description = "Scale (resize) selected items";
ot->idname = OP_RESIZE;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
ot->default_icon = ICON_MAN_SCALE;
/* api callbacks */
ot->invoke = transform_invoke;
@@ -653,6 +655,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
ot->description = "Rotate selected items";
ot->idname = OP_ROTATION;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
ot->default_icon = ICON_MAN_ROT;
/* api callbacks */
ot->invoke = transform_invoke;

View File

@@ -84,6 +84,7 @@ set(SRC
../include/ED_uvedit.h
../include/ED_view3d.h
../include/UI_icons.h
../include/UI_opicons.h
../include/UI_interface.h
../include/UI_interface_icons.h
../include/UI_resources.h

View File

@@ -37,6 +37,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
@@ -46,10 +47,14 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "ED_util.h"
#include "ED_mesh.h"
#include "WM_api.h"
#include "WM_types.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -80,8 +85,11 @@
static void error(const char *UNUSED(arg)) {}
/* ****** XXX ***** */
/* op should be in the third position so it
correctly maps to UndoElem in wm.c */
typedef struct UndoElem {
struct UndoElem *next, *prev;
wmOperator *op;
ID id; // copy of editmode object ID
Object *ob; // pointer to edited object
int type; // type of edited object
@@ -101,20 +109,25 @@ static UndoElem *curundo = NULL;
/* ********************* xtern api calls ************* */
static void undo_restore(UndoElem *undo, void *editdata, void *obdata)
static void undo_restore(bContext *C, UndoElem *undo, void *editdata, void *obdata)
{
if (undo) {
ListBase included_ops;
undo->to_editmode(undo->undodata, editdata, obdata);
included_ops.first = undobase.first;
included_ops.last = undo;
WM_operator_build_stack(C, &included_ops, true);
}
}
/* name can be a dynamic string */
void undo_editmode_push(bContext *C, const char *name,
void * (*getdata)(bContext * C),
void (*freedata)(void *),
void (*to_editmode)(void *, void *, void *),
void *(*from_editmode)(void *, void *),
int (*validate_undo)(void *, void *))
void * (*getdata)(bContext * C),
void (*freedata)(void *),
void (*to_editmode)(void *, void *, void *),
void *(*from_editmode)(void *, void *),
int (*validate_undo)(void *, void *),
wmOperator *op)
{
UndoElem *uel;
Object *obedit = CTX_data_edit_object(C);
@@ -128,6 +141,9 @@ void undo_editmode_push(bContext *C, const char *name,
/* remove all undos after (also when curundo == NULL) */
while (undobase.last != curundo) {
uel = undobase.last;
// Don't free the op if it is repeated!
if(uel->op && uel->op != op)
WM_operator_free(uel->op);
uel->freedata(uel->undodata);
BLI_freelinkN(&undobase, uel);
}
@@ -142,6 +158,9 @@ void undo_editmode_push(bContext *C, const char *name,
uel->to_editmode = to_editmode;
uel->from_editmode = from_editmode;
uel->validate_undo = validate_undo;
if (op && op->type && op->type->flag & OPTYPE_REGISTER && op->type->flag & OPTYPE_UNDO) {
uel->op = op;
}
/* limit amount to the maximum amount*/
nr = 0;
@@ -154,6 +173,8 @@ void undo_editmode_push(bContext *C, const char *name,
if (uel) {
while (undobase.first != uel) {
UndoElem *first = undobase.first;
if(first->op)
WM_operator_free(first->op);
first->freedata(first->undodata);
BLI_freelinkN(&undobase, first);
}
@@ -186,11 +207,15 @@ void undo_editmode_push(bContext *C, const char *name,
while (undobase.first != uel) {
UndoElem *first = undobase.first;
if(first->op)
WM_operator_free(first->op);
first->freedata(first->undodata);
BLI_freelinkN(&undobase, first);
}
}
}
WM_operator_build_stack(C, &undobase, true);
}
/* helper to remove clean other objects from undo stack */
@@ -222,7 +247,8 @@ static void undo_clean_stack(bContext *C)
else {
if (uel == curundo)
curundo = NULL;
if(uel->op)
WM_operator_free(uel->op);
uel->freedata(uel->undodata);
BLI_freelinkN(&undobase, uel);
}
@@ -242,7 +268,7 @@ void undo_editmode_step(bContext *C, int step)
undo_clean_stack(C);
if (step == 0) {
undo_restore(curundo, curundo->getdata(C), obedit->data);
undo_restore(C, curundo, curundo->getdata(C), obedit->data);
}
else if (step == 1) {
@@ -252,7 +278,7 @@ void undo_editmode_step(bContext *C, int step)
else {
if (G.debug & G_DEBUG) printf("undo %s\n", curundo->name);
curundo = curundo->prev;
undo_restore(curundo, curundo->getdata(C), obedit->data);
undo_restore(C, curundo, curundo->getdata(C), obedit->data);
}
}
else {
@@ -262,7 +288,7 @@ void undo_editmode_step(bContext *C, int step)
error("No more steps to redo");
}
else {
undo_restore(curundo->next, curundo->getdata(C), obedit->data);
undo_restore(C, curundo->next, curundo->getdata(C), obedit->data);
curundo = curundo->next;
if (G.debug & G_DEBUG) printf("redo %s\n", curundo->name);
}
@@ -284,6 +310,8 @@ void undo_editmode_clear(void)
uel = undobase.first;
while (uel) {
if(uel->op)
WM_operator_free(uel->op);
uel->freedata(uel->undodata);
uel = uel->next;
}
@@ -304,12 +332,12 @@ void undo_editmode_number(bContext *C, int nr)
undo_editmode_step(C, 0);
}
void undo_editmode_name(bContext *C, const char *undoname)
void undo_editmode_op(bContext *C, const wmOperator* op)
{
UndoElem *uel;
for (uel = undobase.last; uel; uel = uel->prev) {
if (strcmp(undoname, uel->name) == 0)
if (uel->op == op)
break;
}
if (uel && uel->prev) {

View File

@@ -78,7 +78,7 @@
/* ***************** generic undo system ********************* */
void ED_undo_push(bContext *C, const char *str)
static void ed_undo_push_internal(bContext *C, const char *str, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
Object *obedit = CTX_data_edit_object(C);
@@ -91,25 +91,26 @@ void ED_undo_push(bContext *C, const char *str)
if (U.undosteps == 0) return;
if (obedit->type == OB_MESH)
undo_push_mesh(C, str);
undo_push_mesh(C, str, op);
else if (ELEM(obedit->type, OB_CURVE, OB_SURF))
undo_push_curve(C, str);
undo_push_curve(C, str, op);
else if (obedit->type == OB_FONT)
undo_push_font(C, str);
undo_push_font(C, str, op);
else if (obedit->type == OB_MBALL)
undo_push_mball(C, str);
undo_push_mball(C, str, op);
else if (obedit->type == OB_LATTICE)
undo_push_lattice(C, str);
undo_push_lattice(C, str, op);
else if (obedit->type == OB_ARMATURE)
undo_push_armature(C, str);
undo_push_armature(C, str, op);
}
// not sure what to do with the partice edit undo stack ~ ack-err
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
if (U.undosteps == 0) return;
PE_undo_push(CTX_data_scene(C), str);
}
else {
BKE_write_undo(C, str);
BKE_write_undo_op(C, str, op);
}
if (wm->file_saved) {
@@ -119,8 +120,13 @@ void ED_undo_push(bContext *C, const char *str)
}
}
void ED_undo_push(bContext *C, const char *str)
{
ed_undo_push_internal(C, str, NULL);
}
/* note: also check undo_history_exec() in bottom if you change notifiers */
static int ed_undo_step(bContext *C, int step, const char *undoname)
static int ed_undo_step(bContext *C, int step, const char *undoname, const wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
@@ -141,10 +147,10 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) {
if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname ? undoname : op->type->name)) {
if (U.uiflag & USER_GLOBALUNDO) {
ED_viewport_render_kill_jobs(C, true);
BKE_undo_name(C, undoname);
BKE_undo_name(C, undoname ? undoname : op->type->name);
}
}
@@ -158,8 +164,8 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
}
else if (obedit) {
if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
if (undoname)
undo_editmode_name(C, undoname);
if (op)
undo_editmode_op(C, op);
else
undo_editmode_step(C, step);
@@ -197,9 +203,9 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
undo_editmode_clear();
ED_viewport_render_kill_jobs(C, true);
if (undoname)
BKE_undo_name(C, undoname);
if (op)
BKE_undo_op(C, op);
else
BKE_undo_step(C, step);
@@ -214,23 +220,23 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
void ED_undo_pop(bContext *C)
{
ed_undo_step(C, 1, NULL);
ed_undo_step(C, 1, NULL, NULL);
}
void ED_undo_redo(bContext *C)
{
ed_undo_step(C, -1, NULL);
ed_undo_step(C, -1, NULL, NULL);
}
void ED_undo_push_op(bContext *C, wmOperator *op)
{
/* in future, get undo string info? */
ED_undo_push(C, op->type->name);
ed_undo_push_internal(C, op->type->name, op);
}
void ED_undo_pop_op(bContext *C, wmOperator *op)
{
/* search back a couple of undo's, in case something else added pushes */
ed_undo_step(C, 0, op->type->name);
/* go back to the given op exactly */
ed_undo_step(C, 0, NULL, op);
}
/* name optionally, function used to check for operator redo panel */
@@ -281,9 +287,7 @@ int ED_undo_valid(const bContext *C, const char *undoname)
static int ed_undo_exec(bContext *C, wmOperator *UNUSED(op))
{
/* "last operator" should disappear, later we can tie this with undo stack nicer */
WM_operator_stack_clear(CTX_wm_manager(C));
return ed_undo_step(C, 1, NULL);
return ed_undo_step(C, 1, NULL, NULL);
}
static int ed_undo_push_exec(bContext *C, wmOperator *op)
@@ -296,7 +300,7 @@ static int ed_undo_push_exec(bContext *C, wmOperator *op)
static int ed_redo_exec(bContext *C, wmOperator *UNUSED(op))
{
return ed_undo_step(C, -1, NULL);
return ed_undo_step(C, -1, NULL, NULL);
}
@@ -375,9 +379,11 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
printf("redo_cb: operator redo %s\n", op->type->name);
ED_undo_pop_op(C, op);
#if 0
if (op->type->check) {
op->type->check(C, op); /* ignore return value since its running again anyway */
}
#endif
retval = WM_operator_repeat(C, op);
if ((retval & OPERATOR_FINISHED) == 0) {

View File

@@ -35,7 +35,7 @@
/* internal exports only */
/* editmode_undo.c */
void undo_editmode_name (struct bContext *C, const char *undoname);
void undo_editmode_op (struct bContext *C, const struct wmOperator* op);
int undo_editmode_valid (const char *undoname);
const char *undo_editmode_get_name (struct bContext *C, int nr, int *active);
void *undo_editmode_get_prev (struct Object *ob);

View File

@@ -103,13 +103,18 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */
char panelname[64], tabname[64]; /* defined as UI_MAX_NAME_STR */
char drawname[64]; /* panelname is identifier for restoring location */
int ofsx, ofsy, sizex, sizey;
short labelofs, pad;
short labelofs;
short hidden;
short flag, runtime_flag;
short control;
short snap;
int sortorder; /* panels are aligned according to increasing sortorder */
struct Panel *paneltab; /* this panel is tabbed in *paneltab */
void *activedata; /* runtime for panel manipulation */
char context[64]; /* save context for custom panels */
ListBase operators; /* custom operators for custom panel buttons */
} Panel;
/* uiList dynamic data... */
@@ -183,6 +188,17 @@ typedef struct ScrArea {
ListBase actionzones; /* AZone */
} ScrArea;
typedef struct OperatorListItem {
struct OperatorListItem *next, *prev;
char optype_idname[64];
char context[64];
struct IDProperty *properties;
int opcontext;
int flag;
} OperatorListItem;
typedef struct ARegion {
struct ARegion *next, *prev;
@@ -211,11 +227,13 @@ typedef struct ARegion {
ListBase panels; /* Panel */
ListBase ui_lists; /* uiList */
ListBase handlers; /* wmEventHandler */
ListBase operators; /* OperatorListItem for custom tool shelf */
struct wmTimer *regiontimer; /* blend in/out */
char *headerstr; /* use this string to draw info */
void *regiondata; /* XXX 2.50, need spacedata equivalent? */
void *dragdata;
} ARegion;
/* swap */
@@ -257,6 +275,7 @@ typedef struct ARegion {
/* paneltype flag */
#define PNL_DEFAULT_CLOSED 1
#define PNL_NO_HEADER 2
#define PNL_CUSTOM_PANELTYPE 4
/* uiList layout_type */
enum {
@@ -290,6 +309,13 @@ enum {
#define UILST_FLT_SORT_MASK (((unsigned int)UILST_FLT_SORT_REVERSE) - 1)
/* OperatorListItem flags */
enum {
OLI_DIVIDER = 1 << 0, /* 1 for marking the OperatorListItem a divider, 0 for a normal button */
OLI_DIVIDER_CLOSED = 1 << 1 /* 1 for marking a divider as being closed, 0 for open */
};
/* regiontype, first two are the default set */
/* Do NOT change order, append on end. Types are hardcoded needed */
enum {
@@ -300,7 +326,8 @@ enum {
RGN_TYPE_UI = 4,
RGN_TYPE_TOOLS = 5,
RGN_TYPE_TOOL_PROPS = 6,
RGN_TYPE_PREVIEW = 7
RGN_TYPE_PREVIEW = 7,
RGN_TYPE_MENU_BAR = 8,
};
/* region alignment */

View File

@@ -355,6 +355,7 @@ extern StructRNA RNA_MaterialVolume;
extern StructRNA RNA_Mask;
extern StructRNA RNA_MaskLayer;
extern StructRNA RNA_Menu;
extern StructRNA RNA_MenuBar;
extern StructRNA RNA_Mesh;
extern StructRNA RNA_MeshColor;
extern StructRNA RNA_MeshColorLayer;

View File

@@ -102,12 +102,17 @@ EnumPropertyItem node_chunksize_items[] = {
#define DEF_ICON_BLANK_SKIP
#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
#define DEF_VICO(name)
#define DEF_OPICON(name) {OPICON_##name, (#name), 0, (#name), ""},
#define DEF_FIRST_OPICON(name) {OPICON_##name, (#name), 0, (#name), ""},
EnumPropertyItem node_icon_items[] = {
#include "UI_icons.h"
#include "UI_opicons.h"
{0, NULL, 0, NULL, NULL}};
#undef DEF_ICON_BLANK_SKIP
#undef DEF_ICON
#undef DEF_VICO
#undef DEF_OPICON
#undef DEF_FIRST_OPICON
EnumPropertyItem node_math_items[] = {
{ 0, "ADD", 0, "Add", ""},

View File

@@ -45,6 +45,7 @@ EnumPropertyItem region_type_items[] = {
{RGN_TYPE_TOOLS, "TOOLS", 0, "Tools", ""},
{RGN_TYPE_TOOL_PROPS, "TOOL_PROPS", 0, "Tool Properties", ""},
{RGN_TYPE_PREVIEW, "PREVIEW", 0, "Preview", ""},
{RGN_TYPE_MENU_BAR, "MENU_BAR", 0, "Editor Menu Bar", ""},
{0, NULL, 0, NULL, NULL}
};

View File

@@ -38,6 +38,8 @@
#include "rna_internal.h"
#include "RNA_enum_types.h"
#include "RNA_access.h"
#include "UI_interface.h"
#include "WM_types.h"
@@ -757,6 +759,106 @@ static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
else assert(!"setting the bl_description on a non-builtin menu");
}
/* MenuBar */
static void menubar_draw(const bContext *C, MenuBar *mb)
{
extern FunctionRNA rna_MenuBar_draw_func;
PointerRNA ptr;
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(&CTX_wm_screen(C)->id, mb->type->ext.srna, mb, &ptr);
func = &rna_MenuBar_draw_func;
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
mb->type->ext.call((bContext *)C, &ptr, func, &list);
RNA_parameter_list_free(&list);
}
static void rna_MenuBar_unregister(Main *UNUSED(bmain), StructRNA *type)
{
ARegionType *art;
MenuBarType *mbt = RNA_struct_blender_type_get(type);
if (!mbt)
return;
if (!(art = region_type_find(NULL, mbt->space_type, RGN_TYPE_MENU_BAR)))
return;
RNA_struct_free_extension(type, &mbt->ext);
BLI_freelinkN(&art->menubartypes, mbt);
RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
}
static StructRNA *rna_MenuBar_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
ARegionType *art;
MenuBarType *mbt, dummymbt = {NULL};
MenuBar dummymb = {NULL};
PointerRNA dummyptr;
int have_function[1];
/* setup dummy header & header type to store static properties in */
dummymb.type = &dummymbt;
RNA_pointer_create(NULL, &RNA_MenuBar, &dummymb, &dummyptr);
/* validate the python class */
if (validate(&dummyptr, data, have_function) != 0)
return NULL;
if (strlen(identifier) >= sizeof(dummymbt.idname)) {
BKE_reportf(reports, RPT_ERROR, "Registering menu bar class: '%s' is too long, maximum length is %d",
identifier, (int)sizeof(dummymbt.idname));
return NULL;
}
if (!(art = region_type_find(reports, dummymbt.space_type, RGN_TYPE_MENU_BAR)))
return NULL;
/* check if we have registered this header type before, and remove it */
for (mbt = art->menubartypes.first; mbt; mbt = mbt->next) {
if (strcmp(mbt->idname, dummymbt.idname) == 0) {
if (mbt->ext.srna)
rna_MenuBar_unregister(bmain, mbt->ext.srna);
break;
}
}
/* create a new header type */
mbt = MEM_callocN(sizeof(MenuBarType), "register menu bar type");
memcpy(mbt, &dummymbt, sizeof(dummymbt));
mbt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, mbt->idname, &RNA_MenuBar);
mbt->ext.data = data;
mbt->ext.call = call;
mbt->ext.free = free;
RNA_struct_blender_type_set(mbt->ext.srna, mbt);
mbt->draw = (have_function[0]) ? menubar_draw : NULL;
BLI_addtail(&art->menubartypes, mbt);
/* update while blender is running */
WM_main_add_notifier(NC_WINDOW, NULL);
return mbt->ext.srna;
}
static StructRNA *rna_MenuBar_refine(PointerRNA *ptr)
{
MenuBar *mb = (MenuBar *)ptr->data;
return (mb->type && mb->type->ext.srna) ? mb->type->ext.srna : &RNA_MenuBar;
}
/* UILayout */
static int rna_UILayout_active_get(PointerRNA *ptr)
@@ -1240,6 +1342,64 @@ static void rna_def_menu(BlenderRNA *brna)
RNA_define_verify_sdna(1);
}
static void rna_def_menubar(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
PropertyRNA *parm;
FunctionRNA *func;
srna = RNA_def_struct(brna, "MenuBar", NULL);
RNA_def_struct_ui_text(srna, "MenuBar", "Menu Bar for the editor");
RNA_def_struct_sdna(srna, "MenuBar");
RNA_def_struct_refine_func(srna, "rna_MenuBar_refine");
RNA_def_struct_register_funcs(srna, "rna_MenuBar_register", "rna_MenuBar_unregister", NULL);
/* draw */
func = RNA_def_function(srna, "draw", NULL);
RNA_def_function_ui_description(func, "Draw UI elements into the menu bar UI layout");
RNA_def_function_flag(func, FUNC_REGISTER);
parm = RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
RNA_define_verify_sdna(0); /* not in sdna */
prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "layout");
RNA_def_property_struct_type(prop, "UILayout");
RNA_def_property_ui_text(prop, "Layout", "Structure of the menu bar in the UI");
/* registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->idname");
RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
RNA_def_property_ui_text(prop, "ID Name",
"If this is set, the menu bar gets a custom ID, otherwise it takes "
"the name of the class used to define the menu bar; for example, if the "
"class name is \"OBJECT_MBT_hello\", and bl_idname is not set by the "
"script, then bl_idname = \"OBJECT_MBT_hello\"");
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
RNA_def_property_enum_items(prop, space_type_items);
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "Space type", "The space where the menu bar is going to be used in");
prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type->region_type");
RNA_def_property_enum_items(prop, region_type_items);
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "Region Type", "The region where the menu bar is going to be used in");
prop = RNA_def_property(srna, "bl_context", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->context");
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_ui_text(prop, "Context",
"The context in which the panel appears");
RNA_define_verify_sdna(1);
}
void RNA_def_ui(BlenderRNA *brna)
{
rna_def_ui_layout(brna);
@@ -1247,6 +1407,7 @@ void RNA_def_ui(BlenderRNA *brna)
rna_def_uilist(brna);
rna_def_header(brna);
rna_def_menu(brna);
rna_def_menubar(brna);
}
#endif /* RNA_RUNTIME */

View File

@@ -50,13 +50,18 @@
#define DEF_ICON_BLANK_SKIP
#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
#define DEF_VICO(name) {VICO_##name, (#name), 0, (#name), ""},
#define DEF_OPICON(name) {OPICON_##name, (#name), 0, (#name), ""},
#define DEF_FIRST_OPICON(name) {OPICON_##name, (#name), 0, (#name), ""},
EnumPropertyItem icon_items[] = {
#include "UI_icons.h"
#include "UI_opicons.h"
{0, NULL, 0, NULL, NULL}
};
#undef DEF_ICON_BLANK_SKIP
#undef DEF_ICON
#undef DEF_VICO
#undef DEF_OPICON
#undef DEF_FIRST_OPICON
#ifdef RNA_RUNTIME
@@ -174,7 +179,7 @@ static void rna_uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const c
}
static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *name, const char *text_ctxt,
int translate, int icon, int emboss)
int translate, int icon, int emboss, int single_unit, int shortcut)
{
wmOperatorType *ot;
int flag;
@@ -190,6 +195,9 @@ static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *
flag = UI_ITEM_O_RETURN_PROPS;
flag |= (emboss) ? 0 : UI_ITEM_R_NO_BG;
if (single_unit) flag |= UI_ITEM_O_SINGLE_UNIT;
if (shortcut) flag |= UI_ITEM_O_SHORTCUT;
return uiItemFullO_ptr(layout, ot, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag);
}
@@ -422,21 +430,26 @@ void RNA_api_ui_layout(StructRNA *srna)
static float node_socket_color_default[] = { 0.0f, 0.0f, 0.0f, 1.0f };
/* simple layout specifiers */
func = RNA_def_function(srna, "row", "uiLayoutRow");
func = RNA_def_function(srna, "row", "uiLayoutRowWithButtonHeight");
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,
"Sub-layout. Items placed in this sublayout are placed next to each other "
"in a row");
RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
// TODO: button_height should be replaced by the already present scale_y property. ~ ack-err
parm = RNA_def_float(func, "button_height", 1.0f, 1.0f, 5.0f, "",
"The multiplier for the height of buttons in this new layout.", 1.0f, 5.0f);
func = RNA_def_function(srna, "column", "uiLayoutColumn");
func = RNA_def_function(srna, "column", "uiLayoutColumnWithButtonHeight");
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,
"Sub-layout. Items placed in this sublayout are placed under each other "
"in a column");
RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
parm = RNA_def_float(func, "button_height", 1.0f, 1.0f, 5.0f, "",
"The multiplier for the height of buttons in this new layout.", 1.0f, 5.0f);
func = RNA_def_function(srna, "column_flow", "uiLayoutColumnFlow");
RNA_def_int(func, "columns", 0, 0, INT_MAX, "", "Number of columns, 0 is automatic", 0, INT_MAX);
@@ -536,6 +549,8 @@ void RNA_api_ui_layout(StructRNA *srna)
func = RNA_def_function(srna, "operator", "rna_uiItemO");
api_ui_item_op_common(func);
RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text");
RNA_def_boolean(func, "single_unit", 0, "", "Truncate the button width to a single unit if there is no text");
RNA_def_boolean(func, "shortcut", 1, "", "Show the shortcut on the button if there is one");
parm = RNA_def_pointer(func, "properties", "OperatorProperties", "",
"Operator properties to fill in, return when 'properties' is set to true");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
@@ -641,6 +656,15 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_int(func, "rows", 0, 0, INT_MAX, "Number of thumbnail preview rows to display", "", 0, INT_MAX);
RNA_def_int(func, "cols", 0, 0, INT_MAX, "Number of thumbnail preview columns to display", "", 0, INT_MAX);
func = RNA_def_function(srna, "template_ID_preview_compact", "uiTemplateIDPreviewCompact");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
api_ui_item_rna_common(func);
RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block");
RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a file for creating a new ID block");
RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block");
RNA_def_int(func, "rows", 0, 0, INT_MAX, "Number of thumbnail preview rows to display", "", 0, INT_MAX);
RNA_def_int(func, "cols", 0, 0, INT_MAX, "Number of thumbnail preview columns to display", "", 0, INT_MAX);
func = RNA_def_function(srna, "template_any_ID", "rna_uiTemplateAnyID");
parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);

View File

@@ -464,7 +464,7 @@ static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr)
if (wm)
for (op = wm->operators.first; op; op = op->next)
if (op->properties == properties)
if (op->properties && op->properties == properties)
return op;
return NULL;
@@ -1424,6 +1424,12 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_property_enum_items(prop, operator_flag_items);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Options", "Options for this operator type");
prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type->default_icon");
RNA_def_property_enum_items(prop, icon_items); /* TODO: operator_icon_items */
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Icon", "Default icon for this operator type");
RNA_api_operator(srna);

View File

@@ -209,6 +209,7 @@ int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, con
void WM_operator_free (struct wmOperator *op);
void WM_operator_type_set(struct wmOperator *op, struct wmOperatorType *ot);
void WM_operator_stack_clear(struct wmWindowManager *wm);
void WM_operator_build_stack(struct bContext *C, const ListBase *uels, bool notify);
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot);
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet);
@@ -250,9 +251,16 @@ void WM_operator_properties_select_action(struct wmOperatorType *ot, int defaul
bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
wmOperator *WM_operator_last_redo(const struct bContext *C);
bool WM_operator_last_properties_init(struct wmOperator *op);
wmOperator *WM_operator_create(const struct bContext *C, struct wmOperatorType *ot,
struct PointerRNA *properties, struct ReportList *reports);
wmOperator *WM_operator_copy(struct bContext *C, wmOperator *op, bool copylink);
bool WM_operator_properties_init(struct wmOperator *op);
bool WM_operator_last_properties_store(struct wmOperator *op);
bool WM_operator_default_properties_store(struct wmOperator *op);
void add_to_icon_shelf(struct bContext *C, void *arg1, void *arg2);
void add_to_custom_panel_menu(struct bContext *C, struct uiLayout *layout, void *arg);
/* MOVE THIS SOMEWHERE ELSE */
#define SEL_TOGGLE 0
#define SEL_SELECT 1
@@ -322,11 +330,12 @@ void WM_event_print(const struct wmEvent *event);
void WM_operator_region_active_win_set(struct bContext *C);
/* drag and drop */
struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value);
struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value, struct PointerRNA *ptr, short opcontext);
void wm_drag_free(struct wmDrag *drag);
void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx, int sy);
struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event),
void (*copy)(struct wmDrag *, struct wmDropBox *));
void (*copy)(const struct bContext *, const struct wmEvent *, struct wmDrag *, struct wmDropBox *));
ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid);
/* Set a subwindow active in pixelspace view, with optional scissor subset */

View File

@@ -545,10 +545,17 @@ typedef struct wmOperatorType {
/* optional panel for redo and repeat, autogenerated if not set */
void (*ui)(struct bContext *, struct wmOperator *);
/* optional function to decide which icon to use based on operator properties */
int (*icon)(const struct bContext *, PointerRNA *);
/* rna for properties */
struct StructRNA *srna;
/* default settings - for initializing */
struct IDProperty *default_properties;
struct wmOperator *default_properties_op;
/* previous settings - for initializing on re-use */
struct IDProperty *last_properties;
@@ -572,6 +579,7 @@ typedef struct wmOperatorType {
/* Flag last for padding */
short flag;
int default_icon;
} wmOperatorType;
@@ -606,6 +614,7 @@ typedef struct wmReport {
#define WM_DRAG_PATH 2
#define WM_DRAG_NAME 3
#define WM_DRAG_VALUE 4
#define WM_DRAG_OP 5
/* note: structs need not exported? */
@@ -622,6 +631,8 @@ typedef struct wmDrag {
int sx, sy;
char opname[200]; /* if set, draws operator name*/
PointerRNA *ptr;
int opcontext;
} wmDrag;
/* dropboxes are like keymaps, part of the screen/area/region definition */
@@ -633,7 +644,7 @@ typedef struct wmDropBox {
int (*poll)(struct bContext *, struct wmDrag *, const wmEvent *);
/* before exec, this copies drag info to wmDrop properties */
void (*copy)(struct wmDrag *, struct wmDropBox *);
void (*copy)(const struct bContext *, const struct wmEvent *, struct wmDrag *, struct wmDropBox *);
/* if poll survives, operator is called */
wmOperatorType *ot; /* not saved in file, so can be pointer */

View File

@@ -134,9 +134,13 @@ static void wm_reports_free(wmWindowManager *wm)
void wm_operator_register(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
int tot;
BLI_addtail(&wm->operators, op);
/* The operator stack is limited by the undo stacks, and therefore we do not
* have to check for MAX_OP_REGISTERED. */
#if 0
int tot;
tot = BLI_countlist(&wm->operators);
while (tot > MAX_OP_REGISTERED) {
@@ -145,6 +149,7 @@ void wm_operator_register(bContext *C, wmOperator *op)
WM_operator_free(opt);
tot--;
}
#endif
/* so the console is redrawn */
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
@@ -163,6 +168,34 @@ void WM_operator_stack_clear(wmWindowManager *wm)
WM_main_add_notifier(NC_WM | ND_HISTORY, NULL);
}
/* This ugly little duckling is used to be able to access both the
edit mode and object mode UndoElems. */
typedef struct UndoElem {
struct UndoElem *next, *prev;
wmOperator * op;
} UndoElem;
void WM_operator_build_stack(bContext *C, const ListBase *uels, bool notify)
{
wmWindowManager *wm = CTX_wm_manager(C);
UndoElem *uel;
wm->operators.first = NULL;
wm->operators.last = NULL;
for (uel = uels->first; uel && uel->prev != uels->last; uel = uel->next) {
if (uel->op && uel->op->type && uel->op->type->flag & OPTYPE_UNDO && uel->op->type->flag & OPTYPE_REGISTER) {
BLI_addtail(&wm->operators, uel->op);
}
}
if (notify)
{
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
WM_event_add_notifier(C, NC_WM | ND_HISTORY, NULL);
}
}
/**
* This function is needed in the case when an addon id disabled
* while a modal operator it defined is running.
@@ -407,8 +440,8 @@ void wm_add_default(bContext *C)
void wm_close_and_free(bContext *C, wmWindowManager *wm)
{
wmWindow *win;
wmOperator *op;
wmKeyConfig *keyconf;
wmDrag *drag;
if (wm->autosavetimer)
wm_autosave_timer_ended(wm);
@@ -419,9 +452,12 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
wm_window_free(C, wm, win);
}
#if 0
// we're freeing the operators from the undo system
while ((op = BLI_pophead(&wm->operators))) {
WM_operator_free(op);
}
#endif
while ((keyconf = BLI_pophead(&wm->keyconfigs))) {
WM_keyconfig_free(keyconf);
@@ -430,6 +466,10 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
BLI_freelistN(&wm->queue);
BLI_freelistN(&wm->paintcursors);
while ((drag = BLI_pophead(&wm->drags))) {
wm_drag_free(drag);
}
BLI_freelistN(&wm->drags);
wm_reports_free(wm);

View File

@@ -104,7 +104,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, const wmEvent *),
void (*copy)(wmDrag *, wmDropBox *))
void (*copy)(const bContext *, const wmEvent *, wmDrag *, wmDropBox *))
{
wmDropBox *drop = MEM_callocN(sizeof(wmDropBox), "wmDropBox");
@@ -147,7 +147,7 @@ void wm_dropbox_free(void)
/* *********************************** */
/* note that the pointer should be valid allocated and not on stack */
wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value)
wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value, PointerRNA *ptr, short opcontext)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmDrag *drag = MEM_callocN(sizeof(struct wmDrag), "new drag");
@@ -160,6 +160,15 @@ wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin,
drag->type = type;
if (type == WM_DRAG_PATH)
BLI_strncpy(drag->path, poin, FILE_MAX);
else if (type == WM_DRAG_OP) {
/* the PointerRNA should be copied */
if (ptr && ptr->data) {
drag->ptr = MEM_callocN(sizeof(PointerRNA), "PointerRNA for dragging");
drag->ptr->data = IDP_CopyProperty(ptr->data);
}
drag->opcontext = (int)opcontext;
drag->poin = poin;
}
else
drag->poin = poin;
drag->value = value;
@@ -167,6 +176,16 @@ wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin,
return drag;
}
/* N.B. this doesn't free drag itself */
void wm_drag_free(wmDrag *drag)
{
if (drag->ptr) {
if (drag->type == WM_DRAG_OP)
WM_operator_properties_free(drag->ptr);
MEM_freeN(drag->ptr);
}
}
void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy)
{
drag->imb = imb;
@@ -199,7 +218,9 @@ static const char *wm_dropbox_active(bContext *C, wmDrag *drag, wmEvent *event)
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
const char *name;
ARegion *ar_iter = NULL;
const char *name = NULL;
const char *name_overlap = NULL;
name = dropbox_active(C, &win->handlers, drag, event);
if (name) return name;
@@ -208,7 +229,27 @@ static const char *wm_dropbox_active(bContext *C, wmDrag *drag, wmEvent *event)
if (name) return name;
name = dropbox_active(C, &ar->handlers, drag, event);
if (name) return name;
/* Make sure overlapping regions are preferred over non-overlapping ones */
if (!ar->overlap) {
for (ar_iter = sa->regionbase.first; ar_iter; ar_iter = ar_iter->next) {
if (ar_iter->overlap) {
/* only update name_overlap if none was found yet */
if (name_overlap == NULL) {
/* We've got to fake the region for a little bit */
CTX_wm_region_set(C, ar_iter);
name_overlap = dropbox_active(C, &ar_iter->handlers, drag, event);
}
}
}
}
/* make sure proper region is restored */
CTX_wm_region_set(C, ar);
if (name_overlap)
return name_overlap;
if (name)
return name;
return NULL;
}
@@ -279,6 +320,11 @@ static const char *wm_drag_name(wmDrag *drag)
return drag->path;
case WM_DRAG_NAME:
return (char *)drag->path;
case WM_DRAG_OP:
{
wmOperatorType *ot = (wmOperatorType*)drag->poin;
return ot->name;
}
}
return "";
}

View File

@@ -109,8 +109,16 @@ void wm_event_free(wmEvent *event)
if (event->customdata) {
if (event->customdatafree) {
/* note: pointer to listbase struct elsewhere */
if (event->custom == EVT_DATA_LISTBASE)
if (event->custom == EVT_DATA_LISTBASE) {
if (event->type == EVT_DROP) {
ListBase *lb = (ListBase *)event->customdata;
wmDrag *drag;
for (drag = lb->first; drag; drag = drag->next) {
wm_drag_free(drag);
}
}
BLI_freelistN(event->customdata);
}
else
MEM_freeN(event->customdata);
}
@@ -638,6 +646,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, int cal
wm_add_reports(C, op->reports);
}
#if 0
/* this function is mainly to check that the rules for freeing
* an operator are kept in sync.
*/
@@ -645,8 +654,9 @@ static int wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot)
{
return wm && (wm->op_undo_depth == 0) && (ot->flag & OPTYPE_REGISTER);
}
#endif
static void wm_operator_finished(bContext *C, wmOperator *op, int repeat)
static void wm_operator_finished(bContext *C, wmOperator *op, int UNUSED(repeat))
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -655,10 +665,16 @@ static void wm_operator_finished(bContext *C, wmOperator *op, int repeat)
/* we don't want to do undo pushes for operators that are being
* called from operators that already do an undo push. usually
* this will happen for python operators that call C operators */
if (wm->op_undo_depth == 0)
if (op->type->flag & OPTYPE_UNDO)
ED_undo_push_op(C, op);
if (wm->op_undo_depth == 0
&& op->type->flag & OPTYPE_UNDO) {
ED_undo_push_op(C, op);
if (!(op->type->flag & OPTYPE_REGISTER))
WM_operator_free(op);
} else
WM_operator_free(op);
#if 0
// operators are registered and freed from the undo system.
if (repeat == 0) {
if (G.debug & G_DEBUG_WM) {
char *buf = WM_operator_pystring(C, op->type, op->ptr, 1);
@@ -677,6 +693,7 @@ static void wm_operator_finished(bContext *C, wmOperator *op, int repeat)
WM_operator_free(op);
}
}
#endif
}
/* if repeat is true, it doesn't register again, nor does it free */
@@ -873,6 +890,30 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot,
return op;
}
wmOperator *WM_operator_create(const bContext *C, wmOperatorType *ot,
PointerRNA *properties, ReportList *reports)
{
wmWindowManager *wm = CTX_wm_manager(C);
return wm_operator_create(wm, ot, properties, reports);
}
wmOperator *WM_operator_copy(bContext *C, wmOperator *op, bool copylink)
{
/* The logic wm_operator_create is used as it already
* creates copies of the properties. Note that the
* report list is not copied. */
wmWindowManager *wm = CTX_wm_manager(C);
wmOperator *newop = wm_operator_create(wm, op->type, op->ptr, NULL);
/* This likely isn't necessary. */
if(!copylink)
{
newop->next = NULL;
newop->prev = NULL;
}
return newop;
}
static void wm_region_mouse_co(bContext *C, wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
@@ -888,59 +929,68 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event)
}
}
#if 1 /* may want to disable operator remembering previous state for testing */
bool WM_operator_last_properties_init(wmOperator *op)
{
static bool wm_operator_properties_init_set(wmOperator *op, IDProperty **properties, bool respect_skip_save, bool respect_already_set) {
PropertyRNA *iterprop = iterprop = RNA_struct_iterator_property(op->type->srna);
bool change = false;
if (op->type->last_properties) {
PropertyRNA *iterprop;
if (G.debug & G_DEBUG_WM) {
printf("%s: loading previous properties for '%s'\n", __func__, op->type->idname);
}
iterprop = RNA_struct_iterator_property(op->type->srna);
RNA_PROP_BEGIN (op->ptr, itemptr, iterprop)
{
PropertyRNA *prop = itemptr.data;
if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
if (!RNA_property_is_set(op->ptr, prop)) { /* don't override a setting already set */
const char *identifier = RNA_property_identifier(prop);
IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, identifier);
if (idp_src) {
IDProperty *idp_dst = IDP_CopyProperty(idp_src);
/* note - in the future this may need to be done recursively,
* but for now RNA doesn't access nested operators */
idp_dst->flag |= IDP_FLAG_GHOST;
IDP_ReplaceInGroup(op->properties, idp_dst);
change = true;
}
RNA_PROP_BEGIN (op->ptr, itemptr, iterprop)
{
PropertyRNA *prop = itemptr.data;
if (!respect_skip_save || (RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
if (!respect_already_set || !RNA_property_is_set(op->ptr, prop)) { /* don't override a setting already set */
const char *identifier = RNA_property_identifier(prop);
IDProperty *idp_src = IDP_GetPropertyFromGroup(*properties, identifier);
if (idp_src) {
IDProperty *idp_dst = IDP_CopyProperty(idp_src);
/* note - in the future this may need to be done recursively,
* but for now RNA doesn't access nested operators */
idp_dst->flag |= IDP_FLAG_GHOST;
IDP_ReplaceInGroup(op->properties, idp_dst);
change = true;
}
}
}
RNA_PROP_END;
}
RNA_PROP_END;
return change;
}
#if 1 /* may want to disable operator remembering previous state for testing */
bool WM_operator_properties_init(wmOperator *op)
{
bool change = false;
if (op->type->default_properties) {
if (G.debug & G_DEBUG_WM) {
printf("%s: loading default properties for '%s'\n", __func__, op->type->idname);
}
change = wm_operator_properties_init_set(op, &(op->type->default_properties), FALSE, FALSE);
}
if (op->type->last_properties) {
if (G.debug & G_DEBUG_WM) {
printf("%s: loading previous properties for '%s'\n", __func__, op->type->idname);
}
// don't overwrite the previously set change flag
change = change ? change : wm_operator_properties_init_set(op, &(op->type->last_properties), TRUE, TRUE);
}
return change;
}
bool WM_operator_last_properties_store(wmOperator *op)
static bool wm_operator_properties_store(wmOperator *op, IDProperty **properties)
{
if (op->type->last_properties) {
IDP_FreeProperty(op->type->last_properties);
MEM_freeN(op->type->last_properties);
op->type->last_properties = NULL;
if (*properties) {
IDP_FreeProperty(*properties);
MEM_freeN(*properties);
*properties = NULL;
}
if (op->properties) {
if (G.debug & G_DEBUG_WM) {
printf("%s: storing properties for '%s'\n", __func__, op->type->idname);
}
op->type->last_properties = IDP_CopyProperty(op->properties);
*properties = IDP_CopyProperty(op->properties);
return true;
}
else {
@@ -948,6 +998,16 @@ bool WM_operator_last_properties_store(wmOperator *op)
}
}
bool WM_operator_last_properties_store(wmOperator *op)
{
return wm_operator_properties_store(op, &(op->type->last_properties));
}
bool WM_operator_default_properties_store(wmOperator *op)
{
return wm_operator_properties_store(op, &(op->type->default_properties));
}
#else
int WM_operator_last_properties_init(wmOperator *UNUSED(op))
@@ -978,9 +1038,9 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
/* initialize setting from previous run */
if (!is_nested_call) { /* not called by py script */
WM_operator_last_properties_init(op);
WM_operator_properties_init(op);
}
if ((G.debug & G_DEBUG_HANDLERS) && ((event == NULL) || (event->type != MOUSEMOVE))) {
printf("%s: handle evt %d win %d op %s\n",
__func__, event ? event->type : 0, CTX_wm_screen(C)->subwinactive, ot->idname);
@@ -1698,7 +1758,11 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
WM_operator_last_properties_store(handler->op);
}
WM_operator_free(handler->op);
// Only free if it wasn't registered
if (!(handler->op->type
&& (handler->op->type->flag & OPTYPE_REGISTER)
&& (handler->op->type->flag & OPTYPE_UNDO)))
WM_operator_free(handler->op);
}
else {
if (handler->op->type->cancel) {
@@ -1876,24 +1940,27 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
for (drag = lb->first; drag; drag = drag->next) {
if (drop->poll(C, drag, event)) {
drop->copy(drag, drop);
drop->copy(C, event, drag, drop);
/* free the drags before calling operator */
BLI_freelistN(event->customdata);
event->customdata = NULL;
event->custom = 0;
WM_operator_name_call(C, drop->ot->idname, drop->opcontext, drop->ptr);
action |= WM_HANDLER_BREAK;
/* XXX fileread case */
if (CTX_wm_window(C) == NULL)
return action;
/* escape from drag loop, got freed */
/* escape from drag loop... */
break;
}
}
/* and free all the drags */
for (drag = lb->first; drag; drag = drag->next) {
wm_drag_free(drag);
}
BLI_freelistN(lb);
}
}
}
@@ -2077,18 +2144,34 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even
if (event->type == MOUSEMOVE)
win->screen->do_draw_drag = TRUE;
else if (event->type == ESCKEY) {
wmDrag *drag;
for (drag = wm->drags.first; drag; drag = drag->next) {
wm_drag_free(drag);
}
BLI_freelistN(&wm->drags);
win->screen->do_draw_drag = TRUE;
}
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
event->type = EVT_DROP;
/* create customdata, first free existing */
if (event->customdata) {
if (event->customdatafree)
MEM_freeN(event->customdata);
if (event->customdatafree) {
if (event->custom == EVT_DATA_LISTBASE) {
if (event->type == EVT_DROP) {
ListBase *lb = (ListBase *)event->customdata;
wmDrag *drag;
for (drag = lb->first; drag; drag = drag->next) {
wm_drag_free(drag);
}
}
BLI_freelistN(event->customdata);
}
else
MEM_freeN(event->customdata);
}
}
event->type = EVT_DROP;
event->custom = EVT_DATA_LISTBASE;
event->customdata = &wm->drags;
event->customdatafree = 1;
@@ -2216,29 +2299,37 @@ void wm_event_do_handlers(bContext *C)
CTX_wm_area_set(C, sa);
if ((action & WM_HANDLER_BREAK) == 0) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (wm_event_inside_i(event, &ar->winrct)) {
CTX_wm_region_set(C, ar);
/* call even on non mouse events, since the */
wm_region_mouse_co(C, event);
/* Go through the regions twice, first for floating regions, then for normal ones.
This entails that floating panels catch events first. This is done because floating
panels should be drawn over other regions. */
for (int i=0; i<2; i++) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if ((i == 0 && ar->alignment == RGN_ALIGN_FLOAT) ||
(i == 1 && ar->alignment != RGN_ALIGN_FLOAT)) {
if (wm_event_inside_i(event, &ar->winrct)) {
CTX_wm_region_set(C, ar);
/* call even on non mouse events, since the */
wm_region_mouse_co(C, event);
/* does polls for drop regions and checks uibuts */
/* need to be here to make sure region context is true */
if (ELEM(event->type, MOUSEMOVE, EVT_DROP)) {
wm_drags_check_ops(C, event);
/* does polls for drop regions and checks uibuts */
/* need to be here to make sure region context is true */
if (ELEM(event->type, MOUSEMOVE, EVT_DROP)) {
wm_drags_check_ops(C, event);
}
action |= wm_handlers_do(C, event, &ar->handlers);
/* fileread case (python), [#29489] */
if (CTX_wm_window(C) == NULL)
return;
doit |= (BLI_rcti_isect_pt_v(&ar->winrct, &event->x));
if (action & WM_HANDLER_BREAK)
break;
}
}
action |= wm_handlers_do(C, event, &ar->handlers);
/* fileread case (python), [#29489] */
if (CTX_wm_window(C) == NULL)
return;
doit |= (BLI_rcti_isect_pt_v(&ar->winrct, &event->x));
if (action & WM_HANDLER_BREAK)
break;
}
}
}

View File

@@ -484,7 +484,7 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
#endif
BKE_reset_undo();
BKE_reset_undo(C);
BKE_write_undo(C, "original"); /* save current state */
}
else if (retval == BKE_READ_EXOTIC_OK_OTHER)
@@ -594,7 +594,7 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
// refresh_interface_font();
// undo_editmode_clear();
BKE_reset_undo();
BKE_reset_undo(C);
BKE_write_undo(C, "original"); /* save current state */
ED_editors_init(C);

View File

@@ -395,6 +395,7 @@ void WM_exit_ext(bContext *C, const short do_python)
wmWindow *win;
if (!G.background) {
if ((U.uiflag2 & USER_KEEP_SESSION) || BKE_undo_valid(NULL)) {
/* save the undo state as quit.blend */
char filename[FILE_MAX];
@@ -493,7 +494,7 @@ void WM_exit_ext(bContext *C, const short do_python)
GPU_free_unused_buffers();
GPU_extensions_exit();
BKE_reset_undo();
BKE_reset_undo(C);
ED_file_exit(); /* for fsmenu */

View File

@@ -91,6 +91,7 @@
#include "ED_object.h"
#include "ED_view3d.h"
#include "RNA_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -113,6 +114,8 @@ static GHash *global_ops_hash = NULL;
#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
#define MAX_CUSTOM_PANELS 1000
/* ************ operator API, exported ********** */
@@ -467,6 +470,14 @@ int WM_operatortype_remove(const char *idname)
IDP_FreeProperty(ot->last_properties);
MEM_freeN(ot->last_properties);
}
if (ot->default_properties) {
IDP_FreeProperty(ot->default_properties);
MEM_freeN(ot->default_properties);
}
if(ot->default_properties_op)
WM_operator_free(ot->default_properties_op);
if (ot->macro.first)
wm_operatortype_free_macro(ot);
@@ -1217,7 +1228,9 @@ wmOperator *WM_operator_last_redo(const bContext *C)
wmWindowManager *wm = CTX_wm_manager(C);
wmOperator *op;
/* only for operators that are registered and did an undo push */
/* Only for operators that are registered and did an undo push.
These should be the only ones in here anyway.
*/
for (op = wm->operators.last; op; op = op->prev)
if ((op->type->flag & OPTYPE_REGISTER) && (op->type->flag & OPTYPE_UNDO))
break;
@@ -1235,8 +1248,10 @@ static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event))
}
else {
/* operator not executed yet, call it */
ED_undo_push_op(C, op);
wm_operator_register(C, op);
/* -- When does this happen?
-- Also, the undo stack should be updated when the operator finishes
~ ack-err */
//ED_undo_push_op(C, op);
WM_operator_repeat(C, op);
}
@@ -1385,7 +1400,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, style);
/* since ui is defined the auto-layout args are not used */
uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0);
uiLayoutOperatorButs(C, layout, op, NULL, 'H', 0);
uiPopupBoundsBlock(block, 4, 0, 0);
uiEndBlock(C, block);
@@ -4137,6 +4152,286 @@ static void operatortype_ghash_free_cb(wmOperatorType *ot)
MEM_freeN(ot);
}
/* ******************************************************* */
void add_to_icon_shelf(bContext *C, void *ot_arg, void *opptr_arg)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_MENU_BAR);
wmWindowManager *wm = CTX_wm_manager(C);
if (ar && ot_arg)
{
wmOperatorType *ot = (wmOperatorType*)ot_arg;
OperatorListItem *oli;
PointerRNA *opptr = (PointerRNA*)opptr_arg;
if (uiOperatorListItemPresent(&ar->operators, ot->idname, opptr->data, CTX_data_mode_string(C))) {
BKE_reportf(&wm->reports, RPT_INFO, "This operator (%s) is already present in the menubar.", ot->idname);
return;
}
oli = MEM_callocN(sizeof(OperatorListItem), "add operator list item to icon shelf");
BLI_strncpy(oli->optype_idname, ot->idname, OP_MAX_TYPENAME);
BLI_strncpy(oli->context, CTX_data_mode_string(C), MAX_NAME);
if (opptr) {
PropertyRNA *prop;
prop = RNA_struct_find_property(opptr, "COPY_opcontext");
if(prop)
oli->opcontext = RNA_property_int_get(opptr, prop);
/* clear the properties that were only necessary for this operator execution */
/* TODO: see if this can all be done a little bit nicer by including a pointer as a property */
RNA_struct_idprops_unset(opptr, "COPY_opcontext");
RNA_struct_idprops_unset(opptr, "COPY_idname");
oli->properties = IDP_CopyProperty(opptr->data);
}
BLI_addtail(&ar->operators, oli);
ED_region_tag_redraw(ar);
}
}
void add_to_custom_panel_menu(bContext *C, uiLayout *layout, void *arg1)
{
ARegion *ar;
const char *context = CTX_data_mode_string(C);
ScrArea *sa = CTX_wm_area(C);
PanelType *pt;
PropertyRNA *prop;
wmOperatorType *optype = (wmOperatorType*)arg1;
ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
if (ar == NULL) return;
for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
if(strcmp(pt->context, context) == 0
// && pt->space_type == sa->type->spaceid
// && pt->region_type == RGN_TYPE_TOOLS
&& pt->flag & PNL_CUSTOM_PANELTYPE) {
PointerRNA op_ptr = uiItemFullO(layout, "WM_OT_add_to_custom_panel", pt->label, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
prop = RNA_struct_find_property(&op_ptr, "COPY_idname");
RNA_property_string_set(&op_ptr, prop, optype->idname);
prop = RNA_struct_find_property(&op_ptr, "COPY_paneltypeid");
RNA_property_string_set(&op_ptr, prop, pt->idname);
}
}
}
static int wm_create_custom_panel_poll(bContext *C)
{
ScrArea *sa;
ARegion *ar;
if (CTX_wm_window(C) == NULL)
return 0;
sa = CTX_wm_area(C);
ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
return (ar != NULL);
}
static int wm_create_custom_panel_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar;
PanelType *pt_iter;
char *name = NULL;
int name_taken = 1;
// find RGN_TYPE_TOOLS
ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
if (ar == NULL) return OPERATOR_CANCELLED;
// find new name for paneltype
for (int i=0; i < MAX_CUSTOM_PANELS; i++) {
// generate name
name = BLI_sprintfN("custom panel %i", i);
name_taken = 0;
// see if it is taken
for (pt_iter = ar->type->paneltypes.first; pt_iter; pt_iter = pt_iter->next) {
if (strcmp(pt_iter->idname, name) == 0) {
name_taken = 1;
break;
}
}
// clear if taken
if(name_taken) {
MEM_freeN(name);
continue;
} else {
// name the new panel type if not taken
break;
}
}
// If we've run out of names (too many custom panels)
if (name_taken)
return OPERATOR_CANCELLED;
uiCreateCustomPanelType(sa, ar, CTX_data_mode_string(C), name, "Custom Panel");
MEM_freeN(name);
ED_region_tag_redraw(ar);
return OPERATOR_FINISHED;
}
static void WM_OT_create_custom_panel(wmOperatorType *ot)
{
ot->name = "Create Custom Panel";
ot->idname = "WM_OT_create_custom_panel";
ot->description = "Create a custom panel in the current region's toolbar";
ot->exec = wm_create_custom_panel_exec;
ot->poll = wm_create_custom_panel_poll;
}
static int wm_add_to_custom_panel_exec(bContext *C, wmOperator *op)
{
// get operator properties: paneltype idname, property name
PropertyRNA *prop;
char *idname = NULL, *panelid = NULL;
ARegion *ar;
ScrArea *sa = CTX_wm_area(C);
Panel *pa;
wmOperatorType *ot;
prop = RNA_struct_find_property(op->ptr, "COPY_idname");
if(prop == NULL) return OPERATOR_CANCELLED;
idname = RNA_property_string_get_alloc(op->ptr, prop, NULL, 0, NULL);
ot = WM_operatortype_find(idname, 1);
prop = RNA_struct_find_property(op->ptr, "COPY_paneltypeid");
if(prop == NULL) return OPERATOR_CANCELLED;
panelid = RNA_property_string_get_alloc(op->ptr, prop, NULL, 0, NULL);
// get panel
ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
for (pa = ar->panels.first; pa; pa = pa->next) {
if (pa->type && strcmp(pa->type->idname, panelid) == 0) {
break;
}
}
if (pa == NULL) {
MEM_freeN(idname);
MEM_freeN(panelid);
return OPERATOR_CANCELLED;
}
// This shouldn't be necessary, already checked in the dragg poll
if (uiOperatorListItemPresent(&pa->operators, idname, op->ptr->data, CTX_data_mode_string(C))) {
return OPERATOR_CANCELLED;
}
uiPanelAddOperator(C, pa, ot, op->ptr);
MEM_freeN(idname);
MEM_freeN(panelid);
ED_region_tag_redraw(ar);
return OPERATOR_FINISHED;
}
static int wm_add_to_custom_panel_poll(bContext *UNUSED(C))
{
// TODO: what are the necessary conditions?
return 1;
}
static void WM_OT_add_to_custom_panel(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name = "Add to Custom Panel";
ot->idname = "WM_OT_add_to_custom_panel";
ot->description = "Add the selected operator to the custom panel";
// ot->invoke = wm_create_custom_panel_invoke;
ot->exec = wm_add_to_custom_panel_exec;
ot->poll = wm_add_to_custom_panel_poll;
ot->flag |= OPTYPE_INTERNAL;
prop = RNA_def_string(ot->srna, "COPY_idname", "", OP_MAX_TYPENAME, "Operator to add", "The operator id to add to the panel");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE | PROP_REQUIRED);
prop = RNA_def_string(ot->srna, "COPY_paneltypeid", "", OP_MAX_TYPENAME, "idname of PanelType", "idname of the PanelType to add the operator to");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE | PROP_REQUIRED);
prop = RNA_def_int(ot->srna, "COPY_opcontext", 0, 0, 0, "Operator context", "The original opcontext that was set for the button", 0, 0);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE | PROP_REQUIRED);
}
static int wm_menubar_add_dragged_operator_exec(bContext *C, wmOperator *op)
{
PropertyRNA *prop;
char *idname = NULL;
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_MENU_BAR);
wmOperatorType *ot;
if (ar == NULL) return OPERATOR_CANCELLED;
prop = RNA_struct_find_property(op->ptr, "COPY_idname");
if(prop == NULL) return OPERATOR_CANCELLED;
idname = RNA_property_string_get_alloc(op->ptr, prop, NULL, 0, NULL);
ot = WM_operatortype_find(idname, 1);
add_to_icon_shelf(C, ot, op->ptr);
MEM_freeN(idname);
ED_region_tag_redraw(ar);
return OPERATOR_FINISHED;
}
static int wm_menubar_add_dragged_operator_poll(bContext *UNUSED(C))
{
return 1;
}
static void WM_OT_menubar_add_dragged_operator(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name = "Add Operator to Menubar";
ot->idname = "WM_OT_menubar_add_dragged_operator";
ot->description = "Add the dragged operator to the current menubar";
ot->exec = wm_menubar_add_dragged_operator_exec;
ot->poll = wm_menubar_add_dragged_operator_poll;
ot->flag = OPTYPE_INTERNAL;
prop = RNA_def_string(ot->srna, "COPY_idname", "", MAX_NAME, "Operator Name", "The name of the operator to add");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE | PROP_REQUIRED);
prop = RNA_def_int(ot->srna, "COPY_opcontext", 0, 0, 0, "Operator context", "The original opcontext that was set for the button", 0, 0);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE | PROP_REQUIRED);
}
/* ******************************************************* */
/* called on initialize WM_exit() */
void wm_operatortype_free(void)
@@ -4177,6 +4472,9 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_call_menu);
WM_operatortype_append(WM_OT_radial_control);
WM_operatortype_append(WM_OT_ndof_sensitivity_change);
WM_operatortype_append(WM_OT_create_custom_panel);
WM_operatortype_append(WM_OT_add_to_custom_panel);
WM_operatortype_append(WM_OT_menubar_add_dragged_operator);
#if defined(WIN32)
WM_operatortype_append(WM_OT_console_toggle);
#endif

View File

@@ -992,7 +992,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
/* try to get icon type from extension */
icon = ED_file_extension_icon((char *)stra->strings[a]);
WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0);
WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0, NULL, 0);
/* void poin should point to string, it makes a copy */
break; /* only one drop element supported now */
}