space_toolsystem_toolbar.py 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; either version 2
  6. # of the License, or (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software Foundation,
  15. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18. # <pep8 compliant>
  19. # For now group all tools together
  20. # we may want to move these into per space-type files.
  21. #
  22. # For now keep this in a single file since it's an area that may change,
  23. # so avoid making changes all over the place.
  24. import bpy
  25. from bpy.types import Panel
  26. from bl_ui.space_toolsystem_common import (
  27. ToolSelectPanelHelper,
  28. ToolDef,
  29. )
  30. from bpy.app.translations import pgettext_tip as tip_
  31. I18N_CTX_OPERATOR = bpy.app.translations.contexts_C_to_py['BLT_I18NCONTEXT_OPERATOR_DEFAULT']
  32. def kmi_to_string_or_none(kmi):
  33. return kmi.to_string() if kmi else "<none>"
  34. def generate_from_enum_ex(
  35. _context, *,
  36. idname_prefix,
  37. icon_prefix,
  38. type,
  39. attr,
  40. tooldef_keywords={},
  41. ):
  42. tool_defs = []
  43. for enum in type.bl_rna.properties[attr].enum_items_static:
  44. name = enum.name
  45. idname = enum.identifier
  46. tool_defs.append(
  47. ToolDef.from_dict(
  48. dict(
  49. idname=idname_prefix + name,
  50. label=name,
  51. icon=icon_prefix + idname.lower(),
  52. data_block=idname,
  53. **tooldef_keywords,
  54. )
  55. )
  56. )
  57. return tuple(tool_defs)
  58. # Use for shared widget data.
  59. class _template_widget:
  60. class VIEW3D_GGT_xform_extrude:
  61. @staticmethod
  62. def draw_settings(_context, layout, tool):
  63. props = tool.gizmo_group_properties("VIEW3D_GGT_xform_extrude")
  64. layout.prop(props, "axis_type", expand=True)
  65. class VIEW3D_GGT_xform_gizmo:
  66. @staticmethod
  67. def draw_settings_with_index(context, layout, index):
  68. scene = context.scene
  69. orient_slot = scene.transform_orientation_slots[index]
  70. layout.prop(orient_slot, "type")
  71. class _defs_view3d_generic:
  72. @ToolDef.from_fn
  73. def cursor():
  74. def draw_settings(_context, layout, tool):
  75. props = tool.operator_properties("view3d.cursor3d")
  76. layout.prop(props, "use_depth")
  77. layout.prop(props, "orientation")
  78. return dict(
  79. idname="builtin.cursor",
  80. label="Cursor",
  81. description=(
  82. "Set the cursor location, drag to transform"
  83. ),
  84. icon="ops.generic.cursor",
  85. keymap="3D View Tool: Cursor",
  86. draw_settings=draw_settings,
  87. )
  88. @ToolDef.from_fn
  89. def cursor_click():
  90. return dict(
  91. idname="builtin.none",
  92. label="None",
  93. icon="ops.generic.cursor",
  94. keymap=(),
  95. )
  96. @ToolDef.from_fn
  97. def ruler():
  98. def description(_context, _item, km):
  99. if km is not None:
  100. kmi_add = km.keymap_items.find_from_operator("view3d.ruler_add")
  101. kmi_remove = km.keymap_items.find_from_operator("view3d.ruler_remove")
  102. else:
  103. kmi_add = None
  104. kmi_remove = None
  105. return tip_(
  106. "Measure distance and angles.\n"
  107. "\u2022 {} anywhere for new measurement.\n"
  108. "\u2022 Drag ruler segment to measure an angle.\n"
  109. "\u2022 {} to remove the active ruler.\n"
  110. "\u2022 Ctrl while dragging to snap.\n"
  111. "\u2022 Shift while dragging to measure surface thickness."
  112. ).format(
  113. kmi_to_string_or_none(kmi_add),
  114. kmi_to_string_or_none(kmi_remove),
  115. )
  116. return dict(
  117. idname="builtin.measure",
  118. label="Measure",
  119. description=description,
  120. icon="ops.view3d.ruler",
  121. widget="VIEW3D_GGT_ruler",
  122. keymap="3D View Tool: Measure",
  123. )
  124. class _defs_annotate:
  125. def draw_settings_common(context, layout, tool):
  126. if type(context.gpencil_data_owner) is bpy.types.Object:
  127. gpd = context.scene.grease_pencil
  128. else:
  129. gpd = context.gpencil_data
  130. if gpd is not None:
  131. if gpd.layers.active_note is not None:
  132. text = gpd.layers.active_note
  133. maxw = 25
  134. if len(text) > maxw:
  135. text = text[:maxw - 5] + '..' + text[-3:]
  136. else:
  137. text = ""
  138. gpl = context.active_gpencil_layer
  139. if gpl is not None:
  140. layout.label(text="Annotation:")
  141. sub = layout.row(align=True)
  142. sub.ui_units_x = 8
  143. sub.prop(gpl, "color", text="")
  144. sub.popover(
  145. panel="TOPBAR_PT_annotation_layers",
  146. text=text,
  147. )
  148. tool_settings = context.tool_settings
  149. space_type = tool.space_type
  150. if space_type == 'VIEW_3D':
  151. layout.separator()
  152. row = layout.row(align=True)
  153. row.prop(tool_settings, "annotation_stroke_placement_view3d", text="Placement")
  154. if tool_settings.gpencil_stroke_placement_view3d == 'CURSOR':
  155. row.prop(tool_settings.gpencil_sculpt, "lockaxis")
  156. elif tool_settings.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}:
  157. row.prop(tool_settings, "use_gpencil_stroke_endpoints")
  158. @ToolDef.from_fn.with_args(draw_settings=draw_settings_common)
  159. def scribble(*, draw_settings):
  160. return dict(
  161. idname="builtin.annotate",
  162. label="Annotate",
  163. icon="ops.gpencil.draw",
  164. cursor='PAINT_BRUSH',
  165. keymap="Generic Tool: Annotate",
  166. draw_settings=draw_settings,
  167. )
  168. @ToolDef.from_fn.with_args(draw_settings=draw_settings_common)
  169. def line(*, draw_settings):
  170. return dict(
  171. idname="builtin.annotate_line",
  172. label="Annotate Line",
  173. icon="ops.gpencil.draw.line",
  174. cursor='CROSSHAIR',
  175. keymap="Generic Tool: Annotate Line",
  176. draw_settings=draw_settings,
  177. )
  178. @ToolDef.from_fn.with_args(draw_settings=draw_settings_common)
  179. def poly(*, draw_settings):
  180. return dict(
  181. idname="builtin.annotate_polygon",
  182. label="Annotate Polygon",
  183. icon="ops.gpencil.draw.poly",
  184. cursor='CROSSHAIR',
  185. keymap="Generic Tool: Annotate Polygon",
  186. draw_settings=draw_settings,
  187. )
  188. @ToolDef.from_fn
  189. def eraser():
  190. def draw_settings(context, layout, _tool):
  191. # TODO: Move this setting to tool_settings
  192. prefs = context.preferences
  193. layout.prop(prefs.edit, "grease_pencil_eraser_radius", text="Radius")
  194. return dict(
  195. idname="builtin.annotate_eraser",
  196. label="Annotate Eraser",
  197. icon="ops.gpencil.draw.eraser",
  198. cursor='CROSSHAIR', # XXX: Always show brush circle when enabled
  199. keymap="Generic Tool: Annotate Eraser",
  200. draw_settings=draw_settings,
  201. )
  202. class _defs_transform:
  203. @ToolDef.from_fn
  204. def translate():
  205. def draw_settings(context, layout, _tool):
  206. _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1)
  207. return dict(
  208. idname="builtin.move",
  209. label="Move",
  210. # cursor='SCROLL_XY',
  211. icon="ops.transform.translate",
  212. widget="VIEW3D_GGT_xform_gizmo",
  213. operator="transform.translate",
  214. keymap="3D View Tool: Move",
  215. draw_settings=draw_settings,
  216. )
  217. @ToolDef.from_fn
  218. def rotate():
  219. def draw_settings(context, layout, _tool):
  220. _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 2)
  221. return dict(
  222. idname="builtin.rotate",
  223. label="Rotate",
  224. # cursor='SCROLL_XY',
  225. icon="ops.transform.rotate",
  226. widget="VIEW3D_GGT_xform_gizmo",
  227. operator="transform.rotate",
  228. keymap="3D View Tool: Rotate",
  229. draw_settings=draw_settings,
  230. )
  231. @ToolDef.from_fn
  232. def scale():
  233. def draw_settings(context, layout, _tool):
  234. _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 3)
  235. return dict(
  236. idname="builtin.scale",
  237. label="Scale",
  238. # cursor='SCROLL_XY',
  239. icon="ops.transform.resize",
  240. widget="VIEW3D_GGT_xform_gizmo",
  241. operator="transform.resize",
  242. keymap="3D View Tool: Scale",
  243. draw_settings=draw_settings,
  244. )
  245. @ToolDef.from_fn
  246. def scale_cage():
  247. def draw_settings(context, layout, _tool):
  248. _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 3)
  249. return dict(
  250. idname="builtin.scale_cage",
  251. label="Scale Cage",
  252. icon="ops.transform.resize.cage",
  253. widget="VIEW3D_GGT_xform_cage",
  254. operator="transform.resize",
  255. keymap="3D View Tool: Scale",
  256. draw_settings=draw_settings,
  257. )
  258. @ToolDef.from_fn
  259. def transform():
  260. def draw_settings(context, layout, tool):
  261. if layout.use_property_split:
  262. layout.label(text="Gizmos:")
  263. props = tool.gizmo_group_properties("VIEW3D_GGT_xform_gizmo")
  264. layout.prop(props, "drag_action")
  265. _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1)
  266. return dict(
  267. idname="builtin.transform",
  268. label="Transform",
  269. description=(
  270. "Supports any combination of grab, rotate & scale at once"
  271. ),
  272. icon="ops.transform.transform",
  273. widget="VIEW3D_GGT_xform_gizmo",
  274. keymap="3D View Tool: Transform",
  275. draw_settings=draw_settings,
  276. )
  277. class _defs_view3d_select:
  278. @ToolDef.from_fn
  279. def select():
  280. def draw_settings(_context, _layout, _tool):
  281. pass
  282. return dict(
  283. idname="builtin.select",
  284. label="Select",
  285. icon="ops.generic.select",
  286. widget=None,
  287. keymap="3D View Tool: Select",
  288. draw_settings=draw_settings,
  289. )
  290. @ToolDef.from_fn
  291. def box():
  292. def draw_settings(_context, layout, tool):
  293. props = tool.operator_properties("view3d.select_box")
  294. row = layout.row()
  295. row.use_property_split = False
  296. row.prop(props, "mode", text="", expand=True, icon_only=True)
  297. return dict(
  298. idname="builtin.select_box",
  299. label="Select Box",
  300. icon="ops.generic.select_box",
  301. widget=None,
  302. keymap="3D View Tool: Select Box",
  303. draw_settings=draw_settings,
  304. )
  305. @ToolDef.from_fn
  306. def lasso():
  307. def draw_settings(_context, layout, tool):
  308. props = tool.operator_properties("view3d.select_lasso")
  309. row = layout.row()
  310. row.use_property_split = False
  311. row.prop(props, "mode", text="", expand=True, icon_only=True)
  312. return dict(
  313. idname="builtin.select_lasso",
  314. label="Select Lasso",
  315. icon="ops.generic.select_lasso",
  316. widget=None,
  317. keymap="3D View Tool: Select Lasso",
  318. draw_settings=draw_settings,
  319. )
  320. @ToolDef.from_fn
  321. def circle():
  322. def draw_settings(_context, layout, tool):
  323. props = tool.operator_properties("view3d.select_circle")
  324. row = layout.row()
  325. row.use_property_split = False
  326. row.prop(props, "mode", text="", expand=True, icon_only=True)
  327. layout.prop(props, "radius")
  328. def draw_cursor(_context, tool, xy):
  329. from gpu_extras.presets import draw_circle_2d
  330. props = tool.operator_properties("view3d.select_circle")
  331. radius = props.radius
  332. draw_circle_2d(xy, (1.0,) * 4, radius, 32)
  333. return dict(
  334. idname="builtin.select_circle",
  335. label="Select Circle",
  336. icon="ops.generic.select_circle",
  337. widget=None,
  338. keymap="3D View Tool: Select Circle",
  339. draw_settings=draw_settings,
  340. draw_cursor=draw_cursor,
  341. )
  342. # -----------------------------------------------------------------------------
  343. # Object Modes (named based on context.mode)
  344. class _defs_edit_armature:
  345. @ToolDef.from_fn
  346. def roll():
  347. return dict(
  348. idname="builtin.roll",
  349. label="Roll",
  350. icon="ops.armature.bone.roll",
  351. widget=None,
  352. keymap=(),
  353. )
  354. @ToolDef.from_fn
  355. def bone_envelope():
  356. return dict(
  357. idname="builtin.bone_envelope",
  358. label="Bone Envelope",
  359. icon="ops.transform.bone_envelope",
  360. widget=None,
  361. keymap=(),
  362. )
  363. @ToolDef.from_fn
  364. def bone_size():
  365. return dict(
  366. idname="builtin.bone_size",
  367. label="Bone Size",
  368. icon="ops.transform.bone_size",
  369. widget=None,
  370. keymap=(),
  371. )
  372. @ToolDef.from_fn
  373. def extrude():
  374. return dict(
  375. idname="builtin.extrude",
  376. label="Extrude",
  377. icon="ops.armature.extrude_move",
  378. widget="VIEW3D_GGT_xform_extrude",
  379. keymap=(),
  380. draw_settings=_template_widget.VIEW3D_GGT_xform_extrude.draw_settings,
  381. )
  382. @ToolDef.from_fn
  383. def extrude_cursor():
  384. return dict(
  385. idname="builtin.extrude_to_cursor",
  386. label="Extrude to Cursor",
  387. icon="ops.armature.extrude_cursor",
  388. widget=None,
  389. keymap=(),
  390. )
  391. class _defs_edit_mesh:
  392. @ToolDef.from_fn
  393. def cube_add():
  394. return dict(
  395. idname="builtin.add_cube",
  396. label="Add Cube",
  397. icon="ops.mesh.primitive_cube_add_gizmo",
  398. description=(
  399. "Add cube to mesh interactively"
  400. ),
  401. widget=None,
  402. keymap=(),
  403. )
  404. @ToolDef.from_fn
  405. def rip_region():
  406. def draw_settings(_context, layout, tool):
  407. props = tool.operator_properties("mesh.rip_move")
  408. props_macro = props.MESH_OT_rip
  409. layout.prop(props_macro, "use_fill")
  410. return dict(
  411. idname="builtin.rip_region",
  412. label="Rip Region",
  413. icon="ops.mesh.rip",
  414. widget=None,
  415. keymap=(),
  416. draw_settings=draw_settings,
  417. )
  418. @ToolDef.from_fn
  419. def rip_edge():
  420. return dict(
  421. idname="builtin.rip_edge",
  422. label="Rip Edge",
  423. icon="ops.mesh.rip_edge",
  424. widget=None,
  425. keymap=(),
  426. )
  427. @ToolDef.from_fn
  428. def poly_build():
  429. return dict(
  430. idname="builtin.poly_build",
  431. label="Poly Build",
  432. icon="ops.mesh.polybuild_hover",
  433. widget="VIEW3D_GGT_mesh_preselect_elem",
  434. keymap=(),
  435. )
  436. @ToolDef.from_fn
  437. def edge_slide():
  438. def draw_settings(_context, layout, tool):
  439. props = tool.operator_properties("transform.edge_slide")
  440. layout.prop(props, "correct_uv")
  441. return dict(
  442. idname="builtin.edge_slide",
  443. label="Edge Slide",
  444. icon="ops.transform.edge_slide",
  445. widget=None,
  446. keymap=(),
  447. draw_settings=draw_settings,
  448. )
  449. @ToolDef.from_fn
  450. def vert_slide():
  451. def draw_settings(_context, layout, tool):
  452. props = tool.operator_properties("transform.vert_slide")
  453. layout.prop(props, "correct_uv")
  454. return dict(
  455. idname="builtin.vertex_slide",
  456. label="Vertex Slide",
  457. icon="ops.transform.vert_slide",
  458. widget=None,
  459. keymap=(),
  460. draw_settings=draw_settings,
  461. )
  462. @ToolDef.from_fn
  463. def spin():
  464. def draw_settings(_context, layout, tool):
  465. props = tool.operator_properties("mesh.spin")
  466. layout.prop(props, "steps")
  467. props = tool.gizmo_group_properties("MESH_GGT_spin")
  468. layout.prop(props, "axis")
  469. return dict(
  470. idname="builtin.spin",
  471. label="Spin",
  472. icon="ops.mesh.spin",
  473. widget="MESH_GGT_spin",
  474. keymap=(),
  475. draw_settings=draw_settings,
  476. )
  477. @ToolDef.from_fn
  478. def spin_duplicate():
  479. def draw_settings(_context, layout, tool):
  480. props = tool.operator_properties("mesh.spin")
  481. layout.prop(props, "steps")
  482. props = tool.gizmo_group_properties("MESH_GGT_spin")
  483. layout.prop(props, "axis")
  484. return dict(
  485. idname="builtin.spin_duplicates",
  486. label="Spin Duplicates",
  487. icon="ops.mesh.spin.duplicate",
  488. widget="MESH_GGT_spin",
  489. keymap=(),
  490. draw_settings=draw_settings,
  491. )
  492. @ToolDef.from_fn
  493. def inset():
  494. def draw_settings(_context, layout, tool):
  495. props = tool.operator_properties("mesh.inset")
  496. layout.prop(props, "use_outset")
  497. layout.prop(props, "use_individual")
  498. layout.prop(props, "use_even_offset")
  499. layout.prop(props, "use_relative_offset")
  500. return dict(
  501. idname="builtin.inset_faces",
  502. label="Inset Faces",
  503. icon="ops.mesh.inset",
  504. widget=None,
  505. keymap=(),
  506. draw_settings=draw_settings,
  507. )
  508. @ToolDef.from_fn
  509. def bevel():
  510. def draw_settings(_context, layout, tool):
  511. props = tool.operator_properties("mesh.bevel")
  512. layout.prop(props, "offset_type")
  513. layout.prop(props, "segments")
  514. layout.prop(props, "profile", slider=True)
  515. layout.prop(props, "vertex_only")
  516. return dict(
  517. idname="builtin.bevel",
  518. label="Bevel",
  519. icon="ops.mesh.bevel",
  520. widget=None,
  521. keymap=(),
  522. draw_settings=draw_settings,
  523. )
  524. @ToolDef.from_fn
  525. def extrude():
  526. return dict(
  527. idname="builtin.extrude_region",
  528. label="Extrude Region",
  529. # The operator description isn't useful in this case, give our own.
  530. description=(
  531. "Extrude freely or along an axis"
  532. ),
  533. icon="ops.mesh.extrude_region_move",
  534. widget="VIEW3D_GGT_xform_extrude",
  535. # Important to use same operator as 'E' key.
  536. operator="view3d.edit_mesh_extrude_move_normal",
  537. keymap=(),
  538. draw_settings=_template_widget.VIEW3D_GGT_xform_extrude.draw_settings,
  539. )
  540. @ToolDef.from_fn
  541. def extrude_normals():
  542. def draw_settings(_context, layout, tool):
  543. props = tool.operator_properties("mesh.extrude_region_shrink_fatten")
  544. props_macro = props.TRANSFORM_OT_shrink_fatten
  545. layout.prop(props_macro, "use_even_offset")
  546. return dict(
  547. idname="builtin.extrude_along_normals",
  548. label="Extrude Along Normals",
  549. icon="ops.mesh.extrude_region_shrink_fatten",
  550. widget=None,
  551. operator="mesh.extrude_region_shrink_fatten",
  552. keymap=(),
  553. draw_settings=draw_settings,
  554. )
  555. @ToolDef.from_fn
  556. def extrude_individual():
  557. return dict(
  558. idname="builtin.extrude_individual",
  559. label="Extrude Individual",
  560. icon="ops.mesh.extrude_faces_move",
  561. widget=None,
  562. keymap=(),
  563. )
  564. @ToolDef.from_fn
  565. def extrude_cursor():
  566. def draw_settings(_context, layout, tool):
  567. props = tool.operator_properties("mesh.dupli_extrude_cursor")
  568. layout.prop(props, "rotate_source")
  569. return dict(
  570. idname="builtin.extrude_to_cursor",
  571. label="Extrude to Cursor",
  572. icon="ops.mesh.dupli_extrude_cursor",
  573. widget=None,
  574. keymap=(),
  575. draw_settings=draw_settings,
  576. )
  577. @ToolDef.from_fn
  578. def loopcut_slide():
  579. def draw_settings(_context, layout, tool):
  580. props = tool.operator_properties("mesh.loopcut_slide")
  581. props_macro = props.MESH_OT_loopcut
  582. layout.prop(props_macro, "number_cuts")
  583. props_macro = props.TRANSFORM_OT_edge_slide
  584. layout.prop(props_macro, "correct_uv")
  585. return dict(
  586. idname="builtin.loop_cut",
  587. label="Loop Cut",
  588. icon="ops.mesh.loopcut_slide",
  589. widget="VIEW3D_GGT_mesh_preselect_edgering",
  590. keymap=(),
  591. draw_settings=draw_settings,
  592. )
  593. @ToolDef.from_fn
  594. def offset_edge_loops_slide():
  595. return dict(
  596. idname="builtin.offset_edge_loop_cut",
  597. label="Offset Edge Loop Cut",
  598. icon="ops.mesh.offset_edge_loops_slide",
  599. widget=None,
  600. keymap=(),
  601. )
  602. @ToolDef.from_fn
  603. def vertex_smooth():
  604. def draw_settings(_context, layout, tool):
  605. props = tool.operator_properties("mesh.vertices_smooth")
  606. layout.prop(props, "repeat")
  607. return dict(
  608. idname="builtin.smooth",
  609. label="Smooth",
  610. icon="ops.mesh.vertices_smooth",
  611. widget="WM_GGT_value_operator_redo",
  612. keymap=(),
  613. draw_settings=draw_settings,
  614. )
  615. @ToolDef.from_fn
  616. def vertex_randomize():
  617. def draw_settings(_context, layout, tool):
  618. props = tool.operator_properties("transform.vertex_random")
  619. layout.prop(props, "uniform")
  620. layout.prop(props, "normal")
  621. layout.prop(props, "seed")
  622. return dict(
  623. idname="builtin.randomize",
  624. label="Randomize",
  625. icon="ops.transform.vertex_random",
  626. widget="WM_GGT_value_operator_redo",
  627. keymap=(),
  628. draw_settings=draw_settings,
  629. )
  630. @ToolDef.from_fn
  631. def shear():
  632. def draw_settings(context, layout, tool):
  633. props = tool.operator_properties("transform.shear")
  634. layout.label(text="View Axis:")
  635. layout.prop(props, "shear_axis", expand=True)
  636. _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 2)
  637. return dict(
  638. idname="builtin.shear",
  639. label="Shear",
  640. icon="ops.transform.shear",
  641. widget="VIEW3D_GGT_xform_shear",
  642. keymap=(),
  643. draw_settings=draw_settings,
  644. )
  645. @ToolDef.from_fn
  646. def tosphere():
  647. return dict(
  648. idname="builtin.to_sphere",
  649. label="To Sphere",
  650. icon="ops.transform.tosphere",
  651. widget=None,
  652. keymap=(),
  653. )
  654. @ToolDef.from_fn
  655. def shrink_fatten():
  656. def draw_settings(_context, layout, tool):
  657. props = tool.operator_properties("transform.shrink_fatten")
  658. layout.prop(props, "use_even_offset")
  659. return dict(
  660. idname="builtin.shrink_fatten",
  661. label="Shrink/Fatten",
  662. icon="ops.transform.shrink_fatten",
  663. widget=None,
  664. keymap=(),
  665. draw_settings=draw_settings,
  666. )
  667. @ToolDef.from_fn
  668. def push_pull():
  669. return dict(
  670. idname="builtin.push_pull",
  671. label="Push/Pull",
  672. icon="ops.transform.push_pull",
  673. widget=None,
  674. keymap=(),
  675. )
  676. @ToolDef.from_fn
  677. def knife():
  678. def draw_settings(_context, layout, tool):
  679. props = tool.operator_properties("mesh.knife_tool")
  680. layout.prop(props, "use_occlude_geometry")
  681. layout.prop(props, "only_selected")
  682. return dict(
  683. idname="builtin.knife",
  684. label="Knife",
  685. cursor='KNIFE',
  686. icon="ops.mesh.knife_tool",
  687. widget=None,
  688. keymap=(),
  689. draw_settings=draw_settings,
  690. )
  691. @ToolDef.from_fn
  692. def bisect():
  693. def draw_settings(_context, layout, tool):
  694. props = tool.operator_properties("mesh.bisect")
  695. layout.prop(props, "use_fill")
  696. layout.prop(props, "clear_inner")
  697. layout.prop(props, "clear_outer")
  698. layout.prop(props, "threshold")
  699. return dict(
  700. idname="builtin.bisect",
  701. label="Bisect",
  702. icon="ops.mesh.bisect",
  703. widget=None,
  704. keymap=(),
  705. draw_settings=draw_settings,
  706. )
  707. class _defs_edit_curve:
  708. @ToolDef.from_fn
  709. def draw():
  710. def draw_settings(context, layout, _tool):
  711. # Tool settings initialize operator options.
  712. tool_settings = context.tool_settings
  713. cps = tool_settings.curve_paint_settings
  714. col = layout.column()
  715. col.prop(cps, "curve_type")
  716. if cps.curve_type == 'BEZIER':
  717. col.prop(cps, "error_threshold")
  718. col.prop(cps, "fit_method")
  719. col.prop(cps, "use_corners_detect")
  720. col = layout.row()
  721. col.active = cps.use_corners_detect
  722. col.prop(cps, "corner_angle")
  723. return dict(
  724. idname="builtin.draw",
  725. label="Draw",
  726. cursor='PAINT_BRUSH',
  727. icon="ops.curve.draw",
  728. widget=None,
  729. keymap=(),
  730. draw_settings=draw_settings,
  731. )
  732. @ToolDef.from_fn
  733. def extrude():
  734. return dict(
  735. idname="builtin.extrude",
  736. label="Extrude",
  737. icon="ops.curve.extrude_move",
  738. widget="VIEW3D_GGT_xform_extrude",
  739. keymap=(),
  740. draw_settings=_template_widget.VIEW3D_GGT_xform_extrude.draw_settings,
  741. )
  742. @ToolDef.from_fn
  743. def extrude_cursor():
  744. return dict(
  745. idname="builtin.extrude_cursor",
  746. label="Extrude Cursor",
  747. icon="ops.curve.extrude_cursor",
  748. widget=None,
  749. keymap=(),
  750. )
  751. @ToolDef.from_fn
  752. def tilt():
  753. return dict(
  754. idname="builtin.tilt",
  755. label="Tilt",
  756. icon="ops.transform.tilt",
  757. widget=None,
  758. keymap=(),
  759. )
  760. @ToolDef.from_fn
  761. def curve_radius():
  762. return dict(
  763. idname="builtin.radius",
  764. label="Radius",
  765. description=(
  766. "Expand or contract the radius of the selected curve points"
  767. ),
  768. icon="ops.curve.radius",
  769. widget=None,
  770. keymap=(),
  771. )
  772. @ToolDef.from_fn
  773. def curve_vertex_randomize():
  774. def draw_settings(_context, layout, tool):
  775. props = tool.operator_properties("transform.vertex_random")
  776. layout.prop(props, "uniform")
  777. layout.prop(props, "normal")
  778. layout.prop(props, "seed")
  779. return dict(
  780. idname="builtin.randomize",
  781. label="Randomize",
  782. icon="ops.curve.vertex_random",
  783. widget="WM_GGT_value_operator_redo",
  784. keymap=(),
  785. draw_settings=draw_settings,
  786. )
  787. class _defs_pose:
  788. @ToolDef.from_fn
  789. def breakdown():
  790. return dict(
  791. idname="builtin.breakdowner",
  792. label="Breakdowner",
  793. icon="ops.pose.breakdowner",
  794. widget=None,
  795. keymap=(),
  796. )
  797. @ToolDef.from_fn
  798. def push():
  799. return dict(
  800. idname="builtin.push",
  801. label="Push",
  802. icon="ops.pose.push",
  803. widget=None,
  804. keymap=(),
  805. )
  806. @ToolDef.from_fn
  807. def relax():
  808. return dict(
  809. idname="builtin.relax",
  810. label="Relax",
  811. icon="ops.pose.relax",
  812. widget=None,
  813. keymap=(),
  814. )
  815. class _defs_particle:
  816. @staticmethod
  817. def generate_from_brushes(context):
  818. return generate_from_enum_ex(
  819. context,
  820. idname_prefix="builtin_brush.",
  821. icon_prefix="brush.particle.",
  822. type=bpy.types.ParticleEdit,
  823. attr="tool",
  824. )
  825. class _defs_sculpt:
  826. @staticmethod
  827. def generate_from_brushes(context):
  828. return generate_from_enum_ex(
  829. context,
  830. idname_prefix="builtin_brush.",
  831. icon_prefix="brush.sculpt.",
  832. type=bpy.types.Brush,
  833. attr="sculpt_tool",
  834. )
  835. @ToolDef.from_fn
  836. def hide_border():
  837. return dict(
  838. idname="builtin.box_hide",
  839. label="Box Hide",
  840. icon="ops.sculpt.border_hide",
  841. widget=None,
  842. keymap=(),
  843. )
  844. @ToolDef.from_fn
  845. def mask_border():
  846. return dict(
  847. idname="builtin.box_mask",
  848. label="Box Mask",
  849. icon="ops.sculpt.border_mask",
  850. widget=None,
  851. keymap=(),
  852. )
  853. @ToolDef.from_fn
  854. def mask_lasso():
  855. return dict(
  856. idname="builtin.lasso_mask",
  857. label="Lasso Mask",
  858. icon="ops.sculpt.lasso_mask",
  859. widget=None,
  860. keymap=(),
  861. )
  862. class _defs_vertex_paint:
  863. @staticmethod
  864. def poll_select_mask(context):
  865. if context is None:
  866. return True
  867. ob = context.active_object
  868. return (ob and ob.type == 'MESH' and
  869. (ob.data.use_paint_mask or
  870. ob.data.use_paint_mask_vertex))
  871. @staticmethod
  872. def generate_from_brushes(context):
  873. return generate_from_enum_ex(
  874. context,
  875. idname_prefix="builtin_brush.",
  876. icon_prefix="brush.paint_vertex.",
  877. type=bpy.types.Brush,
  878. attr="vertex_tool",
  879. )
  880. class _defs_texture_paint:
  881. @staticmethod
  882. def poll_select_mask(context):
  883. if context is None:
  884. return True
  885. ob = context.active_object
  886. return (ob and ob.type == 'MESH' and
  887. (ob.data.use_paint_mask))
  888. @staticmethod
  889. def generate_from_brushes(context):
  890. return generate_from_enum_ex(
  891. context,
  892. idname_prefix="builtin_brush.",
  893. icon_prefix="brush.paint_texture.",
  894. type=bpy.types.Brush,
  895. attr="image_tool",
  896. )
  897. class _defs_weight_paint:
  898. @staticmethod
  899. def poll_select_mask(context):
  900. if context is None:
  901. return True
  902. ob = context.active_object
  903. return (ob and ob.type == 'MESH' and
  904. (ob.data.use_paint_mask or
  905. ob.data.use_paint_mask_vertex))
  906. @staticmethod
  907. def generate_from_brushes(context):
  908. return generate_from_enum_ex(
  909. context,
  910. idname_prefix="builtin_brush.",
  911. icon_prefix="brush.paint_weight.",
  912. type=bpy.types.Brush,
  913. attr="weight_tool",
  914. )
  915. @ToolDef.from_fn
  916. def sample_weight():
  917. return dict(
  918. idname="builtin.sample_weight",
  919. label="Sample Weight",
  920. icon="ops.paint.weight_sample",
  921. widget=None,
  922. keymap=(),
  923. )
  924. @ToolDef.from_fn
  925. def sample_weight_group():
  926. return dict(
  927. idname="builtin.sample_vertex_group",
  928. label="Sample Vertex Group",
  929. icon="ops.paint.weight_sample_group",
  930. widget=None,
  931. keymap=(),
  932. )
  933. @ToolDef.from_fn
  934. def gradient():
  935. def draw_settings(context, layout, tool):
  936. brush = context.tool_settings.weight_paint.brush
  937. if brush is not None:
  938. from bl_ui.properties_paint_common import UnifiedPaintPanel
  939. UnifiedPaintPanel.prop_unified_weight(layout, context, brush, "weight", slider=True)
  940. UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength", slider=True)
  941. props = tool.operator_properties("paint.weight_gradient")
  942. layout.prop(props, "type")
  943. return dict(
  944. idname="builtin.gradient",
  945. label="Gradient",
  946. icon="ops.paint.weight_gradient",
  947. widget=None,
  948. keymap=(),
  949. draw_settings=draw_settings,
  950. )
  951. class _defs_image_generic:
  952. @staticmethod
  953. def poll_uvedit(context):
  954. if context is None:
  955. return True
  956. ob = context.edit_object
  957. if ob is not None:
  958. data = ob.data
  959. if data is not None:
  960. return bool(getattr(data, "uv_layers", False))
  961. return False
  962. @ToolDef.from_fn
  963. def cursor():
  964. return dict(
  965. idname="builtin.cursor",
  966. label="Cursor",
  967. description=(
  968. "Set the cursor location, drag to transform"
  969. ),
  970. icon="ops.generic.cursor",
  971. keymap=(),
  972. )
  973. # Currently a place holder so we can switch away from the annotation tool.
  974. # Falls back to default image editor action.
  975. @ToolDef.from_fn
  976. def sample():
  977. def draw_settings(_context, layout, tool):
  978. props = tool.operator_properties("image.sample")
  979. layout.prop(props, "size")
  980. return dict(
  981. idname="builtin.sample",
  982. label="Sample",
  983. description=(
  984. "Sample pixel values under the cursor"
  985. ),
  986. icon="ops.paint.weight_sample", # XXX, needs own icon.
  987. keymap="Image Editor Tool: Sample",
  988. draw_settings=draw_settings,
  989. )
  990. class _defs_image_uv_transform:
  991. @ToolDef.from_fn
  992. def translate():
  993. return dict(
  994. idname="builtin.move",
  995. label="Move",
  996. icon="ops.transform.translate",
  997. # widget="VIEW3D_GGT_xform_gizmo",
  998. operator="transform.translate",
  999. keymap="Image Editor Tool: Uv, Move",
  1000. )
  1001. @ToolDef.from_fn
  1002. def rotate():
  1003. return dict(
  1004. idname="builtin.rotate",
  1005. label="Rotate",
  1006. icon="ops.transform.rotate",
  1007. # widget="VIEW3D_GGT_xform_gizmo",
  1008. operator="transform.rotate",
  1009. keymap="Image Editor Tool: Uv, Rotate",
  1010. )
  1011. @ToolDef.from_fn
  1012. def scale():
  1013. return dict(
  1014. idname="builtin.scale",
  1015. label="Scale",
  1016. icon="ops.transform.resize",
  1017. # widget="VIEW3D_GGT_xform_gizmo",
  1018. operator="transform.resize",
  1019. keymap="Image Editor Tool: Uv, Scale",
  1020. )
  1021. @ToolDef.from_fn
  1022. def transform():
  1023. return dict(
  1024. idname="builtin.transform",
  1025. label="Transform",
  1026. description=(
  1027. "Supports any combination of grab, rotate & scale at once"
  1028. ),
  1029. icon="ops.transform.transform",
  1030. widget="IMAGE_GGT_gizmo2d",
  1031. # No keymap default action, only for gizmo!
  1032. )
  1033. class _defs_image_uv_select:
  1034. @ToolDef.from_fn
  1035. def select():
  1036. def draw_settings(_context, _layout, _tool):
  1037. pass
  1038. return dict(
  1039. idname="builtin.select",
  1040. label="Select",
  1041. icon="ops.generic.select",
  1042. widget=None,
  1043. keymap=(),
  1044. draw_settings=draw_settings,
  1045. )
  1046. @ToolDef.from_fn
  1047. def box():
  1048. def draw_settings(_context, layout, tool):
  1049. props = tool.operator_properties("uv.select_box")
  1050. row = layout.row()
  1051. row.use_property_split = False
  1052. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1053. return dict(
  1054. idname="builtin.select_box",
  1055. label="Select Box",
  1056. icon="ops.generic.select_box",
  1057. widget=None,
  1058. keymap=(),
  1059. draw_settings=draw_settings,
  1060. )
  1061. @ToolDef.from_fn
  1062. def lasso():
  1063. def draw_settings(_context, layout, tool):
  1064. props = tool.operator_properties("uv.select_lasso")
  1065. row = layout.row()
  1066. row.use_property_split = False
  1067. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1068. return dict(
  1069. idname="builtin.select_lasso",
  1070. label="Select Lasso",
  1071. icon="ops.generic.select_lasso",
  1072. widget=None,
  1073. keymap=(),
  1074. draw_settings=draw_settings,
  1075. )
  1076. @ToolDef.from_fn
  1077. def circle():
  1078. def draw_settings(_context, layout, tool):
  1079. props = tool.operator_properties("uv.select_circle")
  1080. row = layout.row()
  1081. row.use_property_split = False
  1082. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1083. layout.prop(props, "radius")
  1084. def draw_cursor(_context, tool, xy):
  1085. from gpu_extras.presets import draw_circle_2d
  1086. props = tool.operator_properties("uv.select_circle")
  1087. radius = props.radius
  1088. draw_circle_2d(xy, (1.0,) * 4, radius, 32)
  1089. return dict(
  1090. idname="builtin.select_circle",
  1091. label="Select Circle",
  1092. icon="ops.generic.select_circle",
  1093. widget=None,
  1094. keymap=(),
  1095. draw_settings=draw_settings,
  1096. draw_cursor=draw_cursor,
  1097. )
  1098. class _defs_image_uv_sculpt:
  1099. @staticmethod
  1100. def generate_from_brushes(context):
  1101. def draw_cursor(context, _tool, xy):
  1102. from gpu_extras.presets import draw_circle_2d
  1103. tool_settings = context.tool_settings
  1104. uv_sculpt = tool_settings.uv_sculpt
  1105. if not uv_sculpt.show_brush:
  1106. return
  1107. ups = tool_settings.unified_paint_settings
  1108. if ups.use_unified_size:
  1109. radius = ups.size
  1110. else:
  1111. brush = tool_settings.uv_sculpt.brush
  1112. if brush is None:
  1113. return
  1114. radius = brush.size
  1115. draw_circle_2d(xy, (1.0,) * 4, radius, 32)
  1116. return generate_from_enum_ex(
  1117. context,
  1118. idname_prefix="builtin_brush.",
  1119. icon_prefix="brush.uv_sculpt.",
  1120. type=bpy.types.Brush,
  1121. attr="uv_sculpt_tool",
  1122. tooldef_keywords=dict(
  1123. operator="sculpt.uv_sculpt_stroke",
  1124. keymap="Image Editor Tool: Uv, Sculpt Stroke",
  1125. draw_cursor=draw_cursor,
  1126. ),
  1127. )
  1128. class _defs_gpencil_paint:
  1129. @staticmethod
  1130. def generate_from_brushes(context):
  1131. return generate_from_enum_ex(
  1132. context,
  1133. idname_prefix="builtin_brush.",
  1134. icon_prefix="brush.gpencil_draw.",
  1135. type=bpy.types.Brush,
  1136. attr="gpencil_tool",
  1137. tooldef_keywords=dict(
  1138. operator="gpencil.draw",
  1139. ),
  1140. )
  1141. @ToolDef.from_fn
  1142. def cutter():
  1143. return dict(
  1144. idname="builtin.cutter",
  1145. label="Cutter",
  1146. icon="ops.gpencil.stroke_cutter",
  1147. cursor='KNIFE',
  1148. widget=None,
  1149. keymap=(),
  1150. )
  1151. @ToolDef.from_fn
  1152. def line():
  1153. return dict(
  1154. idname="builtin.line",
  1155. label="Line",
  1156. icon="ops.gpencil.primitive_line",
  1157. cursor='CROSSHAIR',
  1158. widget=None,
  1159. keymap=(),
  1160. )
  1161. @ToolDef.from_fn
  1162. def box():
  1163. return dict(
  1164. idname="builtin.box",
  1165. label="Box",
  1166. icon="ops.gpencil.primitive_box",
  1167. cursor='CROSSHAIR',
  1168. widget=None,
  1169. keymap=(),
  1170. )
  1171. @ToolDef.from_fn
  1172. def circle():
  1173. return dict(
  1174. idname="builtin.circle",
  1175. label="Circle",
  1176. icon="ops.gpencil.primitive_circle",
  1177. cursor='CROSSHAIR',
  1178. widget=None,
  1179. keymap=(),
  1180. )
  1181. @ToolDef.from_fn
  1182. def arc():
  1183. return dict(
  1184. idname="builtin.arc",
  1185. label="Arc",
  1186. icon="ops.gpencil.primitive_arc",
  1187. cursor='CROSSHAIR',
  1188. widget=None,
  1189. keymap=(),
  1190. )
  1191. @ToolDef.from_fn
  1192. def curve():
  1193. return dict(
  1194. idname="builtin.curve",
  1195. label="Curve",
  1196. icon="ops.gpencil.primitive_curve",
  1197. cursor='CROSSHAIR',
  1198. widget=None,
  1199. keymap=(),
  1200. )
  1201. class _defs_gpencil_edit:
  1202. @ToolDef.from_fn
  1203. def bend():
  1204. return dict(
  1205. idname="builtin.bend",
  1206. label="Bend",
  1207. icon="ops.gpencil.edit_bend",
  1208. widget=None,
  1209. keymap=(),
  1210. )
  1211. @ToolDef.from_fn
  1212. def select():
  1213. def draw_settings(context, layout, _tool):
  1214. layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
  1215. return dict(
  1216. idname="builtin.select",
  1217. label="Select",
  1218. icon="ops.generic.select",
  1219. widget=None,
  1220. keymap=(),
  1221. draw_settings=draw_settings,
  1222. )
  1223. @ToolDef.from_fn
  1224. def box_select():
  1225. def draw_settings(context, layout, tool):
  1226. props = tool.operator_properties("gpencil.select_box")
  1227. row = layout.row()
  1228. row.use_property_split = False
  1229. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1230. layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
  1231. return dict(
  1232. idname="builtin.select_box",
  1233. label="Select Box",
  1234. icon="ops.generic.select_box",
  1235. widget=None,
  1236. keymap=(),
  1237. draw_settings=draw_settings,
  1238. )
  1239. @ToolDef.from_fn
  1240. def lasso_select():
  1241. def draw_settings(context, layout, tool):
  1242. props = tool.operator_properties("gpencil.select_lasso")
  1243. row = layout.row()
  1244. row.use_property_split = False
  1245. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1246. layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
  1247. return dict(
  1248. idname="builtin.select_lasso",
  1249. label="Select Lasso",
  1250. icon="ops.generic.select_lasso",
  1251. widget=None,
  1252. keymap=(),
  1253. draw_settings=draw_settings,
  1254. )
  1255. @ToolDef.from_fn
  1256. def circle_select():
  1257. def draw_settings(context, layout, tool):
  1258. props = tool.operator_properties("gpencil.select_circle")
  1259. row = layout.row()
  1260. row.use_property_split = False
  1261. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1262. layout.prop(props, "radius")
  1263. layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
  1264. def draw_cursor(_context, tool, xy):
  1265. from gpu_extras.presets import draw_circle_2d
  1266. props = tool.operator_properties("gpencil.select_circle")
  1267. radius = props.radius
  1268. draw_circle_2d(xy, (1.0,) * 4, radius, 32)
  1269. return dict(
  1270. idname="builtin.select_circle",
  1271. label="Select Circle",
  1272. icon="ops.generic.select_circle",
  1273. widget=None,
  1274. keymap=(),
  1275. draw_settings=draw_settings,
  1276. draw_cursor=draw_cursor,
  1277. )
  1278. @ToolDef.from_fn
  1279. def radius():
  1280. return dict(
  1281. idname="builtin.radius",
  1282. label="Radius",
  1283. description=(
  1284. "Expand or contract the radius of the selected points"
  1285. ),
  1286. icon="ops.gpencil.radius",
  1287. widget=None,
  1288. keymap=(),
  1289. )
  1290. @ToolDef.from_fn
  1291. def shear():
  1292. return dict(
  1293. idname="builtin.shear",
  1294. label="Shear",
  1295. icon="ops.gpencil.edit_shear",
  1296. widget=None,
  1297. keymap=(),
  1298. )
  1299. @ToolDef.from_fn
  1300. def tosphere():
  1301. return dict(
  1302. idname="builtin.to_sphere",
  1303. label="To Sphere",
  1304. icon="ops.transform.tosphere",
  1305. widget=None,
  1306. keymap=(),
  1307. )
  1308. @ToolDef.from_fn
  1309. def extrude():
  1310. return dict(
  1311. idname="builtin.extrude",
  1312. label="Extrude",
  1313. icon="ops.gpencil.extrude_move",
  1314. widget="VIEW3D_GGT_xform_extrude",
  1315. keymap=(),
  1316. draw_settings=_template_widget.VIEW3D_GGT_xform_extrude.draw_settings,
  1317. )
  1318. class _defs_gpencil_sculpt:
  1319. @staticmethod
  1320. def generate_from_brushes(context):
  1321. return generate_from_enum_ex(
  1322. context,
  1323. idname_prefix="builtin_brush.",
  1324. icon_prefix="ops.gpencil.sculpt_",
  1325. type=bpy.types.GPencilSculptSettings,
  1326. attr="sculpt_tool",
  1327. tooldef_keywords=dict(
  1328. operator="gpencil.sculpt_paint",
  1329. keymap="3D View Tool: Sculpt Gpencil, Paint",
  1330. ),
  1331. )
  1332. class _defs_gpencil_weight:
  1333. @staticmethod
  1334. def generate_from_brushes(context):
  1335. return generate_from_enum_ex(
  1336. context,
  1337. idname_prefix="builtin_brush.",
  1338. icon_prefix="ops.gpencil.sculpt_",
  1339. type=bpy.types.GPencilSculptSettings,
  1340. attr="weight_tool",
  1341. tooldef_keywords=dict(
  1342. operator="gpencil.sculpt_paint",
  1343. keymap="3D View Tool: Sculpt Gpencil, Paint",
  1344. ),
  1345. )
  1346. class _defs_node_select:
  1347. @ToolDef.from_fn
  1348. def select():
  1349. def draw_settings(_context, _layout, _tool):
  1350. pass
  1351. return dict(
  1352. idname="builtin.select",
  1353. label="Select",
  1354. icon="ops.generic.select",
  1355. widget=None,
  1356. keymap="Node Tool: Select",
  1357. draw_settings=draw_settings,
  1358. )
  1359. @ToolDef.from_fn
  1360. def box():
  1361. def draw_settings(_context, layout, tool):
  1362. props = tool.operator_properties("node.select_box")
  1363. row = layout.row()
  1364. row.use_property_split = False
  1365. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1366. pass
  1367. return dict(
  1368. idname="builtin.select_box",
  1369. label="Select Box",
  1370. icon="ops.generic.select_box",
  1371. widget=None,
  1372. keymap="Node Tool: Select Box",
  1373. draw_settings=draw_settings,
  1374. )
  1375. @ToolDef.from_fn
  1376. def lasso():
  1377. def draw_settings(_context, layout, tool):
  1378. props = tool.operator_properties("node.select_lasso")
  1379. row = layout.row()
  1380. row.use_property_split = False
  1381. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1382. return dict(
  1383. idname="builtin.select_lasso",
  1384. label="Select Lasso",
  1385. icon="ops.generic.select_lasso",
  1386. widget=None,
  1387. keymap="Node Tool: Select Lasso",
  1388. draw_settings=draw_settings,
  1389. )
  1390. @ToolDef.from_fn
  1391. def circle():
  1392. def draw_settings(_context, layout, tool):
  1393. props = tool.operator_properties("node.select_circle")
  1394. row = layout.row()
  1395. row.use_property_split = False
  1396. row.prop(props, "mode", text="", expand=True, icon_only=True)
  1397. layout.prop(props, "radius")
  1398. def draw_cursor(_context, tool, xy):
  1399. from gpu_extras.presets import draw_circle_2d
  1400. props = tool.operator_properties("node.select_circle")
  1401. radius = props.radius
  1402. draw_circle_2d(xy, (1.0,) * 4, radius, 32)
  1403. return dict(
  1404. idname="builtin.select_circle",
  1405. label="Select Circle",
  1406. icon="ops.generic.select_circle",
  1407. widget=None,
  1408. keymap="Node Tool: Select Circle",
  1409. draw_settings=draw_settings,
  1410. draw_cursor=draw_cursor,
  1411. )
  1412. class _defs_node_edit:
  1413. @ToolDef.from_fn
  1414. def links_cut():
  1415. return dict(
  1416. idname="builtin.links_cut",
  1417. label="Links Cut",
  1418. icon="ops.node.links_cut",
  1419. widget=None,
  1420. keymap="Node Tool: Links Cut",
  1421. )
  1422. class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
  1423. bl_space_type = 'IMAGE_EDITOR'
  1424. bl_region_type = 'TOOLS'
  1425. bl_label = "Tools" # not visible
  1426. bl_options = {'HIDE_HEADER'}
  1427. # Satisfy the 'ToolSelectPanelHelper' API.
  1428. keymap_prefix = "Image Editor Tool:"
  1429. @classmethod
  1430. def tools_from_context(cls, context, mode=None):
  1431. if mode is None:
  1432. if context.space_data is None:
  1433. mode = 'VIEW'
  1434. else:
  1435. mode = context.space_data.mode
  1436. for tools in (cls._tools[None], cls._tools.get(mode, ())):
  1437. for item in tools:
  1438. if not (type(item) is ToolDef) and callable(item):
  1439. yield from item(context)
  1440. else:
  1441. yield item
  1442. @classmethod
  1443. def tools_all(cls):
  1444. yield from cls._tools.items()
  1445. # for reuse
  1446. _tools_transform = (
  1447. _defs_image_uv_transform.translate,
  1448. _defs_image_uv_transform.rotate,
  1449. _defs_image_uv_transform.scale,
  1450. _defs_image_uv_transform.transform,
  1451. )
  1452. _tools_select = (
  1453. (
  1454. _defs_image_uv_select.select,
  1455. _defs_image_uv_select.box,
  1456. _defs_image_uv_select.circle,
  1457. _defs_image_uv_select.lasso,
  1458. ),
  1459. )
  1460. _tools_annotate = (
  1461. (
  1462. _defs_annotate.scribble,
  1463. _defs_annotate.line,
  1464. _defs_annotate.poly,
  1465. _defs_annotate.eraser,
  1466. ),
  1467. )
  1468. _tools = {
  1469. None: [
  1470. # for all modes
  1471. ],
  1472. 'VIEW': [
  1473. _defs_image_generic.sample,
  1474. *_tools_annotate,
  1475. ],
  1476. 'UV': [
  1477. *_tools_select,
  1478. _defs_image_generic.cursor,
  1479. None,
  1480. *_tools_transform,
  1481. None,
  1482. *_tools_annotate,
  1483. None,
  1484. lambda context: (
  1485. _defs_image_uv_sculpt.generate_from_brushes(context)
  1486. if _defs_image_generic.poll_uvedit(context)
  1487. else ()
  1488. ),
  1489. ],
  1490. 'MASK': [
  1491. None,
  1492. ],
  1493. 'PAINT': [
  1494. _defs_texture_paint.generate_from_brushes,
  1495. ],
  1496. }
  1497. class NODE_PT_tools_active(ToolSelectPanelHelper, Panel):
  1498. bl_space_type = 'NODE_EDITOR'
  1499. bl_region_type = 'TOOLS'
  1500. bl_label = "Tools" # not visible
  1501. bl_options = {'HIDE_HEADER'}
  1502. # Satisfy the 'ToolSelectPanelHelper' API.
  1503. keymap_prefix = "Node Editor Tool:"
  1504. @classmethod
  1505. def tools_from_context(cls, context, mode=None):
  1506. if mode is None:
  1507. if context.space_data is None:
  1508. mode = None
  1509. else:
  1510. mode = context.space_data.tree_type
  1511. for tools in (cls._tools[None], cls._tools.get(mode, ())):
  1512. for item in tools:
  1513. if not (type(item) is ToolDef) and callable(item):
  1514. yield from item(context)
  1515. else:
  1516. yield item
  1517. @classmethod
  1518. def tools_all(cls):
  1519. yield from cls._tools.items()
  1520. _tools_select = (
  1521. (
  1522. _defs_node_select.select,
  1523. _defs_node_select.box,
  1524. _defs_node_select.lasso,
  1525. _defs_node_select.circle,
  1526. ),
  1527. )
  1528. _tools_annotate = (
  1529. (
  1530. _defs_annotate.scribble,
  1531. _defs_annotate.line,
  1532. _defs_annotate.poly,
  1533. _defs_annotate.eraser,
  1534. ),
  1535. )
  1536. _tools = {
  1537. None: [
  1538. *_tools_select,
  1539. None,
  1540. *_tools_annotate,
  1541. None,
  1542. _defs_node_edit.links_cut,
  1543. ],
  1544. }
  1545. class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
  1546. bl_space_type = 'VIEW_3D'
  1547. bl_region_type = 'TOOLS'
  1548. bl_label = "Tools" # not visible
  1549. bl_options = {'HIDE_HEADER'}
  1550. # Satisfy the 'ToolSelectPanelHelper' API.
  1551. keymap_prefix = "3D View Tool:"
  1552. @classmethod
  1553. def tools_from_context(cls, context, mode=None):
  1554. if mode is None:
  1555. mode = context.mode
  1556. for tools in (cls._tools[None], cls._tools.get(mode, ())):
  1557. for item in tools:
  1558. if not (type(item) is ToolDef) and callable(item):
  1559. yield from item(context)
  1560. else:
  1561. yield item
  1562. @classmethod
  1563. def tools_all(cls):
  1564. yield from cls._tools.items()
  1565. # for reuse
  1566. _tools_transform = (
  1567. _defs_transform.translate,
  1568. _defs_transform.rotate,
  1569. (
  1570. _defs_transform.scale,
  1571. _defs_transform.scale_cage,
  1572. ),
  1573. _defs_transform.transform,
  1574. )
  1575. _tools_select = (
  1576. (
  1577. _defs_view3d_select.select,
  1578. _defs_view3d_select.box,
  1579. _defs_view3d_select.circle,
  1580. _defs_view3d_select.lasso,
  1581. ),
  1582. )
  1583. _tools_annotate = (
  1584. (
  1585. _defs_annotate.scribble,
  1586. _defs_annotate.line,
  1587. _defs_annotate.poly,
  1588. _defs_annotate.eraser,
  1589. ),
  1590. )
  1591. _tools_gpencil_select = (
  1592. (
  1593. _defs_gpencil_edit.select,
  1594. _defs_gpencil_edit.box_select,
  1595. _defs_gpencil_edit.circle_select,
  1596. _defs_gpencil_edit.lasso_select,
  1597. ),
  1598. )
  1599. _tools_default = (
  1600. *_tools_select,
  1601. _defs_view3d_generic.cursor,
  1602. None,
  1603. *_tools_transform,
  1604. None,
  1605. *_tools_annotate,
  1606. _defs_view3d_generic.ruler,
  1607. )
  1608. _tools = {
  1609. None: [
  1610. # Don't use this! because of paint modes.
  1611. # _defs_view3d_generic.cursor,
  1612. # End group.
  1613. ],
  1614. 'OBJECT': [
  1615. *_tools_default,
  1616. ],
  1617. 'POSE': [
  1618. *_tools_default,
  1619. None,
  1620. (
  1621. _defs_pose.breakdown,
  1622. _defs_pose.push,
  1623. _defs_pose.relax,
  1624. ),
  1625. ],
  1626. 'EDIT_ARMATURE': [
  1627. *_tools_default,
  1628. None,
  1629. _defs_edit_armature.roll,
  1630. (
  1631. _defs_edit_armature.bone_size,
  1632. _defs_edit_armature.bone_envelope,
  1633. ),
  1634. None,
  1635. (
  1636. _defs_edit_armature.extrude,
  1637. _defs_edit_armature.extrude_cursor,
  1638. ),
  1639. ],
  1640. 'EDIT_MESH': [
  1641. *_tools_default,
  1642. None,
  1643. (
  1644. _defs_edit_mesh.extrude,
  1645. _defs_edit_mesh.extrude_normals,
  1646. _defs_edit_mesh.extrude_individual,
  1647. _defs_edit_mesh.extrude_cursor,
  1648. ),
  1649. _defs_edit_mesh.inset,
  1650. _defs_edit_mesh.bevel,
  1651. (
  1652. _defs_edit_mesh.loopcut_slide,
  1653. _defs_edit_mesh.offset_edge_loops_slide,
  1654. ),
  1655. (
  1656. _defs_edit_mesh.knife,
  1657. _defs_edit_mesh.bisect,
  1658. ),
  1659. _defs_edit_mesh.poly_build,
  1660. (
  1661. _defs_edit_mesh.spin,
  1662. _defs_edit_mesh.spin_duplicate,
  1663. ),
  1664. (
  1665. _defs_edit_mesh.vertex_smooth,
  1666. _defs_edit_mesh.vertex_randomize,
  1667. ),
  1668. (
  1669. _defs_edit_mesh.edge_slide,
  1670. _defs_edit_mesh.vert_slide,
  1671. ),
  1672. (
  1673. _defs_edit_mesh.shrink_fatten,
  1674. _defs_edit_mesh.push_pull,
  1675. ),
  1676. (
  1677. _defs_edit_mesh.shear,
  1678. _defs_edit_mesh.tosphere,
  1679. ),
  1680. (
  1681. _defs_edit_mesh.rip_region,
  1682. _defs_edit_mesh.rip_edge,
  1683. ),
  1684. ],
  1685. 'EDIT_CURVE': [
  1686. *_tools_default,
  1687. None,
  1688. _defs_edit_curve.draw,
  1689. (
  1690. _defs_edit_curve.extrude,
  1691. _defs_edit_curve.extrude_cursor,
  1692. ),
  1693. None,
  1694. _defs_edit_curve.curve_radius,
  1695. _defs_edit_curve.tilt,
  1696. None,
  1697. _defs_edit_curve.curve_vertex_randomize,
  1698. ],
  1699. 'EDIT_SURFACE': [
  1700. *_tools_default,
  1701. ],
  1702. 'EDIT_METABALL': [
  1703. *_tools_default,
  1704. ],
  1705. 'EDIT_LATTICE': [
  1706. *_tools_default,
  1707. ],
  1708. 'EDIT_TEXT': [
  1709. _defs_view3d_generic.cursor,
  1710. None,
  1711. *_tools_annotate,
  1712. _defs_view3d_generic.ruler,
  1713. ],
  1714. 'PARTICLE': [
  1715. *_tools_select,
  1716. _defs_view3d_generic.cursor,
  1717. None,
  1718. _defs_particle.generate_from_brushes,
  1719. ],
  1720. 'SCULPT': [
  1721. _defs_sculpt.generate_from_brushes,
  1722. None,
  1723. (
  1724. _defs_sculpt.mask_border,
  1725. _defs_sculpt.mask_lasso,
  1726. ),
  1727. _defs_sculpt.hide_border,
  1728. None,
  1729. *_tools_annotate,
  1730. ],
  1731. 'PAINT_TEXTURE': [
  1732. _defs_texture_paint.generate_from_brushes,
  1733. None,
  1734. lambda context: (
  1735. VIEW3D_PT_tools_active._tools_select
  1736. if _defs_texture_paint.poll_select_mask(context)
  1737. else ()
  1738. ),
  1739. *_tools_annotate,
  1740. ],
  1741. 'PAINT_VERTEX': [
  1742. _defs_vertex_paint.generate_from_brushes,
  1743. None,
  1744. lambda context: (
  1745. VIEW3D_PT_tools_active._tools_select
  1746. if _defs_vertex_paint.poll_select_mask(context)
  1747. else ()
  1748. ),
  1749. *_tools_annotate,
  1750. ],
  1751. 'PAINT_WEIGHT': [
  1752. _defs_weight_paint.generate_from_brushes,
  1753. _defs_weight_paint.gradient,
  1754. None,
  1755. (
  1756. _defs_weight_paint.sample_weight,
  1757. _defs_weight_paint.sample_weight_group,
  1758. ),
  1759. None,
  1760. lambda context: (
  1761. (_defs_view3d_generic.cursor,)
  1762. if context is None or context.pose_object
  1763. else ()
  1764. ),
  1765. None,
  1766. lambda context: (
  1767. VIEW3D_PT_tools_active._tools_select
  1768. if _defs_weight_paint.poll_select_mask(context)
  1769. else ()
  1770. ),
  1771. *_tools_annotate,
  1772. ],
  1773. 'PAINT_GPENCIL': [
  1774. _defs_view3d_generic.cursor,
  1775. None,
  1776. _defs_gpencil_paint.generate_from_brushes,
  1777. _defs_gpencil_paint.cutter,
  1778. None,
  1779. _defs_gpencil_paint.line,
  1780. _defs_gpencil_paint.arc,
  1781. _defs_gpencil_paint.curve,
  1782. _defs_gpencil_paint.box,
  1783. _defs_gpencil_paint.circle,
  1784. ],
  1785. 'EDIT_GPENCIL': [
  1786. *_tools_gpencil_select,
  1787. _defs_view3d_generic.cursor,
  1788. None,
  1789. *_tools_transform,
  1790. None,
  1791. _defs_gpencil_edit.extrude,
  1792. _defs_gpencil_edit.radius,
  1793. _defs_gpencil_edit.bend,
  1794. (
  1795. _defs_gpencil_edit.shear,
  1796. _defs_gpencil_edit.tosphere,
  1797. ),
  1798. ],
  1799. 'SCULPT_GPENCIL': [
  1800. *_tools_gpencil_select,
  1801. None,
  1802. _defs_gpencil_sculpt.generate_from_brushes,
  1803. ],
  1804. 'WEIGHT_GPENCIL': [
  1805. _defs_gpencil_weight.generate_from_brushes,
  1806. ],
  1807. }
  1808. classes = (
  1809. IMAGE_PT_tools_active,
  1810. NODE_PT_tools_active,
  1811. VIEW3D_PT_tools_active,
  1812. )
  1813. if __name__ == "__main__": # only for live edit.
  1814. from bpy.utils import register_class
  1815. for cls in classes:
  1816. register_class(cls)