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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts')
m---------release/scripts/addons0
m---------release/scripts/addons_contrib0
-rw-r--r--release/scripts/freestyle/modules/parameter_editor.py15
-rw-r--r--release/scripts/modules/addon_utils.py37
-rw-r--r--release/scripts/modules/bl_i18n_utils/bl_extract_messages.py2
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py2
-rw-r--r--release/scripts/modules/bl_previews_utils/bl_previews_render.py147
-rw-r--r--release/scripts/modules/bpy/__init__.py1
-rw-r--r--release/scripts/modules/bpy/ops.py15
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py67
-rw-r--r--release/scripts/modules/bpy_extras/__init__.py1
-rw-r--r--release/scripts/modules/bpy_extras/io_utils.py22
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils.py9
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils_experimental.py244
-rw-r--r--release/scripts/modules/bpy_extras/node_utils.py32
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py83
-rw-r--r--release/scripts/modules/bpy_types.py234
-rw-r--r--release/scripts/modules/keyingsets_utils.py6
-rw-r--r--release/scripts/modules/rna_prop_ui.py9
-rw-r--r--release/scripts/modules/sys_info.py13
-rw-r--r--release/scripts/presets/interface_theme/24x_blues.xml2
-rw-r--r--release/scripts/presets/interface_theme/back_to_black.xml2
-rw-r--r--release/scripts/presets/interface_theme/blender_24x.xml2
-rw-r--r--release/scripts/presets/interface_theme/blender_27x.xml1242
-rw-r--r--release/scripts/presets/interface_theme/dark_blue_gradient.xml2
-rw-r--r--release/scripts/presets/interface_theme/default++.xml2
-rw-r--r--release/scripts/presets/interface_theme/elsyiun.xml2
-rw-r--r--release/scripts/presets/interface_theme/flatty_light.xml272
-rw-r--r--release/scripts/presets/interface_theme/graph.xml2
-rw-r--r--release/scripts/presets/interface_theme/hexagon.xml2
-rw-r--r--release/scripts/presets/interface_theme/modern_minimalist.xml2
-rw-r--r--release/scripts/presets/interface_theme/north.xml2
-rw-r--r--release/scripts/presets/interface_theme/rtheme.xml2
-rw-r--r--release/scripts/presets/interface_theme/sandyslate.xml2
-rw-r--r--release/scripts/presets/interface_theme/science_lab.xml2
-rw-r--r--release/scripts/presets/interface_theme/softblend.xml2
-rw-r--r--release/scripts/presets/interface_theme/true_blue_menu.xml2
-rw-r--r--release/scripts/presets/keyconfig/3dsmax.py26
-rw-r--r--release/scripts/presets/keyconfig/blender_27x.py10756
-rw-r--r--release/scripts/presets/keyconfig/maya.py25
-rw-r--r--release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py2
-rw-r--r--release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py1
-rw-r--r--release/scripts/presets/sunsky/classic.py14
-rw-r--r--release/scripts/presets/sunsky/desert.py14
-rw-r--r--release/scripts/presets/sunsky/mountain.py14
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py18
-rw-r--r--release/scripts/startup/bl_operators/anim.py40
-rw-r--r--release/scripts/startup/bl_operators/clip.py60
-rw-r--r--release/scripts/startup/bl_operators/console.py4
-rw-r--r--release/scripts/startup/bl_operators/file.py59
-rw-r--r--release/scripts/startup/bl_operators/freestyle.py22
-rw-r--r--release/scripts/startup/bl_operators/image.py2
-rw-r--r--release/scripts/startup/bl_operators/mesh.py6
-rw-r--r--release/scripts/startup/bl_operators/node.py12
-rw-r--r--release/scripts/startup/bl_operators/object.py221
-rw-r--r--release/scripts/startup/bl_operators/object_align.py8
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py164
-rw-r--r--release/scripts/startup/bl_operators/object_randomize_transform.py20
-rw-r--r--release/scripts/startup/bl_operators/presets.py170
-rw-r--r--release/scripts/startup/bl_operators/rigidbody.py20
-rw-r--r--release/scripts/startup/bl_operators/sequencer.py2
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_follow_active.py6
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py27
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py14
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py10
-rw-r--r--release/scripts/startup/bl_operators/view3d.py12
-rw-r--r--release/scripts/startup/bl_operators/wm.py489
-rw-r--r--release/scripts/startup/bl_ui/__init__.py17
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py31
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py65
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py320
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py353
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py331
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lamp.py414
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lattice.py33
-rw-r--r--release/scripts/startup/bl_ui/properties_data_light.py363
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lightprobe.py185
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py119
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py50
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py32
-rw-r--r--release/scripts/startup/bl_ui/properties_data_speaker.py64
-rw-r--r--release/scripts/startup/bl_ui/properties_data_workspace.py101
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py83
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py881
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py28
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py997
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py281
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py1470
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py48
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py64
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py86
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_field.py224
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py42
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody.py20
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py116
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_softbody.py35
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py806
-rw-r--r--release/scripts/startup/bl_ui/properties_render_layer.py242
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py209
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py864
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py82
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py225
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py90
-rw-r--r--release/scripts/startup/bl_ui/space_console.py4
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py334
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py37
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py142
-rw-r--r--release/scripts/startup/bl_ui/space_image.py235
-rw-r--r--release/scripts/startup/bl_ui/space_info.py341
-rw-r--r--release/scripts/startup/bl_ui/space_logic.py145
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py42
-rw-r--r--release/scripts/startup/bl_ui/space_node.py158
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py238
-rw-r--r--release/scripts/startup/bl_ui/space_properties.py1
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py51
-rw-r--r--release/scripts/startup/bl_ui/space_statusbar.py68
-rw-r--r--release/scripts/startup/bl_ui/space_text.py29
-rw-r--r--release/scripts/startup/bl_ui/space_time.py254
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py725
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py1089
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py600
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py224
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py2545
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py1012
-rw-r--r--release/scripts/startup/nodeitems_builtins.py155
-rw-r--r--release/scripts/templates_py/addon_add_object.py2
-rw-r--r--release/scripts/templates_py/background_job.py10
-rw-r--r--release/scripts/templates_py/batch_export.py6
-rw-r--r--release/scripts/templates_py/custom_nodes.py13
-rw-r--r--release/scripts/templates_py/gamelogic.py74
-rw-r--r--release/scripts/templates_py/gamelogic_module.py27
-rw-r--r--release/scripts/templates_py/gamelogic_simple.py18
-rw-r--r--release/scripts/templates_py/manipulator_custom_geometry.py158
-rw-r--r--release/scripts/templates_py/manipulator_operator.py234
-rw-r--r--release/scripts/templates_py/manipulator_operator_target.py50
-rw-r--r--release/scripts/templates_py/manipulator_simple.py47
-rw-r--r--release/scripts/templates_py/operator_file_export.py6
-rw-r--r--release/scripts/templates_py/operator_file_import.py6
-rw-r--r--release/scripts/templates_py/operator_mesh_add.py14
-rw-r--r--release/scripts/templates_py/operator_modal.py4
-rw-r--r--release/scripts/templates_py/operator_modal_view3d.py2
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py2
-rw-r--r--release/scripts/templates_py/ui_list.py6
-rw-r--r--release/scripts/templates_py/ui_list_simple.py12
148 files changed, 23691 insertions, 9549 deletions
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject 9ae033c49c1b16718eac6306bdc271a5e6e6bf3
+Subproject ebd058d7a6438d137522063bb3286c8acc325ca
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject f178e6c933a25c621a5cc7d92935b66cd2ec2f5
+Subproject 474702157831f1a58bb50f5240ab8b1b02b6ba3
diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py
index b093920a4cb..c2b23f017fe 100644
--- a/release/scripts/freestyle/modules/parameter_editor.py
+++ b/release/scripts/freestyle/modules/parameter_editor.py
@@ -1206,7 +1206,7 @@ integration_types = {
# main function for parameter processing
def process(layer_name, lineset_name):
scene = getCurrentScene()
- layer = scene.render.layers[layer_name]
+ layer = scene.view_layers[layer_name]
lineset = layer.freestyle_settings.linesets[lineset_name]
linestyle = lineset.linestyle
@@ -1538,16 +1538,9 @@ def process(layer_name, lineset_name):
raise RuntimeError("No Thickness modifier with type", type(m), m)
# -- Textures -- #
has_tex = False
- if scene.render.use_shading_nodes:
- if linestyle.use_nodes and linestyle.node_tree:
- shaders_list.append(BlenderTextureShader(linestyle.node_tree))
- has_tex = True
- else:
- if linestyle.use_texture:
- textures = tuple(BlenderTextureShader(slot) for slot in linestyle.texture_slots if slot is not None)
- if textures:
- shaders_list.extend(textures)
- has_tex = True
+ if linestyle.use_nodes and linestyle.node_tree:
+ shaders_list.append(BlenderTextureShader(linestyle.node_tree))
+ has_tex = True
if has_tex:
shaders_list.append(StrokeTextureStepShader(linestyle.texture_spacing))
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 5cb313ec41b..86185b96e9d 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -362,9 +362,38 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
_addon_remove(module_name)
return None
+ # 1.1) fail when add-on is too old
+ # This is a temporary 2.8x migration check, so we can manage addons that are supported.
+
+ # Silent default, we know these need updating.
+ if module_name in {
+ "io_anim_bvh",
+ "io_mesh_ply",
+ "io_mesh_stl",
+ "io_mesh_uv_layout",
+ "io_scene_3ds",
+ "io_scene_fbx",
+ "io_scene_obj",
+ "io_scene_x3d",
+ }:
+ return None
+
+ try:
+ if mod.bl_info.get("blender", (0, 0, 0)) < (2, 80, 0):
+ raise Exception(f"Add-on '{module_name:s}' has not been upgraded to 2.8, ignoring")
+ except Exception as ex:
+ handle_error(ex)
+ return None
+
# 2) try register collected modules
# removed, addons need to handle own registration now.
+ use_owner = mod.bl_info.get("use_owner", True)
+ if use_owner:
+ from _bpy import _bl_owner_id_get, _bl_owner_id_set
+ owner_id_prev = _bl_owner_id_get()
+ _bl_owner_id_set(module_name)
+
# 3) try run the modules register function
try:
mod.register()
@@ -378,6 +407,9 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
if default_set:
_addon_remove(module_name)
return None
+ finally:
+ if use_owner:
+ _bl_owner_id_set(owner_id_prev)
# * OK loaded successfully! *
mod.__addon_enabled__ = True
@@ -491,6 +523,7 @@ def module_bl_info(mod, info_basis=None):
"category": "",
"warning": "",
"show_expanded": False,
+ "use_owner": True,
}
addon_info = getattr(mod, "bl_info", {})
@@ -508,5 +541,9 @@ def module_bl_info(mod, info_basis=None):
if not addon_info["name"]:
addon_info["name"] = mod.__name__
+ # Temporary auto-magic, don't use_owner for import export menus.
+ if mod.bl_info["category"] == "Import-Export":
+ mod.bl_info["use_owner"] = False
+
addon_info["_init"] = None
return addon_info
diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
index 10a386039c4..b395aab7772 100644
--- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
+++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
@@ -391,7 +391,7 @@ def dump_rna_messages(msgs, reports, settings, verbose=False):
return
def full_class_id(cls):
- """Gives us 'ID.Lamp.AreaLamp' which is best for sorting."""
+ """Gives us 'ID.Light.AreaLight' which is best for sorting."""
# Always the same issue, some classes listed in blacklist should actually no more exist (they have been
# unregistered), but are still listed by __subclasses__() calls... :/
if cls in blacklist_rna_class:
diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
index 6adf7f1ef91..b811c1c7d71 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -442,7 +442,6 @@ class SpellChecker:
"fedge", "fedges",
"filmic",
"fluidsim",
- "frameserver",
"freestyle",
"enum", "enums",
"gpencil",
@@ -589,7 +588,6 @@ class SpellChecker:
"yuv", "yuva",
# Blender acronyms
- "bge",
"bli",
"bpy",
"bvh",
diff --git a/release/scripts/modules/bl_previews_utils/bl_previews_render.py b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
index 4159121cd90..16b0b107927 100644
--- a/release/scripts/modules/bl_previews_utils/bl_previews_render.py
+++ b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
@@ -31,7 +31,7 @@ from mathutils import (
)
-INTERN_PREVIEW_TYPES = {'MATERIAL', 'LAMP', 'WORLD', 'TEXTURE', 'IMAGE'}
+INTERN_PREVIEW_TYPES = {'MATERIAL', 'LIGHT', 'WORLD', 'TEXTURE', 'IMAGE'}
OBJECT_TYPES_RENDER = {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}
@@ -68,20 +68,20 @@ def rna_backup_restore(data, backup):
setattr(dt, path[-1], val)
-def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
+def do_previews(do_objects, do_collections, do_scenes, do_data_intern):
import collections
# Helpers.
RenderContext = collections.namedtuple("RenderContext", (
- "scene", "world", "camera", "lamp", "camera_data", "lamp_data", "image", # All those are names!
- "backup_scene", "backup_world", "backup_camera", "backup_lamp", "backup_camera_data", "backup_lamp_data",
+ "scene", "world", "camera", "light", "camera_data", "light_data", "image", # All those are names!
+ "backup_scene", "backup_world", "backup_camera", "backup_light", "backup_camera_data", "backup_light_data",
))
RENDER_PREVIEW_SIZE = bpy.app.render_preview_size
def render_context_create(engine, objects_ignored):
if engine == '__SCENE':
- backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data = [()] * 6
+ backup_scene, backup_world, backup_camera, backup_light, backup_camera_data, backup_light_data = [()] * 6
scene = bpy.context.screen.scene
exclude_props = {('world',), ('camera',), ('tool_settings',), ('preview',)}
backup_scene = tuple(rna_backup_gen(scene, exclude_props=exclude_props))
@@ -96,20 +96,20 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
camera.rotation_euler = Euler((1.1635528802871704, 0.0, 0.7853981852531433), 'XYZ') # (66.67, 0.0, 45.0)
scene.camera = camera
scene.objects.link(camera)
- # TODO: add lamp if none found in scene?
- lamp = None
- lamp_data = None
+ # TODO: add light if none found in scene?
+ light = None
+ light_data = None
else:
- backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data = [None] * 6
+ backup_scene, backup_world, backup_camera, backup_light, backup_camera_data, backup_light_data = [None] * 6
scene = bpy.data.scenes.new("TEMP_preview_render_scene")
world = bpy.data.worlds.new("TEMP_preview_render_world")
camera_data = bpy.data.cameras.new("TEMP_preview_render_camera")
camera = bpy.data.objects.new("TEMP_preview_render_camera", camera_data)
- lamp_data = bpy.data.lamps.new("TEMP_preview_render_lamp", 'SPOT')
- lamp = bpy.data.objects.new("TEMP_preview_render_lamp", lamp_data)
+ light_data = bpy.data.lights.new("TEMP_preview_render_light", 'SPOT')
+ light = bpy.data.objects.new("TEMP_preview_render_light", light_data)
- objects_ignored.add((camera.name, lamp.name))
+ objects_ignored.add((camera.name, light.name))
scene.world = world
@@ -117,26 +117,14 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
scene.camera = camera
scene.objects.link(camera)
- lamp.rotation_euler = Euler((0.7853981852531433, 0.0, 1.7453292608261108), 'XYZ') # (45.0, 0.0, 100.0)
- lamp_data.falloff_type = 'CONSTANT'
- lamp_data.spot_size = 1.0471975803375244 # 60
- scene.objects.link(lamp)
-
- if engine == 'BLENDER_RENDER':
- scene.render.engine = 'BLENDER_RENDER'
- scene.render.alpha_mode = 'TRANSPARENT'
-
- world.use_sky_blend = True
- world.horizon_color = 0.9, 0.9, 0.9
- world.zenith_color = 0.5, 0.5, 0.5
- world.ambient_color = 0.1, 0.1, 0.1
- world.light_settings.use_environment_light = True
- world.light_settings.environment_energy = 1.0
- world.light_settings.environment_color = 'SKY_COLOR'
- elif engine == 'CYCLES':
- scene.render.engine = 'CYCLES'
- scene.cycles.film_transparent = True
- # TODO: define Cycles world?
+ light.rotation_euler = Euler((0.7853981852531433, 0.0, 1.7453292608261108), 'XYZ') # (45.0, 0.0, 100.0)
+ light_data.falloff_type = 'CONSTANT'
+ light_data.spot_size = 1.0471975803375244 # 60
+ scene.objects.link(light)
+
+ scene.render.engine = 'CYCLES'
+ scene.cycles.film_transparent = True
+ # TODO: define Cycles world?
scene.render.image_settings.file_format = 'PNG'
scene.render.image_settings.color_depth = '8'
@@ -154,9 +142,9 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
image.filepath = scene.render.filepath
return RenderContext(
- scene.name, world.name if world else None, camera.name, lamp.name if lamp else None,
- camera_data.name, lamp_data.name if lamp_data else None, image.name,
- backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data,
+ scene.name, world.name if world else None, camera.name, light.name if light else None,
+ camera_data.name, light_data.name if light_data else None, image.name,
+ backup_scene, backup_world, backup_camera, backup_light, backup_camera_data, backup_light_data,
)
def render_context_delete(render_context):
@@ -171,8 +159,8 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
scene.camera = None
if render_context.camera:
scene.objects.unlink(bpy.data.objects[render_context.camera, None])
- if render_context.lamp:
- scene.objects.unlink(bpy.data.objects[render_context.lamp, None])
+ if render_context.light:
+ scene.objects.unlink(bpy.data.objects[render_context.light, None])
bpy.data.scenes.remove(scene, do_unlink=True)
scene = None
else:
@@ -213,18 +201,18 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
print("ERROR:", e)
success = False
- if render_context.lamp:
+ if render_context.light:
try:
- lamp = bpy.data.objects[render_context.lamp, None]
- if render_context.backup_lamp is None:
+ light = bpy.data.objects[render_context.light, None]
+ if render_context.backup_light is None:
if scene is not None:
- scene.objects.unlink(lamp)
- lamp.user_clear()
- bpy.data.objects.remove(lamp)
- bpy.data.lamps.remove(bpy.data.lamps[render_context.lamp_data, None])
+ scene.objects.unlink(light)
+ light.user_clear()
+ bpy.data.objects.remove(light)
+ bpy.data.lights.remove(bpy.data.lights[render_context.light_data, None])
else:
- rna_backup_restore(lamp, render_context.backup_lamp)
- rna_backup_restore(bpy.data.lamps[render_context.lamp_data, None], render_context.backup_lamp_data)
+ rna_backup_restore(light, render_context.backup_light)
+ rna_backup_restore(bpy.data.lights[render_context.light_data, None], render_context.backup_light_data)
except Exception as e:
print("ERROR:", e)
success = False
@@ -239,21 +227,10 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
return success
- def objects_render_engine_guess(obs):
- for obname, libpath in obs:
- ob = bpy.data.objects[obname, libpath]
- for matslot in ob.material_slots:
- mat = matslot.material
- if mat and mat.use_nodes and mat.node_tree:
- for nd in mat.node_tree.nodes:
- if nd.shading_compatibility == {'NEW_SHADING'}:
- return 'CYCLES'
- return 'BLENDER_RENDER'
-
def object_bbox_merge(bbox, ob, ob_space, offset_matrix):
- # Take group instances into account (including linked one in this case).
- if ob.type == 'EMPTY' and ob.dupli_type == 'GROUP':
- grp_objects = tuple((ob.name, ob.library.filepath if ob.library else None) for ob in ob.dupli_group.objects)
+ # Take collections instances into account (including linked one in this case).
+ if ob.type == 'EMPTY' and ob.dupli_type == 'COLLECTION':
+ grp_objects = tuple((ob.name, ob.library.filepath if ob.library else None) for ob in ob.dupli_group.all_objects)
if (len(grp_objects) == 0):
ob_bbox = ob.bound_box
else:
@@ -305,7 +282,7 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
scene = bpy.data.scenes[render_context.scene, None]
if objects is not None:
camera = bpy.data.objects[render_context.camera, None]
- lamp = bpy.data.objects[render_context.lamp, None] if render_context.lamp is not None else None
+ light = bpy.data.objects[render_context.light, None] if render_context.light is not None else None
cos = objects_bbox_calc(camera, objects, offset_matrix)
loc, ortho_scale = camera.camera_fit_coords(scene, cos)
camera.location = loc
@@ -320,9 +297,9 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
max_dist = dist
camera.data.clip_start = min_dist / 2
camera.data.clip_end = max_dist * 2
- if lamp:
- loc, ortho_scale = lamp.camera_fit_coords(scene, cos)
- lamp.location = loc
+ if light:
+ loc, ortho_scale = light.camera_fit_coords(scene, cos)
+ light.location = loc
scene.update()
bpy.ops.render.render(write_still=True)
@@ -343,7 +320,7 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
render_contexts = {}
objects_ignored = set()
- groups_ignored = set()
+ collections_ignored = set()
prev_scenename = bpy.context.screen.scene.name
@@ -360,11 +337,10 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
continue
objects = ((root.name, None),)
- render_engine = objects_render_engine_guess(objects)
- render_context = render_contexts.get(render_engine, None)
+ render_context = render_contexts.get('CYCLES', None)
if render_context is None:
- render_context = render_context_create(render_engine, objects_ignored)
- render_contexts[render_engine] = render_context
+ render_context = render_context_create('CYCLES', objects_ignored)
+ render_contexts['CYCLES'] = render_context
scene = bpy.data.scenes[render_context.scene, None]
bpy.context.screen.scene = scene
@@ -398,30 +374,29 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
if is_rendered is not ...:
ob.hide_render = is_rendered
- if do_groups:
- for grp in ids_nolib(bpy.data.groups):
- if grp.name in groups_ignored:
+ if do_collections:
+ for grp in ids_nolib(bpy.data.collections):
+ if grp.name in collections_ignored:
continue
- # Here too, we do want to keep linked objects members of local group...
+ # Here too, we do want to keep linked objects members of local collection...
objects = tuple((ob.name, ob.library.filepath if ob.library else None) for ob in grp.objects)
- render_engine = objects_render_engine_guess(objects)
- render_context = render_contexts.get(render_engine, None)
+ render_context = render_contexts.get('CYCLES', None)
if render_context is None:
- render_context = render_context_create(render_engine, objects_ignored)
- render_contexts[render_engine] = render_context
+ render_context = render_context_create('CYCLES', objects_ignored)
+ render_contexts['CYCLES'] = render_context
scene = bpy.data.scenes[render_context.scene, None]
bpy.context.screen.scene = scene
- bpy.ops.object.group_instance_add(group=grp.name)
+ bpy.ops.object.collection_instance_add(collection=grp.name)
grp_ob = next((ob for ob in scene.objects if ob.dupli_group and ob.dupli_group.name == grp.name))
grp_obname = grp_ob.name
scene.update()
offset_matrix = Matrix.Translation(grp.dupli_offset).inverted()
- preview_render_do(render_context, 'groups', grp.name, objects, offset_matrix)
+ preview_render_do(render_context, 'collections', grp.name, objects, offset_matrix)
scene = bpy.data.scenes[render_context.scene, None]
scene.objects.unlink(bpy.data.objects[grp_obname, None])
@@ -462,7 +437,7 @@ def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
print("*NOT* Saving %s, because some error(s) happened while deleting temp render data..." % bpy.data.filepath)
-def do_clear_previews(do_objects, do_groups, do_scenes, do_data_intern):
+def do_clear_previews(do_objects, do_collections, do_scenes, do_data_intern):
if do_data_intern:
bpy.ops.wm.previews_clear(id_type=INTERN_PREVIEW_TYPES)
@@ -470,8 +445,8 @@ def do_clear_previews(do_objects, do_groups, do_scenes, do_data_intern):
for ob in ids_nolib(bpy.data.objects):
ob.preview.image_size = (0, 0)
- if do_groups:
- for grp in ids_nolib(bpy.data.groups):
+ if do_collections:
+ for grp in ids_nolib(bpy.data.collections):
grp.preview.image_size = (0, 0)
if do_scenes:
@@ -502,8 +477,8 @@ def main():
help="Do not generate a backup .blend1 file when saving processed ones.")
parser.add_argument('--no_scenes', default=True, action="store_false",
help="Do not generate/clear previews for scene IDs.")
- parser.add_argument('--no_groups', default=True, action="store_false",
- help="Do not generate/clear previews for group IDs.")
+ parser.add_argument('--no_collections', default=True, action="store_false",
+ help="Do not generate/clear previews for collection IDs.")
parser.add_argument('--no_objects', default=True, action="store_false",
help="Do not generate/clear previews for object IDs.")
parser.add_argument('--no_data_intern', default=True, action="store_false",
@@ -518,11 +493,11 @@ def main():
if args.clear:
print("clear!")
- do_clear_previews(do_objects=args.no_objects, do_groups=args.no_groups, do_scenes=args.no_scenes,
+ do_clear_previews(do_objects=args.no_objects, do_collections=args.no_collections, do_scenes=args.no_scenes,
do_data_intern=args.no_data_intern)
else:
print("render!")
- do_previews(do_objects=args.no_objects, do_groups=args.no_groups, do_scenes=args.no_scenes,
+ do_previews(do_objects=args.no_objects, do_collections=args.no_collections, do_scenes=args.no_scenes,
do_data_intern=args.no_data_intern)
# Not really necessary, but better be consistent.
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index 6312c25065f..a80135a59e1 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -39,6 +39,7 @@ from _bpy import (
app,
context,
data,
+ msgbus,
props,
types,
)
diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py
index 7c5c76ffdbe..6d8ed1c1780 100644
--- a/release/scripts/modules/bpy/ops.py
+++ b/release/scripts/modules/bpy/ops.py
@@ -145,10 +145,10 @@ class BPyOpsSubModOp:
return C_dict, C_exec, C_undo
@staticmethod
- def _scene_update(context):
- scene = context.scene
- if scene: # None in background mode
- scene.update()
+ def _view_layer_update(context):
+ view_layer = context.view_layer
+ if view_layer: # None in background mode
+ view_layer.update()
else:
import bpy
for scene in bpy.data.scenes:
@@ -180,7 +180,10 @@ class BPyOpsSubModOp:
wm = context.window_manager
# run to account for any rna values the user changes.
- BPyOpsSubModOp._scene_update(context)
+ # NOTE: We only update active vew layer, since that's what
+ # operators are supposed to operate on. There might be some
+ # corner cases when operator need a full scene update though.
+ BPyOpsSubModOp._view_layer_update(context)
if args:
C_dict, C_exec, C_undo = BPyOpsSubModOp._parse_args(args)
@@ -189,7 +192,7 @@ class BPyOpsSubModOp:
ret = op_call(self.idname_py(), None, kw)
if 'FINISHED' in ret and context.window_manager == wm:
- BPyOpsSubModOp._scene_update(context)
+ BPyOpsSubModOp._view_layer_update(context)
return ret
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py
index 5e5a35b9518..80e48697b2f 100644
--- a/release/scripts/modules/bpy/utils/__init__.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -34,7 +34,6 @@ __all__ = (
"refresh_script_paths",
"app_template_paths",
"register_class",
- "register_module",
"register_manual_map",
"unregister_manual_map",
"register_classes_factory",
@@ -50,7 +49,6 @@ __all__ = (
"smpte_from_seconds",
"units",
"unregister_class",
- "unregister_module",
"user_resource",
)
@@ -166,10 +164,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
for module_name in [ext.module for ext in _user_preferences.addons]:
_addon_utils.disable(module_name)
- # *AFTER* unregistering all add-ons, otherwise all calls to
- # unregister_module() will silently fail (do nothing).
- _bpy_types.TypeMap.clear()
-
def register_module_call(mod):
register = getattr(mod, "register", None)
if register:
@@ -581,8 +575,13 @@ def keyconfig_set(filepath, report=None):
try:
error_msg = ""
with open(filepath, 'r', encoding='utf-8') as keyfile:
- exec(compile(keyfile.read(), filepath, "exec"),
- {"__file__": filepath})
+ exec(
+ compile(keyfile.read(), filepath, "exec"),
+ {
+ "__file__": filepath,
+ "__name__": "__main__",
+ }
+ )
except:
import traceback
error_msg = traceback.format_exc()
@@ -650,58 +649,6 @@ def user_resource(resource_type, path="", create=False):
return target_path
-def _bpy_module_classes(module, is_registered=False):
- typemap_list = _bpy_types.TypeMap.get(module, ())
- i = 0
- while i < len(typemap_list):
- cls_weakref = typemap_list[i]
- cls = cls_weakref()
-
- if cls is None:
- del typemap_list[i]
- else:
- if is_registered == cls.is_registered:
- yield cls
- i += 1
-
-
-def register_module(module, verbose=False):
- if verbose:
- print("bpy.utils.register_module(%r): ..." % module)
- cls = None
- for cls in _bpy_module_classes(module, is_registered=False):
- if verbose:
- print(" %r" % cls)
- try:
- register_class(cls)
- except:
- print("bpy.utils.register_module(): "
- "failed to registering class %r" % cls)
- import traceback
- traceback.print_exc()
- if verbose:
- print("done.\n")
- if cls is None:
- raise Exception("register_module(%r): defines no classes" % module)
-
-
-def unregister_module(module, verbose=False):
- if verbose:
- print("bpy.utils.unregister_module(%r): ..." % module)
- for cls in _bpy_module_classes(module, is_registered=True):
- if verbose:
- print(" %r" % cls)
- try:
- unregister_class(cls)
- except:
- print("bpy.utils.unregister_module(): "
- "failed to unregistering class %r" % cls)
- import traceback
- traceback.print_exc()
- if verbose:
- print("done.\n")
-
-
def register_classes_factory(classes):
"""
Utility function to create register and unregister functions
diff --git a/release/scripts/modules/bpy_extras/__init__.py b/release/scripts/modules/bpy_extras/__init__.py
index d2578e1812a..1caef074d43 100644
--- a/release/scripts/modules/bpy_extras/__init__.py
+++ b/release/scripts/modules/bpy_extras/__init__.py
@@ -29,5 +29,6 @@ __all__ = (
"image_utils",
"keyconfig_utils",
"mesh_utils",
+ "node_utils",
"view3d_utils",
)
diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py
index e2c2e4c9b93..a0c1c3e5c84 100644
--- a/release/scripts/modules/bpy_extras/io_utils.py
+++ b/release/scripts/modules/bpy_extras/io_utils.py
@@ -52,25 +52,19 @@ def _check_axis_conversion(op):
class ExportHelper:
- filepath = StringProperty(
+ filepath: StringProperty(
name="File Path",
description="Filepath used for exporting the file",
maxlen=1024,
subtype='FILE_PATH',
)
- check_existing = BoolProperty(
+ check_existing: BoolProperty(
name="Check Existing",
description="Check and warn on overwriting existing files",
default=True,
options={'HIDDEN'},
)
- # needed for mix-ins
- order = [
- "filepath",
- "check_existing",
- ]
-
# subclasses can override with decorator
# True == use ext, False == no ext, None == do nothing.
check_extension = True
@@ -112,18 +106,13 @@ class ExportHelper:
class ImportHelper:
- filepath = StringProperty(
+ filepath: StringProperty(
name="File Path",
description="Filepath used for importing the file",
maxlen=1024,
subtype='FILE_PATH',
)
- # needed for mix-ins
- order = [
- "filepath",
- ]
-
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
@@ -173,11 +162,6 @@ def orientation_helper_factory(name, axis_forward='Y', axis_up='Z'):
update=_update_axis_up,
)
- members["order"] = [
- "axis_forward",
- "axis_up",
- ]
-
return type(name, (object,), members)
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
index 3a9570a57c4..7e5e1fb855c 100644
--- a/release/scripts/modules/bpy_extras/keyconfig_utils.py
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py
@@ -99,7 +99,6 @@ KM_HIERARCHY = [
('SequencerCommon', 'SEQUENCE_EDITOR', 'WINDOW', []),
('SequencerPreview', 'SEQUENCE_EDITOR', 'WINDOW', []),
]),
- ('Logic Editor', 'LOGIC_EDITOR', 'WINDOW', []),
('File Browser', 'FILE_BROWSER', 'WINDOW', [
('File Browser Main', 'FILE_BROWSER', 'WINDOW', []),
@@ -406,3 +405,11 @@ def keyconfig_test(kc):
if testEntry(kc, entry):
result = True
return result
+
+
+# Note, we may eventually replace existing logic with this
+# so key configs are always data.
+from .keyconfig_utils_experimental import (
+ keyconfig_export_as_data,
+ keyconfig_import_from_data,
+)
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils_experimental.py b/release/scripts/modules/bpy_extras/keyconfig_utils_experimental.py
new file mode 100644
index 00000000000..a0ea87d1c93
--- /dev/null
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils_experimental.py
@@ -0,0 +1,244 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+__all__ = (
+ "keyconfig_export_as_data",
+ "keyconfig_import_from_data",
+)
+
+
+def indent(levels):
+ return levels * " "
+
+
+def round_float_32(f):
+ from struct import pack, unpack
+ return unpack("f", pack("f", f))[0]
+
+
+def repr_f32(f):
+ f_round = round_float_32(f)
+ f_str = repr(f)
+ f_str_frac = f_str.partition(".")[2]
+ if not f_str_frac:
+ return f_str
+ for i in range(1, len(f_str_frac)):
+ f_test = round(f, i)
+ f_test_round = round_float_32(f_test)
+ if f_test_round == f_round:
+ return "%.*f" % (i, f_test)
+ return f_str
+
+
+def kmi_args_as_data(kmi):
+ s = [
+ f"\"type\": '{kmi.type}'",
+ f"\"value\": '{kmi.value}'"
+ ]
+
+ if kmi.any:
+ s.append("\"any\": True")
+ else:
+ if kmi.shift:
+ s.append("\"shift\": True")
+ if kmi.ctrl:
+ s.append("\"ctrl\": True")
+ if kmi.alt:
+ s.append("\"alt\": True")
+ if kmi.oskey:
+ s.append("\"oskey\": True")
+ if kmi.key_modifier and kmi.key_modifier != 'NONE':
+ s.append(f"\"key_modifier\": '{kmi.key_modifier}'")
+
+ return "{" + ", ".join(s) + "}"
+
+
+def _kmi_properties_to_lines_recursive(level, properties, lines):
+ from bpy.types import OperatorProperties
+
+ def string_value(value):
+ if isinstance(value, (str, bool, int)):
+ return repr(value)
+ elif isinstance(value, float):
+ return repr_f32(value)
+ elif getattr(value, '__len__', False):
+ return repr(tuple(value))
+ raise Exception(f"Export key configuration: can't write {value!r}")
+
+ for pname in properties.bl_rna.properties.keys():
+ if pname != "rna_type":
+ value = getattr(properties, pname)
+ if isinstance(value, OperatorProperties):
+ lines_test = []
+ _kmi_properties_to_lines_recursive(level + 2, value, lines_test)
+ if lines_test:
+ lines.append(f"{indent(level)}(\n")
+ lines.append(f"{indent(level + 1)}\"{pname}\",\n")
+ lines.append(f"{indent(level + 1)}" "[\n")
+ lines.extend(lines_test)
+ lines.append(f"{indent(level + 1)}" "],\n")
+ lines.append(f"{indent(level)}" "),\n")
+ del lines_test
+ elif properties.is_property_set(pname):
+ value = string_value(value)
+ lines.append((f"{indent(level)}(\"{pname}\", {value:s}),\n"))
+
+
+def _kmi_properties_to_lines(level, kmi_props, lines):
+ if kmi_props is None:
+ return
+
+ lines_test = [f"{indent(level)}\"properties\": " "[\n"]
+ _kmi_properties_to_lines_recursive(level + 1, kmi_props, lines_test)
+ if len(lines_test) > 1:
+ lines_test.append(f"{indent(level)}" "],\n")
+ lines.extend(lines_test)
+
+
+def _kmi_attrs_or_none(level, kmi):
+ lines = []
+ _kmi_properties_to_lines(level + 1, kmi.properties, lines)
+ if kmi.active is False:
+ lines.append(f"{indent(level)}\"active\":" "False,\n")
+ if not lines:
+ return None
+ return "".join(lines)
+
+
+def keyconfig_export_as_data(wm, kc, filepath):
+ # Alternate foramt
+
+ # Generate a list of keymaps to export:
+ #
+ # First add all user_modified keymaps (found in keyconfigs.user.keymaps list),
+ # then add all remaining keymaps from the currently active custom keyconfig.
+ #
+ # This will create a final list of keymaps that can be used as a "diff" against
+ # the default blender keyconfig, recreating the current setup from a fresh blender
+ # without needing to export keymaps which haven't been edited.
+
+ from .keyconfig_utils import keyconfig_merge
+
+ class FakeKeyConfig:
+ keymaps = []
+ edited_kc = FakeKeyConfig()
+ for km in wm.keyconfigs.user.keymaps:
+ if km.is_user_modified:
+ edited_kc.keymaps.append(km)
+ # merge edited keymaps with non-default keyconfig, if it exists
+ if kc != wm.keyconfigs.default:
+ export_keymaps = keyconfig_merge(edited_kc, kc)
+ else:
+ export_keymaps = keyconfig_merge(edited_kc, edited_kc)
+
+ with open(filepath, "w") as fh:
+ fw = fh.write
+ fw("keyconfig_data = [\n")
+
+ for km, kc_x in export_keymaps:
+ km = km.active()
+ fw(f"{indent(1)}" "(\n")
+ fw(f"{indent(2)}" f"\"{km.name:s}\",\n")
+ fw(f"{indent(2)}" "{")
+ fw(f"\"space_type\": '{km.space_type:s}'")
+ fw(f", \"region_type\": '{km.region_type:s}'")
+ # We can detect from the kind of items.
+ if km.is_modal:
+ fw(", \"modal\": True")
+ fw("},\n")
+ fw(f"{indent(2)}" "{\n")
+ is_modal = km.is_modal
+ fw(f"{indent(3)}" "\"items\": [\n")
+ for kmi in km.keymap_items:
+ if is_modal:
+ kmi_id = kmi.propvalue
+ else:
+ kmi_id = kmi.idname
+
+ fw(f"{indent(4)}" "(")
+ kmi_args = kmi_args_as_data(kmi)
+ kmi_data = _kmi_attrs_or_none(5, kmi)
+ if kmi_data is not None:
+ fw("\n" f"{indent(5)}")
+ fw(f"\"{kmi_id:s}\"")
+ if kmi_data is None:
+ fw(f", ")
+ else:
+ fw(",\n" f"{indent(5)}")
+
+ fw(kmi_args)
+ if kmi_data is None:
+ fw(", None),\n")
+ else:
+ fw(",\n")
+ fw(f"{indent(5)}" "{\n")
+ fw(kmi_data)
+ fw(f"{indent(5)}" "}\n")
+ fw(f"{indent(4)}" "),\n")
+
+ fw(f"{indent(3)}" "],\n")
+ fw(f"{indent(2)}" "},\n")
+ fw(f"{indent(1)}" "),\n")
+ fw("]\n")
+ fw("\n\n")
+ fw("if __name__ == \"__main__\":\n")
+ fw(" import os\n")
+ fw(" from bpy_extras.keyconfig_utils import keyconfig_import_from_data\n")
+ fw(" keyconfig_import_from_data(os.path.splitext(os.path.basename(__file__))[0], keyconfig_data)\n")
+
+
+def keyconfig_import_from_data(name, keyconfig_data):
+ # Load data in the format defined above.
+ #
+ # Runs at load time, keep this fast!
+
+ def kmi_props_setattr(kmi_props, attr, value):
+ if type(value) is list:
+ kmi_subprop = getattr(kmi_props, attr)
+ for subattr, subvalue in value:
+ kmi_props_setattr(kmi_subprop, subattr, subvalue)
+ return
+
+ try:
+ setattr(kmi_props, attr, value)
+ except AttributeError:
+ print(f"Warning: property '{attr}' not found in keymap item '{kmi_props.__class__.__name__}'")
+ except Exception as ex:
+ print(f"Warning: {ex!r}")
+
+ import bpy
+ wm = bpy.context.window_manager
+ kc = wm.keyconfigs.new(name)
+ del name
+
+ for (km_name, km_args, km_content) in keyconfig_data:
+ km = kc.keymaps.new(km_name, **km_args)
+ is_modal = km_args.get("modal", False)
+ new_fn = getattr(km.keymap_items, "new_modal" if is_modal else "new")
+ for (kmi_idname, kmi_args, kmi_data) in km_content["items"]:
+ kmi = new_fn(kmi_idname, **kmi_args)
+ if kmi_data is not None:
+ if not kmi_data.get("active", True):
+ kmi.active = False
+ kmi_props_data = kmi_data.get("properties", None)
+ if kmi_props_data is not None:
+ kmi_props = kmi.properties
+ for attr, value in kmi_props_data:
+ kmi_props_setattr(kmi_props, attr, value)
diff --git a/release/scripts/modules/bpy_extras/node_utils.py b/release/scripts/modules/bpy_extras/node_utils.py
new file mode 100644
index 00000000000..d4c6d5cd45a
--- /dev/null
+++ b/release/scripts/modules/bpy_extras/node_utils.py
@@ -0,0 +1,32 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8-80 compliant>
+
+__all__ = (
+ "find_node_input",
+)
+
+
+# XXX Names are not unique. Returns the first match.
+def find_node_input(node, name):
+ for input in node.inputs:
+ if input.name == name:
+ return input
+
+ return None
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 0a48d99b529..7719e2f6e30 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -103,9 +103,9 @@ def add_object_align_init(context, operator):
return location * rotation
-def object_data_add(context, obdata, operator=None, use_active_layer=True, name=None):
+def object_data_add(context, obdata, operator=None, name=None):
"""
- Add an object using the view context and preference to to initialize the
+ Add an object using the view context and preference to initialize the
location, rotation and layer.
:arg context: The context to use.
@@ -117,53 +117,31 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
:arg name: Optional name
:type name: string
:return: the newly created object in the scene.
- :rtype: :class:`bpy.types.ObjectBase`
+ :rtype: :class:`bpy.types.Object`
"""
scene = context.scene
+ layer = context.view_layer
+ layer_collection = context.layer_collection
- # ugh, could be made nicer
- for ob in scene.objects:
- ob.select = False
+ for ob in layer.objects:
+ ob.select_set(action='DESELECT')
+
+ if not layer_collection:
+ # when there is no collection linked to this view_layer create one
+ scene_collection = scene.master_collection.collections.new("")
+ layer_collection = layer.collections.link(scene_collection)
+ else:
+ scene_collection = layer_collection.collection
if name is None:
name = "Object" if obdata is None else obdata.name
+ obj_act = layer.objects.active
obj_new = bpy.data.objects.new(name, obdata)
-
- base = scene.objects.link(obj_new)
- base.select = True
-
- v3d = None
- if context.space_data and context.space_data.type == 'VIEW_3D':
- v3d = context.space_data
-
- if v3d and v3d.local_view:
- base.layers_from_view(context.space_data)
-
- if operator is not None and any(operator.layers):
- base.layers = operator.layers
- else:
- if use_active_layer:
- if v3d and v3d.local_view:
- base.layers[scene.active_layer] = True
- else:
- if v3d and not v3d.lock_camera_and_layers:
- base.layers = [True if i == v3d.active_layer
- else False for i in range(len(v3d.layers))]
- else:
- base.layers = [True if i == scene.active_layer
- else False for i in range(len(scene.layers))]
- else:
- if v3d:
- base.layers_from_view(context.space_data)
-
- if operator is not None:
- operator.layers = base.layers
-
+ scene_collection.objects.link(obj_new)
+ obj_new.select_set(action='SELECT')
obj_new.matrix_world = add_object_align_init(context, operator)
- obj_act = scene.objects.active
-
# XXX
# caused because entering edit-mode does not add a empty undo slot!
if context.user_preferences.edit.use_enter_edit_mode:
@@ -174,8 +152,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
_obdata = bpy.data.meshes.new(name)
obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world
- scene.objects.link(obj_act)
- scene.objects.active = obj_act
+ scene_collection.objects.link(obj_act)
+ layer.objects.active = obj_act
bpy.ops.object.mode_set(mode='EDIT')
# need empty undo step
bpy.ops.ed.undo_push(message="Enter Editmode")
@@ -183,9 +161,10 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
if obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type:
bpy.ops.mesh.select_all(action='DESELECT')
+ obj_act.select_set(action='SELECT')
bpy.ops.object.mode_set(mode='OBJECT')
- obj_act.select = True
+ obj_act.select_set(action='SELECT')
scene.update() # apply location
# scene.objects.active = obj_new
@@ -200,16 +179,14 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
bpy.ops.object.join() # join into the active.
if obdata:
bpy.data.meshes.remove(obdata)
- # base is freed, set to active object
- base = scene.object_bases.active
bpy.ops.object.mode_set(mode='EDIT')
else:
- scene.objects.active = obj_new
+ layer.objects.active = obj_new
if context.user_preferences.edit.use_enter_edit_mode:
bpy.ops.object.mode_set(mode='EDIT')
- return base
+ return obj_new
class AddObjectHelper:
@@ -217,25 +194,19 @@ class AddObjectHelper:
if not self.view_align:
self.rotation.zero()
- view_align = BoolProperty(
+ view_align: BoolProperty(
name="Align to View",
default=False,
update=view_align_update_callback,
)
- location = FloatVectorProperty(
+ location: FloatVectorProperty(
name="Location",
subtype='TRANSLATION',
)
- rotation = FloatVectorProperty(
+ rotation: FloatVectorProperty(
name="Rotation",
subtype='EULER',
)
- layers = BoolVectorProperty(
- name="Layers",
- size=20,
- subtype='LAYER',
- options={'HIDDEN', 'SKIP_SAVE'},
- )
@classmethod
def poll(self, context):
@@ -251,7 +222,7 @@ def object_add_grid_scale(context):
space_data = context.space_data
if space_data and space_data.type == 'VIEW_3D':
- return space_data.grid_scale_unit
+ return space_data.overlay.grid_scale_unit
return 1.0
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 15d92cd6b61..3bdf92f8e63 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -60,8 +60,8 @@ class Library(bpy_types.ID):
# See: readblenentry.c, IDTYPE_FLAGS_ISLINKABLE,
# we could make this an attribute in rna.
attr_links = ("actions", "armatures", "brushes", "cameras",
- "curves", "grease_pencil", "groups", "images",
- "lamps", "lattices", "materials", "metaballs",
+ "curves", "grease_pencil", "collections", "images",
+ "lights", "lattices", "materials", "metaballs",
"meshes", "node_groups", "objects", "scenes",
"sounds", "speakers", "textures", "texts",
"fonts", "worlds")
@@ -96,12 +96,12 @@ class Texture(bpy_types.ID):
)
-class Group(bpy_types.ID):
+class Collection(bpy_types.ID):
__slots__ = ()
@property
def users_dupli_group(self):
- """The dupli group this group is used in"""
+ """The collection instance objects this collection is used in"""
import bpy
return tuple(obj for obj in bpy.data.objects
if self == obj.dupli_group)
@@ -118,11 +118,11 @@ class Object(bpy_types.ID):
if child.parent == self)
@property
- def users_group(self):
- """The groups this object is in"""
+ def users_collection(self):
+ """The collections this object is in"""
import bpy
- return tuple(group for group in bpy.data.groups
- if self in group.objects[:])
+ return tuple(collection for collection in bpy.data.collections
+ if self in collection.objects[:])
@property
def users_scene(self):
@@ -144,6 +144,21 @@ class WindowManager(bpy_types.ID):
finally:
self.popmenu_end__internal(popup)
+ def popover(
+ self, draw_func, *,
+ ui_units_x=0,
+ keymap=None,
+ ):
+ import bpy
+ popup = self.popover_begin__internal(
+ ui_units_x=ui_units_x,
+ )
+
+ try:
+ draw_func(popup, bpy.context)
+ finally:
+ self.popover_end__internal(popup, keymap)
+
def popup_menu_pie(self, event, draw_func, title="", icon='NONE'):
import bpy
pie = self.piemenu_begin__internal(title, icon, event)
@@ -517,19 +532,6 @@ class Text(bpy_types.ID):
self.clear()
self.write(string)
- @property
- def users_logic(self):
- """Logic bricks that use this text"""
- import bpy
- return tuple(obj for obj in bpy.data.objects
- if self in [cont.text for cont in obj.game.controllers
- if cont.type == 'PYTHON']
- )
-
-
-# values are module: [(cls, path, line), ...]
-TypeMap = {}
-
class Sound(bpy_types.ID):
__slots__ = ()
@@ -542,59 +544,119 @@ class Sound(bpy_types.ID):
class RNAMeta(type):
+ # TODO(campbell): move to C-API
+ @property
+ def is_registered(cls):
+ return "bl_rna" in cls.__dict__
- def __new__(cls, name, bases, classdict, **args):
- result = type.__new__(cls, name, bases, classdict)
- if bases and bases[0] is not StructRNA:
- from _weakref import ref as ref
- module = result.__module__
- # first part of packages only
- if "." in module:
- module = module[:module.index(".")]
+class RNAMetaPropGroup(StructMetaPropGroup, RNAMeta):
+ pass
- TypeMap.setdefault(module, []).append(ref(result))
- return result
+# Same as 'Operator'
+# only without 'as_keywords'
+class Manipulator(StructRNA):
+ __slots__ = ()
- @property
- def is_registered(cls):
- return "bl_rna" in cls.__dict__
+ def __getattribute__(self, attr):
+ properties = StructRNA.path_resolve(self, "properties")
+ bl_rna = getattr(properties, "bl_rna", None)
+ if (bl_rna is not None) and (attr in bl_rna.properties):
+ return getattr(properties, attr)
+ return super().__getattribute__(attr)
+
+ def __setattr__(self, attr, value):
+ properties = StructRNA.path_resolve(self, "properties")
+ bl_rna = getattr(properties, "bl_rna", None)
+ if (bl_rna is not None) and (attr in bl_rna.properties):
+ return setattr(properties, attr, value)
+ return super().__setattr__(attr, value)
+ def __delattr__(self, attr):
+ properties = StructRNA.path_resolve(self, "properties")
+ bl_rna = getattr(properties, "bl_rna", None)
+ if (bl_rna is not None) and (attr in bl_rna.properties):
+ return delattr(properties, attr)
+ return super().__delattr__(attr)
-class OrderedDictMini(dict):
+ from _bpy import (
+ _rna_manipulator_target_set_handler as target_set_handler,
+ _rna_manipulator_target_get_value as target_get_value,
+ _rna_manipulator_target_set_value as target_set_value,
+ _rna_manipulator_target_get_range as target_get_range,
+ )
- def __init__(self, *args):
- self.order = []
- dict.__init__(self, args)
+ # Convenience wrappers around private `_gawain` module.
+ def draw_custom_shape(self, shape, *, matrix=None, select_id=None):
+ """
+ Draw a shape created form :class:`bpy.types.Manipulator.draw_custom_shape`.
- def __setitem__(self, key, val):
- dict.__setitem__(self, key, val)
- if key not in self.order:
- self.order.append(key)
+ :arg shape: The cached shape to draw.
+ :type shape: Undefined.
+ :arg matrix: 4x4 matrix, when not given
+ :class:`bpy.types.Manipulator.matrix_world` is used.
+ :type matrix: :class:`mathutils.Matrix`
+ :arg select_id: The selection id.
+ Only use when drawing within :class:`bpy.types.Manipulator.draw_select`.
+ :type select_it: int
+ """
+ import gpu
- def __delitem__(self, key):
- dict.__delitem__(self, key)
- self.order.remove(key)
+ if matrix is None:
+ matrix = self.matrix_world
+ batch, dims = shape
-class RNAMetaPropGroup(StructMetaPropGroup, RNAMeta):
- pass
+ # XXX, can we avoid setting the shader every time?
+ batch.program_set_builtin('3D_UNIFORM_COLOR' if dims == 3 else '2D_UNIFORM_COLOR')
+ if select_id is not None:
+ gpu.select.load_id(select_id)
+ else:
+ if self.is_highlight:
+ color = (*self.color_highlight, self.alpha_highlight)
+ else:
+ color = (*self.color, self.alpha)
+ batch.uniform_f32("color", *color)
-class OrderedMeta(RNAMeta):
+ with gpu.matrix.push_pop():
+ gpu.matrix.multiply_matrix(matrix)
+ batch.draw()
- def __init__(cls, name, bases, attributes):
- if attributes.__class__ is OrderedDictMini:
- cls.order = attributes.order
+ @staticmethod
+ def new_custom_shape(type, verts):
+ """
+ Create a new shape that can be passed to :class:`bpy.types.Manipulator.draw_custom_shape`.
- def __prepare__(name, bases, **kwargs):
- return OrderedDictMini() # collections.OrderedDict()
+ :arg type: The type of shape to create in (POINTS, LINES, TRIS, LINE_STRIP).
+ :type type: string
+ :arg verts: Coordinates.
+ :type verts: sequence of of 2D or 3D coordinates.
+ :arg display_name: Optional callback that takes the full path, returns the name to display.
+ :type display_name: Callable that takes a string and returns a string.
+ :return: The newly created shape.
+ :rtype: Undefined (it may change).
+ """
+ from _gawain.types import (
+ Gwn_Batch,
+ Gwn_VertBuf,
+ Gwn_VertFormat,
+ )
+ dims = len(verts[0])
+ if dims not in {2, 3}:
+ raise ValueError("Expected 2D or 3D vertex")
+ fmt = Gwn_VertFormat()
+ pos_id = fmt.attr_add(id="pos", comp_type='F32', len=dims, fetch_mode='FLOAT')
+ vbo = Gwn_VertBuf(len=len(verts), format=fmt)
+ vbo.fill(id=pos_id, data=verts)
+ batch = Gwn_Batch(type=type, buf=vbo)
+ return (batch, dims)
# Only defined so operators members can be used by accessing self.order
# with doc generation 'self.properties.bl_rna.properties' can fail
-class Operator(StructRNA, metaclass=OrderedMeta):
+class Operator(StructRNA):
__slots__ = ()
def __getattribute__(self, attr):
@@ -626,7 +688,7 @@ class Operator(StructRNA, metaclass=OrderedMeta):
if attr not in ignore}
-class Macro(StructRNA, metaclass=OrderedMeta):
+class Macro(StructRNA):
# bpy_types is imported before ops is defined
# so we have to do a local import on each run
__slots__ = ()
@@ -666,7 +728,23 @@ class _GenericUI:
# ensure menus always get default context
operator_context_default = self.layout.operator_context
+ # Support filtering out by owner
+ workspace = context.workspace
+ if workspace.use_filter_by_owner:
+ owner_names = {owner_id.name for owner_id in workspace.owner_ids}
+ else:
+ owner_names = None
+
for func in draw_ls._draw_funcs:
+
+ # Begin 'owner_id' filter.
+ if owner_names is not None:
+ owner_id = getattr(func, "_owner", None)
+ if owner_id is not None:
+ if func._owner not in owner_names:
+ continue
+ # End 'owner_id' filter.
+
# so bad menu functions don't stop
# the entire menu from drawing
try:
@@ -682,6 +760,13 @@ class _GenericUI:
return draw_funcs
+ @staticmethod
+ def _dyn_owner_apply(draw_func):
+ from _bpy import _bl_owner_id_get
+ owner_id = _bl_owner_id_get()
+ if owner_id is not None:
+ draw_func._owner = owner_id
+
@classmethod
def is_extended(cls):
return bool(getattr(cls.draw, "_draw_funcs", None))
@@ -693,6 +778,7 @@ class _GenericUI:
takes the same arguments as the menus draw function
"""
draw_funcs = cls._dyn_ui_initialize()
+ cls._dyn_owner_apply(draw_func)
draw_funcs.append(draw_func)
@classmethod
@@ -702,6 +788,7 @@ class _GenericUI:
the menus draw function
"""
draw_funcs = cls._dyn_ui_initialize()
+ cls._dyn_owner_apply(draw_func)
draw_funcs.insert(0, draw_func)
@classmethod
@@ -731,7 +818,8 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
def path_menu(self, searchpaths, operator, *,
props_default=None, prop_filepath="filepath",
- filter_ext=None, filter_path=None, display_name=None):
+ filter_ext=None, filter_path=None, display_name=None,
+ add_operator=None):
"""
Populate a menu from a list of paths.
@@ -777,12 +865,16 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
files.sort()
+ col = layout.column(align=True)
+
for f, filepath in files:
# Intentionally pass the full path to 'display_name' callback,
# since the callback may want to use part a directory in the name.
- props = layout.operator(
+ row = col.row(align=True)
+ name = display_name(filepath) if display_name else bpy.path.display_name(f)
+ props = row.operator(
operator,
- text=display_name(filepath) if display_name else bpy.path.display_name(f),
+ text=name,
translate=False,
)
@@ -794,6 +886,24 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
if operator == "script.execute_preset":
props.menu_idname = self.bl_idname
+ if add_operator:
+ props = row.operator(add_operator, text="", icon='ZOOMOUT')
+ props.name = name
+ props.remove_name = True
+
+ if add_operator:
+ wm = bpy.data.window_managers[0]
+
+ layout.separator()
+ row = layout.row()
+
+ sub = row.row()
+ sub.emboss = 'NORMAL'
+ sub.prop(wm, "preset_name", text="")
+
+ props = row.operator(add_operator, text="", icon='ZOOMIN')
+ props.name = wm.preset_name
+
def draw_preset(self, context):
"""
Define these on the subclass:
@@ -801,23 +911,27 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
- preset_subdir (string)
Optionally:
+ - preset_add_operator (string)
- preset_extensions (set of strings)
- preset_operator_defaults (dict of keyword args)
"""
import bpy
ext_valid = getattr(self, "preset_extensions", {".py", ".xml"})
props_default = getattr(self, "preset_operator_defaults", None)
+ add_operator = getattr(self, "preset_add_operator", None)
self.path_menu(bpy.utils.preset_paths(self.preset_subdir),
self.preset_operator,
props_default=props_default,
- filter_ext=lambda ext: ext.lower() in ext_valid)
+ filter_ext=lambda ext: ext.lower() in ext_valid,
+ add_operator=add_operator)
@classmethod
def draw_collapsible(cls, context, layout):
# helper function for (optionally) collapsed header menus
# only usable within headers
if context.area.show_menus:
- cls.draw_menus(layout, context)
+ # Align menus to space them closely.
+ cls.draw_menus(layout.row(align=True), context)
else:
layout.menu(cls.__name__, icon='COLLAPSEMENU')
diff --git a/release/scripts/modules/keyingsets_utils.py b/release/scripts/modules/keyingsets_utils.py
index de8da450125..35bae1e69b7 100644
--- a/release/scripts/modules/keyingsets_utils.py
+++ b/release/scripts/modules/keyingsets_utils.py
@@ -153,8 +153,10 @@ def get_transform_generators_base_info(data):
# no path in this case
path = ""
- # data on ID-blocks directly should get grouped by the KeyingSet
- grouping = None
+ # transform data on ID-blocks directly should get grouped under a
+ # hardcoded label ("Object Transforms") so that they get grouped
+ # consistently when keyframed directly
+ grouping = "Object Transforms"
else:
# get the path to the ID-block
path = data.path_from_id()
diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index e50922593de..bdb0751c973 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -129,6 +129,7 @@ def draw(layout, context, context_member, property_type, use_edit=True):
props.data_path = context_member
del row
+ show_developer_ui = context.user_preferences.view.show_developer_ui
rna_properties = {prop.identifier for prop in rna_item.bl_rna.properties if prop.is_runtime} if items else None
for key, val in items:
@@ -136,6 +137,12 @@ def draw(layout, context, context_member, property_type, use_edit=True):
if key == '_RNA_UI':
continue
+ is_rna = (key in rna_properties)
+
+ # only show API defined for developers
+ if is_rna and not show_developer_ui:
+ continue
+
row = layout.row()
to_dict = getattr(val, "to_dict", None)
to_list = getattr(val, "to_list", None)
@@ -161,8 +168,6 @@ def draw(layout, context, context_member, property_type, use_edit=True):
row.label(text=key, translate=False)
# explicit exception for arrays
- is_rna = (key in rna_properties)
-
if to_dict or to_list:
row.label(text=val_draw, translate=False)
else:
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index e447d8a4dc5..53b3197fca3 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -185,14 +185,19 @@ def write_sysinfo(filepath):
output.write("version:\t%r\n" % (bgl.glGetString(bgl.GL_VERSION)))
output.write("extensions:\n")
- glext = sorted(bgl.glGetString(bgl.GL_EXTENSIONS).split())
+ limit = bgl.Buffer(bgl.GL_INT, 1)
+ bgl.glGetIntegerv(bgl.GL_NUM_EXTENSIONS, limit)
+
+ glext = []
+ for i in range(limit[0]):
+ glext.append(bgl.glGetStringi(bgl.GL_EXTENSIONS, i))
+
+ glext = sorted(glext)
+
for l in glext:
output.write("\t%s\n" % l)
output.write(title("Implementation Dependent OpenGL Limits"))
- limit = bgl.Buffer(bgl.GL_INT, 1)
- bgl.glGetIntegerv(bgl.GL_MAX_TEXTURE_UNITS, limit)
- output.write("Maximum Fixed Function Texture Units:\t%d\n" % limit[0])
bgl.glGetIntegerv(bgl.GL_MAX_ELEMENTS_VERTICES, limit)
output.write("Maximum DrawElements Vertices:\t%d\n" % limit[0])
bgl.glGetIntegerv(bgl.GL_MAX_ELEMENTS_INDICES, limit)
diff --git a/release/scripts/presets/interface_theme/24x_blues.xml b/release/scripts/presets/interface_theme/24x_blues.xml
index 36cfeeb5980..18b866eeb0f 100644
--- a/release/scripts/presets/interface_theme/24x_blues.xml
+++ b/release/scripts/presets/interface_theme/24x_blues.xml
@@ -253,7 +253,7 @@
text_keyframe="#ddd700"
camera="#000000"
empty="#000000"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
vertex="#000000"
vertex_select="#ff8500"
diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml
index 1636f5b5cf6..464625d0ba5 100644
--- a/release/scripts/presets/interface_theme/back_to_black.xml
+++ b/release/scripts/presets/interface_theme/back_to_black.xml
@@ -253,7 +253,7 @@
text_keyframe="#ddd700"
camera="#535353"
empty="#535353"
- lamp="#fff0d328"
+ light="#fff0d328"
speaker="#535353"
vertex="#72cfdd"
vertex_select="#ff8500"
diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml
index 818e557adf0..d0459e02115 100644
--- a/release/scripts/presets/interface_theme/blender_24x.xml
+++ b/release/scripts/presets/interface_theme/blender_24x.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
camera="#000000"
view_overlay="#000000"
diff --git a/release/scripts/presets/interface_theme/blender_27x.xml b/release/scripts/presets/interface_theme/blender_27x.xml
new file mode 100644
index 00000000000..db9d042ae55
--- /dev/null
+++ b/release/scripts/presets/interface_theme/blender_27x.xml
@@ -0,0 +1,1242 @@
+<bpy>
+ <Theme>
+ <user_interface>
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
+ icon_alpha="1"
+ icon_saturation="1"
+ widget_emboss="#ffffff05"
+ editor_outline="#3f3f3f"
+ axis_x="#dc0000"
+ axis_y="#00dc00"
+ axis_z="#0000dc"
+ manipulator_hi="#ffffff"
+ manipulator_primary="#deff0d"
+ manipulator_secondary="#00ffff"
+ manipulator_a="#177f17"
+ manipulator_b="#7f1717">
+ <wcol_regular>
+ <ThemeWidgetColors outline="#191919"
+ inner="#999999ff"
+ inner_sel="#646464ff"
+ item="#191919ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5">
+ </ThemeWidgetColors>
+ </wcol_regular>
+ <wcol_tool>
+ <ThemeWidgetColors outline="#191919"
+ inner="#999999ff"
+ inner_sel="#646464ff"
+ item="#191919ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="15"
+ shadedown="-15"
+ roundness="0.4">
+ </ThemeWidgetColors>
+ </wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors outline="#000000"
+ inner="#464646ff"
+ inner_sel="#ccccccff"
+ item="#000000ff"
+ text="#ffffff"
+ text_sel="#333333"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.6">
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
+ <wcol_radio>
+ <ThemeWidgetColors outline="#000000"
+ inner="#464646ff"
+ inner_sel="#5680c2ff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#000000"
+ show_shaded="TRUE"
+ shadetop="15"
+ shadedown="-15"
+ roundness="0.4">
+ </ThemeWidgetColors>
+ </wcol_radio>
+ <wcol_text>
+ <ThemeWidgetColors outline="#191919"
+ inner="#999999ff"
+ inner_sel="#999999ff"
+ item="#5a5a5aff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="0"
+ shadedown="25"
+ roundness="0.4">
+ </ThemeWidgetColors>
+ </wcol_text>
+ <wcol_option>
+ <ThemeWidgetColors outline="#000000"
+ inner="#464646ff"
+ inner_sel="#464646ff"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="15"
+ shadedown="-15"
+ roundness="0.666666">
+ </ThemeWidgetColors>
+ </wcol_option>
+ <wcol_toggle>
+ <ThemeWidgetColors outline="#191919"
+ inner="#999999ff"
+ inner_sel="#646464ff"
+ item="#191919ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5">
+ </ThemeWidgetColors>
+ </wcol_toggle>
+ <wcol_num>
+ <ThemeWidgetColors outline="#191919"
+ inner="#b4b4b4ff"
+ inner_sel="#999999ff"
+ item="#5a5a5aff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-20"
+ shadedown="0"
+ roundness="1">
+ </ThemeWidgetColors>
+ </wcol_num>
+ <wcol_numslider>
+ <ThemeWidgetColors outline="#191919"
+ inner="#b4b4b4ff"
+ inner_sel="#999999ff"
+ item="#808080ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="-20"
+ shadedown="0"
+ roundness="1">
+ </ThemeWidgetColors>
+ </wcol_numslider>
+ <wcol_box>
+ <ThemeWidgetColors outline="#191919"
+ inner="#808080ff"
+ inner_sel="#646464ff"
+ item="#191919ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4">
+ </ThemeWidgetColors>
+ </wcol_box>
+ <wcol_menu>
+ <ThemeWidgetColors outline="#000000"
+ inner="#464646ff"
+ inner_sel="#464646ff"
+ item="#ffffffff"
+ text="#ffffff"
+ text_sel="#cccccc"
+ show_shaded="TRUE"
+ shadetop="15"
+ shadedown="-15"
+ roundness="0.4">
+ </ThemeWidgetColors>
+ </wcol_menu>
+ <wcol_pulldown>
+ <ThemeWidgetColors outline="#000000"
+ inner="#3f3f3fff"
+ inner_sel="#5680c2ff"
+ item="#ffffffff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.4">
+ </ThemeWidgetColors>
+ </wcol_pulldown>
+ <wcol_menu_back>
+ <ThemeWidgetColors outline="#000000"
+ inner="#191919e6"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.5">
+ </ThemeWidgetColors>
+ </wcol_menu_back>
+ <wcol_pie_menu>
+ <ThemeWidgetColors outline="#0a0a0a"
+ inner="#191919e6"
+ inner_sel="#8c8c8cff"
+ item="#2d2d2de6"
+ text="#a0a0a0"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="10"
+ shadedown="-10"
+ roundness="1">
+ </ThemeWidgetColors>
+ </wcol_pie_menu>
+ <wcol_tooltip>
+ <ThemeWidgetColors outline="#000000"
+ inner="#191919e6"
+ inner_sel="#2d2d2de6"
+ item="#646464ff"
+ text="#ffffff"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="25"
+ shadedown="-20"
+ roundness="0.5">
+ </ThemeWidgetColors>
+ </wcol_tooltip>
+ <wcol_menu_item>
+ <ThemeWidgetColors outline="#000000"
+ inner="#00000000"
+ inner_sel="#5680c2ff"
+ item="#acacac80"
+ text="#ffffff"
+ text_sel="#000000"
+ show_shaded="TRUE"
+ shadetop="38"
+ shadedown="0"
+ roundness="0.5">
+ </ThemeWidgetColors>
+ </wcol_menu_item>
+ <wcol_scroll>
+ <ThemeWidgetColors outline="#323232"
+ inner="#505050b4"
+ inner_sel="#646464b4"
+ item="#808080ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="TRUE"
+ shadetop="5"
+ shadedown="-5"
+ roundness="1">
+ </ThemeWidgetColors>
+ </wcol_scroll>
+ <wcol_progress>
+ <ThemeWidgetColors outline="#000000"
+ inner="#bebebeff"
+ inner_sel="#646464b4"
+ item="#808080ff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5">
+ </ThemeWidgetColors>
+ </wcol_progress>
+ <wcol_list_item>
+ <ThemeWidgetColors outline="#000000"
+ inner="#00000000"
+ inner_sel="#5680c2ff"
+ item="#5a5a5aff"
+ text="#000000"
+ text_sel="#ffffff"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.4">
+ </ThemeWidgetColors>
+ </wcol_list_item>
+ <wcol_state>
+ <ThemeWidgetStateColors inner_anim="#73be4c"
+ inner_anim_sel="#5aa633"
+ inner_key="#f0eb64"
+ inner_key_sel="#d7d34b"
+ inner_driven="#b400ff"
+ inner_driven_sel="#9900e6"
+ inner_overridden="#000000"
+ inner_overridden_sel="#000000"
+ blend="0.5">
+ </ThemeWidgetStateColors>
+ </wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors outline="#3c3c3c"
+ inner="#535353ff"
+ inner_sel="#727272ff"
+ item="#5a5a5aff"
+ text="#000000"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5">
+ </ThemeWidgetColors>
+ </wcol_tab>
+ </ThemeUserInterface>
+ </user_interface>
+ <view_3d>
+ <ThemeView3D grid="#404040"
+ clipping_border_3d="#313131ff"
+ wire="#000000"
+ wire_edit="#000000"
+ gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ text_grease_pencil="#b5e61d"
+ object_selected="#f15800"
+ object_active="#ffaa40"
+ text_keyframe="#ddd700"
+ camera="#000000"
+ empty="#000000"
+ light="#00000028"
+ speaker="#000000"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="3"
+ vertex_bevel="#00a5ff"
+ vertex_unreferenced="#000000"
+ edge_select="#ffa000"
+ edge_seam="#db2512"
+ edge_sharp="#00ffff"
+ edge_crease="#cc0099"
+ edge_bevel="#00a5ff"
+ edge_facesel="#4b4b4b"
+ freestyle_edge_mark="#7fff7f"
+ face="#00000012"
+ face_select="#ff85003c"
+ face_dot="#ff8500"
+ facedot_size="4"
+ freestyle_face_mark="#7fff7f33"
+ nurb_uline="#909000"
+ nurb_vline="#803060"
+ nurb_sel_uline="#f0ff40"
+ nurb_sel_vline="#f090a0"
+ act_spline="#db2512"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ lastsel_point="#ffffff"
+ extra_edge_len="#200000"
+ extra_edge_angle="#000000"
+ extra_face_angle="#000080"
+ extra_face_area="#002000"
+ editmesh_active="#ffffff80"
+ normal="#22dddd"
+ vertex_normal="#2361dd"
+ split_normal="#dd23dd"
+ bone_pose="#50c8ff"
+ bone_pose_active="#8cffff"
+ bone_solid="#c8c8c8"
+ bundle_solid="#c8c8c8"
+ camera_path="#000000"
+ skin_root="#b44d4d"
+ view_overlay="#000000"
+ transform="#ffffff"
+ frame_current="#60c040"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1">
+ <space>
+ <ThemeSpaceGradient title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#72727280"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <gradients>
+ <ThemeGradientColors show_grad="FALSE"
+ gradient="#000000"
+ high_gradient="#393939">
+ </ThemeGradientColors>
+ </gradients>
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGradient>
+ </space>
+ </ThemeView3D>
+ </view_3d>
+ <graph_editor>
+ <ThemeGraphEditor grid="#5e5e5e"
+ frame_current="#60c040"
+ window_sliders="#969696"
+ channels_region="#707070"
+ dopesheet_channel="#52606e"
+ dopesheet_subchannel="#7c8996"
+ channel_group="#4f6549"
+ active_channels_group="#87b17d"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="6"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_vect="#409030"
+ handle_sel_vect="#40c030"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#994030"
+ handle_sel_auto_clamped="#f0af90"
+ lastsel_point="#ffffff"
+ handle_vertex="#000000"
+ handle_vertex_select="#ff8500"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#6b6b6b"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeGraphEditor>
+ </graph_editor>
+ <file_browser>
+ <ThemeFileBrowser selected_file="#ff8c19">
+ <space>
+ <ThemeSpaceGeneric back="#4c4c4c"
+ title="#000000"
+ text="#fafafa"
+ text_hi="#0f0f0f"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeFileBrowser>
+ </file_browser>
+ <nla_editor>
+ <ThemeNLAEditor grid="#5e5e5e"
+ view_sliders="#969696"
+ active_action="#cc701a66"
+ active_action_unset="#9987614d"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ transition_strips="#1c2630"
+ transition_strips_selected="#2e75db"
+ meta_strips="#332642"
+ meta_strips_selected="#692196"
+ sound_strips="#2b3d3d"
+ sound_strips_selected="#1f7a7a"
+ tweak="#4df31a"
+ tweak_duplicate="#d90000"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ frame_current="#60c040">
+ <space>
+ <ThemeSpaceGeneric back="#6b6b6b"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNLAEditor>
+ </nla_editor>
+ <dopesheet_editor>
+ <ThemeDopeSheet grid="#5e5e5e"
+ frame_current="#60c040"
+ value_sliders="#000000"
+ view_sliders="#969696"
+ dopesheet_channel="#52606e"
+ dopesheet_subchannel="#7c8996"
+ channels="#707070"
+ channels_selected="#60c040"
+ channel_group="#4f6549"
+ active_channels_group="#87b17d"
+ long_key="#0c0a0a"
+ long_key_selected="#ff8c00"
+ keyframe="#e8e8e8"
+ keyframe_selected="#ffbe32"
+ keyframe_extreme="#e8b3cc"
+ keyframe_extreme_selected="#f28080"
+ keyframe_breakdown="#b3dbe8"
+ keyframe_breakdown_selected="#54bfed"
+ keyframe_jitter="#94e575"
+ keyframe_jitter_selected="#61c042"
+ keyframe_border="#000000ff"
+ keyframe_border_selected="#000000ff"
+ keyframe_scale_factor="1"
+ summary="#cc701a66">
+ <space>
+ <ThemeSpaceGeneric back="#6b6b6b"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeDopeSheet>
+ </dopesheet_editor>
+ <image_editor>
+ <ThemeImageEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ vertex="#000000"
+ vertex_select="#ff8500"
+ vertex_size="3"
+ vertex_bevel="#000000"
+ vertex_unreferenced="#000000"
+ face="#ffffff0a"
+ face_select="#ff85003c"
+ face_dot="#ff8500"
+ facedot_size="3"
+ freestyle_face_mark="#00000000"
+ editmesh_active="#ffffff80"
+ wire_edit="#c0c0c0"
+ edge_select="#ff8500"
+ scope_back="#0000004c"
+ preview_stitch_face="#7f7f0033"
+ preview_stitch_edge="#ff00ff33"
+ preview_stitch_vert="#0000ff33"
+ preview_stitch_stitchable="#00ff00ff"
+ preview_stitch_unstitchable="#ff0000ff"
+ preview_stitch_active="#00000000"
+ uv_shadow="#707070ff"
+ uv_others="#606060ff"
+ frame_current="#60c040"
+ metadatabg="#000000"
+ metadatatext="#ffffff"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5"
+ paint_curve_handle="#7fff7f7f"
+ paint_curve_pivot="#ff7f7f7f">
+ <space>
+ <ThemeSpaceGeneric back="#353535"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#72727280"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeImageEditor>
+ </image_editor>
+ <sequence_editor>
+ <ThemeSequenceEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ grid="#404040"
+ window_sliders="#a0a0a0"
+ movie_strip="#516987"
+ movieclip_strip="#20208f"
+ image_strip="#6d5881"
+ scene_strip="#4e983e"
+ audio_strip="#2e8f8f"
+ effect_strip="#a9547c"
+ transition_strip="#a25f6f"
+ meta_strip="#6d9183"
+ text_strip="#a29700"
+ frame_current="#60c040"
+ keyframe="#ff8500"
+ draw_action="#50c8ff"
+ preview_back="#000000"
+ metadatabg="#000000"
+ metadatatext="#ffffff">
+ <space>
+ <ThemeSpaceGeneric back="#747474"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#72727280"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeSequenceEditor>
+ </sequence_editor>
+ <properties>
+ <ThemeProperties>
+ <space>
+ <ThemeSpaceGeneric back="#727272"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeProperties>
+ </properties>
+ <text_editor>
+ <ThemeTextEditor line_numbers_background="#404040"
+ selected_text="#c67777"
+ cursor="#ff0000"
+ syntax_builtin="#800050"
+ syntax_symbols="#4c4c4c"
+ syntax_special="#5f5f00"
+ syntax_preprocessor="#32008c"
+ syntax_reserved="#8c3c00"
+ syntax_comment="#006432"
+ syntax_string="#640000"
+ syntax_numbers="#0000c8">
+ <space>
+ <ThemeSpaceGeneric back="#999999"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTextEditor>
+ </text_editor>
+ <node_editor>
+ <ThemeNodeEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ node_selected="#f15800"
+ node_active="#ffaa40"
+ wire="#000000"
+ wire_inner="#737373"
+ wire_select="#ffffff"
+ selected_text="#7f7070"
+ node_backdrop="#9b9b9ba0"
+ converter_node="#686a75"
+ color_node="#6c696f"
+ group_node="#69756e"
+ group_socket_node="#dfca35"
+ frame_node="#9b9b9ba0"
+ matte_node="#977474"
+ distor_node="#749797"
+ noodle_curving="5"
+ input_node="#646464"
+ output_node="#646464"
+ filter_node="#6c696f"
+ vector_node="#6c696f"
+ texture_node="#6c696f"
+ shader_node="#6c696f"
+ script_node="#6c696f"
+ pattern_node="#6c696f"
+ layout_node="#6c696f">
+ <space>
+ <ThemeSpaceGeneric back="#393939"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#72727280"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#a5a5a5"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeNodeEditor>
+ </node_editor>
+ <outliner>
+ <ThemeOutliner match="#337f33"
+ selected_highlight="#82878c">
+ <space>
+ <ThemeSpaceGeneric back="#727272"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeOutliner>
+ </outliner>
+ <info>
+ <ThemeInfo info_selected="#6080ff"
+ info_selected_text="#ffffff"
+ info_error="#dc0000"
+ info_error_text="#000000"
+ info_warning="#dc8060"
+ info_warning_text="#000000"
+ info_info="#00aa00"
+ info_info_text="#000000"
+ info_debug="#c4c4c4"
+ info_debug_text="#000000">
+ <space>
+ <ThemeSpaceGeneric back="#727272"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeInfo>
+ </info>
+ <user_preferences>
+ <ThemeUserPreferences>
+ <space>
+ <ThemeSpaceGeneric back="#727272"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeUserPreferences>
+ </user_preferences>
+ <console>
+ <ThemeConsole line_output="#6080ff"
+ line_input="#ffffff"
+ line_info="#00aa00"
+ line_error="#dc6060"
+ cursor="#dc6060"
+ select="#ffffff30">
+ <space>
+ <ThemeSpaceGeneric back="#000000"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#727272ff"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeConsole>
+ </console>
+ <clip_editor>
+ <ThemeClipEditor gp_vertex="#000000"
+ gp_vertex_select="#ff8500"
+ gp_vertex_size="3"
+ marker_outline="#000000"
+ marker="#7f7f00"
+ active_marker="#ffffff"
+ selected_marker="#ffff00"
+ disabled_marker="#7f0000"
+ locked_marker="#7f7f7f"
+ path_before="#ff0000"
+ path_after="#0000ff"
+ frame_current="#60c040"
+ strips="#0c0a0a"
+ strips_selected="#ff8c00"
+ handle_free="#000000"
+ handle_auto="#909000"
+ handle_align="#803060"
+ handle_sel_free="#000000"
+ handle_sel_auto="#f0ff40"
+ handle_sel_align="#f090a0"
+ handle_auto_clamped="#000000"
+ handle_sel_auto_clamped="#000000"
+ handle_vertex="#000000"
+ handle_vertex_select="#ffff00"
+ handle_vertex_size="5">
+ <space>
+ <ThemeSpaceGeneric back="#393939"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#72727280"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000019"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ <space_list>
+ <ThemeSpaceListGeneric list="#666666"
+ list_title="#000000"
+ list_text="#000000"
+ list_text_hi="#ffffff">
+ </ThemeSpaceListGeneric>
+ </space_list>
+ </ThemeClipEditor>
+ </clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric back="#727272"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#535353ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#72727280"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000000"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric back="#393939"
+ title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#727272ff"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#72727280"
+ button_title="#000000"
+ button_text="#000000"
+ button_text_hi="#ffffff"
+ tab_active="#727272"
+ tab_inactive="#535353"
+ tab_back="#404040ff"
+ tab_outline="#3c3c3c">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ sub_back="#00000000"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
+ <bone_color_sets>
+ <ThemeBoneColorSet normal="#9a0000"
+ select="#bd1111"
+ active="#f70a0a"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f74018"
+ select="#f66913"
+ active="#fa9900"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e9109"
+ select="#59b70b"
+ active="#83ef1d"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#0a3694"
+ select="#3667df"
+ active="#5ec1ef"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#a9294e"
+ select="#c1416a"
+ active="#f05d91"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#430c78"
+ select="#543aa3"
+ active="#8764d5"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#24785a"
+ select="#3c9579"
+ active="#6fb6ab"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#4b707c"
+ select="#6a8691"
+ active="#9bc2cd"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#f4c90c"
+ select="#eec236"
+ active="#f3ff00"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#1e2024"
+ select="#484c56"
+ active="#ffffff"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6f2f6a"
+ select="#9845be"
+ active="#d330d6"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#6c8e22"
+ select="#7fb022"
+ active="#bbef5b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#8d8d8d"
+ select="#b0b0b0"
+ active="#dedede"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#834326"
+ select="#8b5811"
+ active="#bd6a11"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#08310e"
+ select="#1c430b"
+ active="#34622b"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ <ThemeBoneColorSet normal="#000000"
+ select="#000000"
+ active="#000000"
+ show_colored_constraints="FALSE">
+ </ThemeBoneColorSet>
+ </bone_color_sets>
+ </Theme>
+ <ThemeStyle>
+ <panel_title>
+ <ThemeFontStyle points="12"
+ font_kerning_style="FITTED"
+ shadow="1"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </panel_title>
+ <widget_label>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="3"
+ shadow_offset_x="0"
+ shadow_offset_y="-1"
+ shadow_alpha="0.15"
+ shadow_value="1">
+ </ThemeFontStyle>
+ </widget_label>
+ <widget>
+ <ThemeFontStyle points="11"
+ font_kerning_style="FITTED"
+ shadow="0"
+ shadow_offset_x="0"
+ shadow_offset_y="0"
+ shadow_alpha="0.25"
+ shadow_value="0">
+ </ThemeFontStyle>
+ </widget>
+ </ThemeStyle>
+</bpy>
diff --git a/release/scripts/presets/interface_theme/dark_blue_gradient.xml b/release/scripts/presets/interface_theme/dark_blue_gradient.xml
index d226f8531b2..589aeab3a50 100644
--- a/release/scripts/presets/interface_theme/dark_blue_gradient.xml
+++ b/release/scripts/presets/interface_theme/dark_blue_gradient.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
camera="#000000"
view_overlay="#000000"
diff --git a/release/scripts/presets/interface_theme/default++.xml b/release/scripts/presets/interface_theme/default++.xml
index 413fbc1aa71..3599a094381 100644
--- a/release/scripts/presets/interface_theme/default++.xml
+++ b/release/scripts/presets/interface_theme/default++.xml
@@ -253,7 +253,7 @@
text_keyframe="#ddd700"
camera="#000000"
empty="#000000"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
vertex="#000000"
vertex_select="#ff8500"
diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml
index b9292856fe9..51af13a6009 100644
--- a/release/scripts/presets/interface_theme/elsyiun.xml
+++ b/release/scripts/presets/interface_theme/elsyiun.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
camera="#000000"
view_overlay="#000000"
diff --git a/release/scripts/presets/interface_theme/flatty_light.xml b/release/scripts/presets/interface_theme/flatty_light.xml
index c89cbd92ca0..497b6575731 100644
--- a/release/scripts/presets/interface_theme/flatty_light.xml
+++ b/release/scripts/presets/interface_theme/flatty_light.xml
@@ -5,10 +5,17 @@
menu_shadow_width="4"
icon_file=""
icon_alpha="1"
+ icon_saturation="0.3"
widget_emboss="#00000005"
- axis_x="#dc0000"
- axis_y="#00dc00"
- axis_z="#0000dc">
+ editor_outline="#313338"
+ axis_x="#ff3352"
+ axis_y="#8bdc00"
+ axis_z="#046bdc"
+ manipulator_hi="#ffffff"
+ manipulator_primary="#ffd842"
+ manipulator_secondary="#43c2ff"
+ manipulator_a="#2b9757"
+ manipulator_b="#c43164">
<wcol_regular>
<ThemeWidgetColors outline="#9d9d9d"
inner="#b3b3b3ff"
@@ -18,7 +25,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="0"
- shadedown="-5">
+ shadedown="-5"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_regular>
<wcol_tool>
@@ -30,9 +38,23 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="0"
- shadedown="-5">
+ shadedown="-5"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_tool>
+ <wcol_toolbar_item>
+ <ThemeWidgetColors outline="#808080"
+ inner="#b3b3b3ff"
+ inner_sel="#dbdbdbff"
+ item="#1a1a1aff"
+ text="#1a1a1a"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.5">
+ </ThemeWidgetColors>
+ </wcol_toolbar_item>
<wcol_radio>
<ThemeWidgetColors outline="#4d4d4d"
inner="#464646ff"
@@ -42,7 +64,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="5"
- shadedown="-5">
+ shadedown="-5"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_radio>
<wcol_text>
@@ -54,11 +77,12 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="-8"
- shadedown="0">
+ shadedown="0"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_text>
<wcol_option>
- <ThemeWidgetColors outline="#999999"
+ <ThemeWidgetColors outline="#333333"
inner="#434343ff"
inner_sel="#5680c2ff"
item="#ffffffff"
@@ -66,11 +90,12 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="0"
- shadedown="-15">
+ shadedown="-15"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_option>
<wcol_toggle>
- <ThemeWidgetColors outline="#808080"
+ <ThemeWidgetColors outline="#333333"
inner="#b3b3b3ff"
inner_sel="#5680c2ff"
item="#191919ff"
@@ -78,7 +103,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="0"
- shadedown="0">
+ shadedown="0"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_toggle>
<wcol_num>
@@ -90,7 +116,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="-10"
- shadedown="0">
+ shadedown="0"
+ roundness="0.7">
</ThemeWidgetColors>
</wcol_num>
<wcol_numslider>
@@ -102,7 +129,8 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-4"
- shadedown="0">
+ shadedown="0"
+ roundness="0.7">
</ThemeWidgetColors>
</wcol_numslider>
<wcol_box>
@@ -114,7 +142,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="0"
- shadedown="0">
+ shadedown="0"
+ roundness="0.4">
</ThemeWidgetColors>
</wcol_box>
<wcol_menu>
@@ -126,19 +155,21 @@
text_sel="#cccccc"
show_shaded="FALSE"
shadetop="10"
- shadedown="-10">
+ shadedown="-10"
+ roundness="0.4">
</ThemeWidgetColors>
</wcol_menu>
<wcol_pulldown>
<ThemeWidgetColors outline="#000000"
- inner="#3f3f3fff"
+ inner="#e6e6e699"
inner_sel="#5680c2ff"
item="#ffffffff"
text="#000000"
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="25"
- shadedown="-20">
+ shadedown="-20"
+ roundness="0.3">
</ThemeWidgetColors>
</wcol_pulldown>
<wcol_menu_back>
@@ -150,7 +181,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="25"
- shadedown="-20">
+ shadedown="-20"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_menu_back>
<wcol_pie_menu>
@@ -162,7 +194,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="10"
- shadedown="-10">
+ shadedown="-10"
+ roundness="1">
</ThemeWidgetColors>
</wcol_pie_menu>
<wcol_tooltip>
@@ -174,7 +207,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="25"
- shadedown="-20">
+ shadedown="-20"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_tooltip>
<wcol_menu_item>
@@ -186,7 +220,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="38"
- shadedown="0">
+ shadedown="0"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_menu_item>
<wcol_scroll>
@@ -198,7 +233,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="5"
- shadedown="-5">
+ shadedown="-5"
+ roundness="1">
</ThemeWidgetColors>
</wcol_scroll>
<wcol_progress>
@@ -210,7 +246,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="0"
- shadedown="0">
+ shadedown="0"
+ roundness="0.5">
</ThemeWidgetColors>
</wcol_progress>
<wcol_list_item>
@@ -222,7 +259,8 @@
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="0"
- shadedown="0">
+ shadedown="0"
+ roundness="0.4">
</ThemeWidgetColors>
</wcol_list_item>
<wcol_state>
@@ -232,9 +270,24 @@
inner_key_sel="#d7d34b"
inner_driven="#b400ff"
inner_driven_sel="#9900e6"
+ inner_overridden="#6bf3cc"
+ inner_overridden_sel="#5fd9b6"
blend="0.5">
</ThemeWidgetStateColors>
</wcol_state>
+ <wcol_tab>
+ <ThemeWidgetColors outline="#808080"
+ inner="#8e8e8eff"
+ inner_sel="#b3b3b3ff"
+ item="#28292dff"
+ text="#1a1a1a"
+ text_sel="#000000"
+ show_shaded="FALSE"
+ shadetop="0"
+ shadedown="0"
+ roundness="0.3">
+ </ThemeWidgetColors>
+ </wcol_tab>
</ThemeUserInterface>
</user_interface>
<view_3d>
@@ -248,13 +301,11 @@
text_grease_pencil="#b5e61d"
object_selected="#f15800"
object_active="#ffaa40"
- object_grouped="#004200"
- object_grouped_active="#55bb55"
text_keyframe="#ddd700"
- camera="#000000"
- empty="#000000"
- lamp="#00000028"
- speaker="#000000"
+ camera="#b3b3b3"
+ empty="#b3b3b3"
+ light="#cccccc33"
+ speaker="#b3b3b3"
vertex="#000000"
vertex_select="#ff8500"
vertex_size="3"
@@ -310,10 +361,10 @@
<ThemeSpaceGradient title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#999999"
+ header="#99999900"
header_text="#000000"
header_text_hi="#ffffff"
- button="#999999e6"
+ button="#99999900"
button_title="#1a1a1a"
button_text="#000000"
button_text_hi="#ffffff"
@@ -329,7 +380,7 @@
</gradients>
<panelcolors>
<ThemePanelColors header="#c2c2c2ea"
- back="#99999980"
+ back="#999999cc"
show_header="TRUE"
show_back="TRUE">
</ThemePanelColors>
@@ -371,7 +422,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#adadad"
+ header="#adadadff"
header_text="#000000"
header_text_hi="#ffffff"
button="#999999e6"
@@ -407,7 +458,7 @@
title="#000000"
text="#eeeeee"
text_hi="#ffffff"
- header="#adadad"
+ header="#adadadff"
header_text="#000000"
header_text_hi="#ffffff"
button="#999999e6"
@@ -452,7 +503,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#adadad"
+ header="#adadadff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -482,8 +533,8 @@
</ThemeNLAEditor>
</nla_editor>
<dopesheet_editor>
- <ThemeDopeSheet grid="#5e5e5e"
- frame_current="#60c040"
+ <ThemeDopeSheet grid="#4d4d4d"
+ frame_current="#62b347"
value_sliders="#000000"
view_sliders="#969696"
dopesheet_channel="#2e6399"
@@ -511,7 +562,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#adadad"
+ header="#adadadff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -587,7 +638,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#b3b3b3"
+ header="#b3b3b3ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#999999b3"
@@ -635,7 +686,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#b3b3b3"
+ header="#b3b3b3ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#959595e6"
@@ -664,7 +715,7 @@
title="#181818"
text="#000000"
text_hi="#ffffff"
- header="#b3b3b3"
+ header="#b3b3b3ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -703,7 +754,7 @@
title="#000000"
text="#e6e6e6"
text_hi="#ffffff"
- header="#b3b3b3"
+ header="#b3b3b3ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -725,38 +776,6 @@
</space>
</ThemeTextEditor>
</text_editor>
- <timeline>
- <ThemeTimeline grid="#5b5b5b"
- frame_current="#60c040"
- time_keyframe="#ddd700"
- time_grease_pencil="#b5e61d">
- <space>
- <ThemeSpaceGeneric back="#727272"
- title="#000000"
- text="#000000"
- text_hi="#ffffff"
- header="#a6a6a6"
- header_text="#0b0b0b"
- header_text_hi="#ffffff"
- button="#7272727f"
- button_title="#000000"
- button_text="#000000"
- button_text_hi="#ffffff"
- tab_active="#6697e6"
- tab_inactive="#535353"
- tab_back="#404040ff"
- tab_outline="#3c3c3c">
- <panelcolors>
- <ThemePanelColors header="#c2c2c2ea"
- back="#99999980"
- show_header="TRUE"
- show_back="TRUE">
- </ThemePanelColors>
- </panelcolors>
- </ThemeSpaceGeneric>
- </space>
- </ThemeTimeline>
- </timeline>
<node_editor>
<ThemeNodeEditor gp_vertex="#000000"
gp_vertex_select="#ff8500"
@@ -790,7 +809,7 @@
title="#000000"
text="#0d0d0d"
text_hi="#ffffff"
- header="#b3b3b3"
+ header="#b3b3b3ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -819,44 +838,15 @@
</space_list>
</ThemeNodeEditor>
</node_editor>
- <logic_editor>
- <ThemeLogicEditor>
- <space>
- <ThemeSpaceGeneric back="#646464"
- title="#000000"
- text="#000000"
- text_hi="#ffffff"
- header="#b3b3b3"
- header_text="#000000"
- header_text_hi="#ffffff"
- button="#7272727f"
- button_title="#000000"
- button_text="#000000"
- button_text_hi="#ffffff"
- tab_active="#6697e6"
- tab_inactive="#535353"
- tab_back="#404040ff"
- tab_outline="#3c3c3c">
- <panelcolors>
- <ThemePanelColors header="#c2c2c2ea"
- back="#99999980"
- show_header="TRUE"
- show_back="TRUE">
- </ThemePanelColors>
- </panelcolors>
- </ThemeSpaceGeneric>
- </space>
- </ThemeLogicEditor>
- </logic_editor>
<outliner>
<ThemeOutliner match="#337f33"
selected_highlight="#7297d0">
<space>
- <ThemeSpaceGeneric back="#b3b3b3"
+ <ThemeSpaceGeneric back="#999999"
title="#000000"
- text="#1a1a1a"
+ text="#000000"
text_hi="#ffffff"
- header="#b3b3b3"
+ header="#b3b3b3ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -894,7 +884,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#b3b3b3"
+ header="#b3b3b3ff"
header_text="#1a1a1a"
header_text_hi="#ffffff"
button="#7272727f"
@@ -923,7 +913,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#b3b3b3"
+ header="#b3b3b3ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -957,7 +947,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#727272"
+ header="#727272ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -1010,7 +1000,7 @@
title="#000000"
text="#000000"
text_hi="#ffffff"
- header="#727272"
+ header="#727272ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
@@ -1039,6 +1029,64 @@
</space_list>
</ThemeClipEditor>
</clip_editor>
+ <topbar>
+ <ThemeTopBar>
+ <space>
+ <ThemeSpaceGeneric back="#b3b3b3"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#808080ff"
+ header_text="#eeeeee"
+ header_text_hi="#ffffff"
+ button="#2f303599"
+ button_title="#ffffff"
+ button_text="#ffffff"
+ button_text_hi="#ffffff"
+ tab_active="#446499"
+ tab_inactive="#28292d"
+ tab_back="#28292dff"
+ tab_outline="#28292d">
+ <panelcolors>
+ <ThemePanelColors header="#29282eff"
+ back="#3e3f46ff"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeTopBar>
+ </topbar>
+ <statusbar>
+ <ThemeStatusBar>
+ <space>
+ <ThemeSpaceGeneric back="#393939"
+ title="#ffffff"
+ text="#ffffff"
+ text_hi="#ffffff"
+ header="#adadadff"
+ header_text="#1a1a1a"
+ header_text_hi="#ffffff"
+ button="#2f303500"
+ button_title="#ffffff"
+ button_text="#ffffff"
+ button_text_hi="#ffffff"
+ tab_active="#446499"
+ tab_inactive="#28292d"
+ tab_back="#28292dff"
+ tab_outline="#28292d">
+ <panelcolors>
+ <ThemePanelColors header="#29282eff"
+ back="#3e3f46ff"
+ show_header="TRUE"
+ show_back="TRUE">
+ </ThemePanelColors>
+ </panelcolors>
+ </ThemeSpaceGeneric>
+ </space>
+ </ThemeStatusBar>
+ </statusbar>
<bone_color_sets>
<ThemeBoneColorSet normal="#9a0000"
select="#bd1111"
diff --git a/release/scripts/presets/interface_theme/graph.xml b/release/scripts/presets/interface_theme/graph.xml
index a032d8bd3b2..904fcdf41ec 100644
--- a/release/scripts/presets/interface_theme/graph.xml
+++ b/release/scripts/presets/interface_theme/graph.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
camera="#8d8c8d"
view_overlay="#000000"
diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml
index 4b24abc5fa7..1ca52b76253 100644
--- a/release/scripts/presets/interface_theme/hexagon.xml
+++ b/release/scripts/presets/interface_theme/hexagon.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
camera="#000000"
view_overlay="#000000"
diff --git a/release/scripts/presets/interface_theme/modern_minimalist.xml b/release/scripts/presets/interface_theme/modern_minimalist.xml
index 8ba9402ecdb..3b982514f4f 100644
--- a/release/scripts/presets/interface_theme/modern_minimalist.xml
+++ b/release/scripts/presets/interface_theme/modern_minimalist.xml
@@ -253,7 +253,7 @@
text_keyframe="#ddd700"
camera="#8d8c8d"
empty="#8d8c8d"
- lamp="#8d8c8d40"
+ light="#8d8c8d40"
speaker="#8d8c8d"
vertex="#bfbfbf"
vertex_select="#00bdff"
diff --git a/release/scripts/presets/interface_theme/north.xml b/release/scripts/presets/interface_theme/north.xml
index 69cb90a64ce..8ab51261994 100644
--- a/release/scripts/presets/interface_theme/north.xml
+++ b/release/scripts/presets/interface_theme/north.xml
@@ -253,7 +253,7 @@
text_keyframe="#ddd700"
camera="#000000"
empty="#000000"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
vertex="#000000"
vertex_select="#f2b252"
diff --git a/release/scripts/presets/interface_theme/rtheme.xml b/release/scripts/presets/interface_theme/rtheme.xml
index 27f33aa2fe5..34d4f6bd0db 100644
--- a/release/scripts/presets/interface_theme/rtheme.xml
+++ b/release/scripts/presets/interface_theme/rtheme.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#00000028"
+ light="#00000028"
speaker="#000000"
camera="#000000"
view_overlay="#000000"
diff --git a/release/scripts/presets/interface_theme/sandyslate.xml b/release/scripts/presets/interface_theme/sandyslate.xml
index c5bae419bca..0b4756a40e8 100644
--- a/release/scripts/presets/interface_theme/sandyslate.xml
+++ b/release/scripts/presets/interface_theme/sandyslate.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#ff000080"
+ light="#ff000080"
speaker="#979797"
camera="#ff0000"
view_overlay="#000000"
diff --git a/release/scripts/presets/interface_theme/science_lab.xml b/release/scripts/presets/interface_theme/science_lab.xml
index 2fe4cf99e41..e8a32f6ac29 100644
--- a/release/scripts/presets/interface_theme/science_lab.xml
+++ b/release/scripts/presets/interface_theme/science_lab.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#dbac00b9"
+ light="#dbac00b9"
speaker="#229cd8"
camera="#e28400"
view_overlay="#666666"
diff --git a/release/scripts/presets/interface_theme/softblend.xml b/release/scripts/presets/interface_theme/softblend.xml
index ab0a5994838..ce20f7d4085 100644
--- a/release/scripts/presets/interface_theme/softblend.xml
+++ b/release/scripts/presets/interface_theme/softblend.xml
@@ -244,7 +244,7 @@
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#ffe56666"
+ light="#ffe56666"
speaker="#c2e787"
camera="#000000"
view_overlay="#000000"
diff --git a/release/scripts/presets/interface_theme/true_blue_menu.xml b/release/scripts/presets/interface_theme/true_blue_menu.xml
index 2b464ae120e..26e39f3bcdf 100644
--- a/release/scripts/presets/interface_theme/true_blue_menu.xml
+++ b/release/scripts/presets/interface_theme/true_blue_menu.xml
@@ -253,7 +253,7 @@
text_keyframe="#ddd700"
camera="#000000"
empty="#a78721"
- lamp="#d6df1628"
+ light="#d6df1628"
speaker="#a83f2d"
vertex="#657780"
vertex_select="#00cccb"
diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py
index e8576cfad9b..8bce68a0a30 100644
--- a/release/scripts/presets/keyconfig/3dsmax.py
+++ b/release/scripts/presets/keyconfig/3dsmax.py
@@ -7,7 +7,7 @@ kc = wm.keyconfigs.new('3dsmax')
# Map Window
km = kc.keymaps.new('Window', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.keymap_items.new('wm.window_duplicate', 'W', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.window_new', 'W', 'PRESS', ctrl=True, alt=True)
kmi = km.keymap_items.new('wm.read_homefile', 'N', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.save_homefile', 'U', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.call_menu', 'O', 'PRESS', shift=True, ctrl=True)
@@ -33,9 +33,6 @@ kmi = km.keymap_items.new('wm.call_menu', 'NDOF_BUTTON_MENU', 'PRESS')
kmi.properties.name = 'USERPREF_MT_ndof_settings'
kmi = km.keymap_items.new('wm.context_set_enum', 'F2', 'PRESS', shift=True)
kmi.properties.data_path = 'area.type'
-kmi.properties.value = 'LOGIC_EDITOR'
-kmi = km.keymap_items.new('wm.context_set_enum', 'F3', 'PRESS', shift=True, ctrl=True)
-kmi.properties.data_path = 'area.type'
kmi.properties.value = 'NODE_EDITOR'
kmi = km.keymap_items.new('wm.context_set_enum', 'F4', 'PRESS', shift=True)
kmi.properties.data_path = 'area.type'
@@ -293,7 +290,6 @@ kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
kmi = km.keymap_items.new('wm.context_toggle', 'O', 'PRESS')
kmi.properties.data_path = 'tool_settings.use_proportional_edit_objects'
-kmi = km.keymap_items.new('view3d.game_start', 'P', 'PRESS', shift=True, ctrl=True, alt=True)
kmi = km.keymap_items.new('object.select_all', 'A', 'PRESS', ctrl=True)
kmi.properties.action = 'INVERT'
kmi = km.keymap_items.new('object.select_linked', 'L', 'PRESS', shift=True)
@@ -329,7 +325,6 @@ kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True
kmi = km.keymap_items.new('object.hide_render_clear', 'H', 'PRESS', ctrl=True, alt=True)
kmi = km.keymap_items.new('object.hide_render_set', 'H', 'PRESS', ctrl=True)
-kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'X', 'PRESS')
kmi.properties.use_global = False
kmi = km.keymap_items.new('object.delete', 'X', 'PRESS', shift=True)
@@ -590,11 +585,11 @@ kmi.properties.nr = 9
kmi = km.keymap_items.new('view3d.layers', 'ZERO', 'PRESS', any=True)
kmi.properties.nr = 10
kmi = km.keymap_items.new('wm.context_toggle_enum', 'F3', 'PRESS')
-kmi.properties.data_path = 'space_data.viewport_shade'
+kmi.properties.data_path = 'space_data.shading.type'
kmi.properties.value_1 = 'SOLID'
kmi.properties.value_2 = 'WIREFRAME'
kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True)
-kmi.properties.data_path = 'space_data.viewport_shade'
+kmi.properties.data_path = 'space_data.shading.type'
kmi.properties.value_1 = 'SOLID'
kmi.properties.value_2 = 'TEXTURED'
kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK')
@@ -726,7 +721,7 @@ kmi.properties.value_1 = 'VERTEX'
kmi.properties.value_2 = 'INCREMENT'
kmi = km.keymap_items.new('view3d.select_border', 'EVT_TWEAK_L', 'ANY', ctrl=True)
kmi = km.keymap_items.new('wm.context_toggle', 'G', 'PRESS')
-kmi.properties.data_path = 'space_data.show_floor'
+kmi.properties.data_path = 'space_data.overlay.show_floor'
# Map Animation Channels
km = kc.keymaps.new('Animation Channels', space_type='EMPTY', region_type='WINDOW', modal=False)
@@ -1109,7 +1104,7 @@ kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS')
kmi.properties.exit = False
kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS', shift=True)
kmi.properties.exit = True
-kmi = km.keymap_items.new('node.read_renderlayers', 'R', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('node.read_viewlayers', 'R', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('node.read_fullsamplelayers', 'R', 'PRESS', shift=True)
kmi = km.keymap_items.new('node.render_changed', 'Z', 'PRESS')
kmi = km.keymap_items.new('node.clipboard_copy', 'C', 'PRESS', ctrl=True)
@@ -2282,17 +2277,6 @@ kmi.properties.value_2 = 'CONNECTED'
# Map Armature
km = kc.keymaps.new('Armature', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.keymap_items.new('sketch.delete', 'X', 'PRESS')
-kmi = km.keymap_items.new('sketch.delete', 'DEL', 'PRESS')
-kmi = km.keymap_items.new('sketch.finish_stroke', 'RIGHTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('sketch.cancel_stroke', 'ESC', 'PRESS')
-kmi = km.keymap_items.new('sketch.gesture', 'LEFTMOUSE', 'PRESS', shift=True)
-kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS', ctrl=True)
-kmi.properties.snap = True
-kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY')
-kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY', ctrl=True)
-kmi.properties.snap = True
kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS')
kmi.properties.unselected = False
kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS', shift=True)
diff --git a/release/scripts/presets/keyconfig/blender_27x.py b/release/scripts/presets/keyconfig/blender_27x.py
new file mode 100644
index 00000000000..e9f64183d9a
--- /dev/null
+++ b/release/scripts/presets/keyconfig/blender_27x.py
@@ -0,0 +1,10756 @@
+keyconfig_data = [
+ (
+ "Window",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("wm.window_new", {"type": 'W', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("wm.read_homefile", {"type": 'N', "value": 'PRESS', "ctrl": True}, None),
+ ("wm.save_homefile", {"type": 'U', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'O', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("name", 'INFO_MT_file_open_recent'),
+ ],
+ }
+ ),
+ ("wm.open_mainfile", {"type": 'O', "value": 'PRESS', "ctrl": True}, None),
+ ("wm.open_mainfile", {"type": 'F1', "value": 'PRESS'}, None),
+ ("wm.link", {"type": 'O', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("wm.append", {"type": 'F1', "value": 'PRESS', "shift": True}, None),
+ ("wm.save_mainfile", {"type": 'S', "value": 'PRESS', "ctrl": True}, None),
+ ("wm.save_mainfile", {"type": 'W', "value": 'PRESS', "ctrl": True}, None),
+ ("wm.save_as_mainfile", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("wm.save_as_mainfile", {"type": 'F2', "value": 'PRESS'}, None),
+ (
+ "wm.save_as_mainfile",
+ {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("copy", True),
+ ],
+ }
+ ),
+ ("wm.window_fullscreen_toggle", {"type": 'F11', "value": 'PRESS', "alt": True}, None),
+ ("wm.quit_blender", {"type": 'Q', "value": 'PRESS', "ctrl": True}, None),
+ ("wm.doc_view_manual_ui_context", {"type": 'F1', "value": 'PRESS', "alt": True}, None),
+ ("wm.redraw_timer", {"type": 'T', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("wm.debug_menu", {"type": 'D', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'USERPREF_MT_ndof_settings'),
+ ],
+ }
+ ),
+ ("wm.search_menu", {"type": 'SPACE', "value": 'PRESS'}, None),
+ (
+ "wm.context_set_enum",
+ {"type": 'F3', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'NODE_EDITOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F4', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'CONSOLE'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F5', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'VIEW_3D'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F6', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'GRAPH_EDITOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F7', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'PROPERTIES'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F8', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'SEQUENCE_EDITOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F9', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'OUTLINER'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F10', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'IMAGE_EDITOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F11', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'TEXT_EDITOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'F12', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'area.type'),
+ ("value", 'DOPESHEET_EDITOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_scale_float",
+ {"type": 'NDOF_BUTTON_PLUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'user_preferences.inputs.ndof_sensitivity'),
+ ("value", 1.1),
+ ],
+ }
+ ),
+ (
+ "wm.context_scale_float",
+ {"type": 'NDOF_BUTTON_MINUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'user_preferences.inputs.ndof_sensitivity'),
+ ("value", 1.0),
+ ],
+ }
+ ),
+ (
+ "wm.context_scale_float",
+ {"type": 'NDOF_BUTTON_PLUS', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'user_preferences.inputs.ndof_sensitivity'),
+ ("value", 1.5),
+ ],
+ }
+ ),
+ (
+ "wm.context_scale_float",
+ {"type": 'NDOF_BUTTON_MINUS', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'user_preferences.inputs.ndof_sensitivity'),
+ ("value", 0.6666667),
+ ],
+ }
+ ),
+ ("info.reports_display_update", {"type": 'TIMER_REPORT', "value": 'ANY', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Screen",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("screen.animation_step", {"type": 'TIMER0', "value": 'ANY', "any": True}, None),
+ ("screen.region_blend", {"type": 'TIMERREGION', "value": 'ANY', "any": True}, None),
+ (
+ "screen.screen_set",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "screen.screen_set",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ ("screen.screen_full_area", {"type": 'SPACE', "value": 'PRESS', "shift": True}, None),
+ (
+ "screen.screen_full_area",
+ {"type": 'SPACE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("use_hide_panels", True),
+ ],
+ }
+ ),
+ ("screen.screenshot", {"type": 'F3', "value": 'PRESS', "ctrl": True}, None),
+ ("screen.screencast", {"type": 'F3', "value": 'PRESS', "alt": True}, None),
+ (
+ "screen.space_context_cycle",
+ {"type": 'TAB', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("direction", 'NEXT'),
+ ],
+ }
+ ),
+ (
+ "screen.space_context_cycle",
+ {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("direction", 'PREV'),
+ ],
+ }
+ ),
+ ("screen.region_quadview", {"type": 'Q', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("screen.repeat_history", {"type": 'F3', "value": 'PRESS'}, None),
+ ("screen.repeat_last", {"type": 'R', "value": 'PRESS', "shift": True}, None),
+ ("screen.region_flip", {"type": 'F5', "value": 'PRESS'}, None),
+ ("screen.redo_last", {"type": 'F6', "value": 'PRESS'}, None),
+ ("script.reload", {"type": 'F8', "value": 'PRESS'}, None),
+ ("file.execute", {"type": 'RET', "value": 'PRESS'}, None),
+ ("file.execute", {"type": 'NUMPAD_ENTER', "value": 'PRESS'}, None),
+ ("file.cancel", {"type": 'ESC', "value": 'PRESS'}, None),
+ ("ed.undo", {"type": 'Z', "value": 'PRESS', "ctrl": True}, None),
+ ("ed.redo", {"type": 'Z', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("ed.undo_history", {"type": 'Z', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ (
+ "render.render",
+ {"type": 'F12', "value": 'PRESS'},
+ {
+ "properties": [
+ ("use_viewport", True),
+ ],
+ }
+ ),
+ (
+ "render.render",
+ {"type": 'F12', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("animation", True),
+ ("use_viewport", True),
+ ],
+ }
+ ),
+ ("render.view_cancel", {"type": 'ESC', "value": 'PRESS'}, None),
+ ("render.view_show", {"type": 'F11', "value": 'PRESS'}, None),
+ ("render.play_rendered_anim", {"type": 'F11', "value": 'PRESS', "ctrl": True}, None),
+ ("screen.userpref_show", {"type": 'U', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ],
+ },
+ ),
+ (
+ "User Interface",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("ui.eyedropper_color", {"type": 'E', "value": 'PRESS'}, None),
+ ("ui.eyedropper_colorband", {"type": 'E', "value": 'PRESS'}, None),
+ ("ui.eyedropper_colorband_point", {"type": 'E', "value": 'PRESS', "alt": True}, None),
+ ("ui.eyedropper_id", {"type": 'E', "value": 'PRESS'}, None),
+ ("ui.eyedropper_depth", {"type": 'E', "value": 'PRESS'}, None),
+ ("ui.copy_data_path_button", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "ui.copy_data_path_button",
+ {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("full_path", True),
+ ],
+ }
+ ),
+ ("anim.keyframe_insert_button", {"type": 'I', "value": 'PRESS'}, None),
+ ("anim.keyframe_delete_button", {"type": 'I', "value": 'PRESS', "alt": True}, None),
+ ("anim.keyframe_clear_button", {"type": 'I', "value": 'PRESS', "shift": True, "alt": True}, None),
+ ("anim.driver_button_add", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
+ ("anim.driver_button_remove", {"type": 'D', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("anim.keyingset_button_add", {"type": 'K', "value": 'PRESS'}, None),
+ ("anim.keyingset_button_remove", {"type": 'K', "value": 'PRESS', "alt": True}, None),
+ ],
+ },
+ ),
+ (
+ "View2D",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("view2d.scroller_activate", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("view2d.scroller_activate", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("view2d.pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("view2d.pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("view2d.pan", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
+ ("view2d.scroll_right", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("view2d.scroll_left", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("view2d.scroll_down", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("view2d.scroll_up", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("view2d.ndof", {"type": 'NDOF_MOTION', "value": 'ANY'}, None),
+ ("view2d.zoom_out", {"type": 'WHEELOUTMOUSE', "value": 'PRESS'}, None),
+ ("view2d.zoom_in", {"type": 'WHEELINMOUSE', "value": 'PRESS'}, None),
+ ("view2d.zoom_out", {"type": 'NUMPAD_MINUS', "value": 'PRESS'}, None),
+ ("view2d.zoom_in", {"type": 'NUMPAD_PLUS', "value": 'PRESS'}, None),
+ ("view2d.zoom", {"type": 'TRACKPADPAN', "value": 'ANY', "ctrl": True}, None),
+ ("view2d.smoothview", {"type": 'TIMER1', "value": 'ANY', "any": True}, None),
+ ("view2d.scroll_down", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS'}, None),
+ ("view2d.scroll_up", {"type": 'WHEELUPMOUSE', "value": 'PRESS'}, None),
+ ("view2d.scroll_right", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS'}, None),
+ ("view2d.scroll_left", {"type": 'WHEELUPMOUSE', "value": 'PRESS'}, None),
+ ("view2d.zoom", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("view2d.zoom", {"type": 'TRACKPADZOOM', "value": 'ANY'}, None),
+ ("view2d.zoom_border", {"type": 'B', "value": 'PRESS', "shift": True}, None),
+ ],
+ },
+ ),
+ (
+ "Header",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("screen.header_toolbox", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "View2D Buttons List",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("view2d.scroller_activate", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("view2d.scroller_activate", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("view2d.pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("view2d.pan", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
+ ("view2d.scroll_down", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS'}, None),
+ ("view2d.scroll_up", {"type": 'WHEELUPMOUSE', "value": 'PRESS'}, None),
+ (
+ "view2d.scroll_down",
+ {"type": 'PAGE_DOWN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("page", True),
+ ],
+ }
+ ),
+ (
+ "view2d.scroll_up",
+ {"type": 'PAGE_UP', "value": 'PRESS'},
+ {
+ "properties": [
+ ("page", True),
+ ],
+ }
+ ),
+ ("view2d.zoom", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("view2d.zoom", {"type": 'TRACKPADZOOM', "value": 'ANY'}, None),
+ ("view2d.zoom", {"type": 'TRACKPADPAN', "value": 'ANY', "ctrl": True}, None),
+ ("view2d.zoom_out", {"type": 'NUMPAD_MINUS', "value": 'PRESS'}, None),
+ ("view2d.zoom_in", {"type": 'NUMPAD_PLUS', "value": 'PRESS'}, None),
+ ("view2d.reset", {"type": 'HOME', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Frames",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "screen.frame_offset",
+ {"type": 'UP_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("delta", 10),
+ ],
+ }
+ ),
+ (
+ "screen.frame_offset",
+ {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("delta", -10),
+ ],
+ }
+ ),
+ (
+ "screen.frame_offset",
+ {"type": 'LEFT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ (
+ "screen.frame_offset",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "screen.frame_offset",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "screen.frame_offset",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ (
+ "screen.frame_jump",
+ {"type": 'UP_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("end", True),
+ ],
+ }
+ ),
+ (
+ "screen.frame_jump",
+ {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("end", False),
+ ],
+ }
+ ),
+ (
+ "screen.frame_jump",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("end", True),
+ ],
+ }
+ ),
+ (
+ "screen.frame_jump",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("end", False),
+ ],
+ }
+ ),
+ (
+ "screen.keyframe_jump",
+ {"type": 'UP_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("next", True),
+ ],
+ }
+ ),
+ (
+ "screen.keyframe_jump",
+ {"type": 'DOWN_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("next", False),
+ ],
+ }
+ ),
+ (
+ "screen.keyframe_jump",
+ {"type": 'MEDIA_LAST', "value": 'PRESS'},
+ {
+ "properties": [
+ ("next", True),
+ ],
+ }
+ ),
+ (
+ "screen.keyframe_jump",
+ {"type": 'MEDIA_FIRST', "value": 'PRESS'},
+ {
+ "properties": [
+ ("next", False),
+ ],
+ }
+ ),
+ ("screen.animation_play", {"type": 'A', "value": 'PRESS', "alt": True}, None),
+ (
+ "screen.animation_play",
+ {"type": 'A', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("reverse", True),
+ ],
+ }
+ ),
+ ("screen.animation_cancel", {"type": 'ESC', "value": 'PRESS'}, None),
+ ("screen.animation_play", {"type": 'MEDIA_PLAY', "value": 'PRESS'}, None),
+ ("screen.animation_cancel", {"type": 'MEDIA_STOP', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Property Editor",
+ {"space_type": 'PROPERTIES', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("buttons.toolbox", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Info",
+ {"space_type": 'INFO', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("info.select_pick", {"type": 'SELECTMOUSE', "value": 'PRESS'}, None),
+ ("info.select_all_toggle", {"type": 'A', "value": 'PRESS'}, None),
+ ("info.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ ("info.report_replay", {"type": 'R', "value": 'PRESS'}, None),
+ ("info.report_delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("info.report_delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("info.report_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "Outliner",
+ {"space_type": 'OUTLINER', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("outliner.highlight_update", {"type": 'MOUSEMOVE', "value": 'ANY', "any": True}, None),
+ ("outliner.item_rename", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
+ (
+ "outliner.item_activate",
+ {"type": 'LEFTMOUSE', "value": 'CLICK'},
+ {
+ "properties": [
+ ("extend", False),
+ ("recursive", False),
+ ],
+ }
+ ),
+ (
+ "outliner.item_activate",
+ {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("recursive", False),
+ ],
+ }
+ ),
+ (
+ "outliner.item_activate",
+ {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("recursive", True),
+ ],
+ }
+ ),
+ (
+ "outliner.item_activate",
+ {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("recursive", True),
+ ],
+ }
+ ),
+ ("outliner.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ (
+ "outliner.item_openclose",
+ {"type": 'RET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("all", False),
+ ],
+ }
+ ),
+ (
+ "outliner.item_openclose",
+ {"type": 'RET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("all", True),
+ ],
+ }
+ ),
+ ("outliner.item_rename", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("outliner.operation", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, None),
+ ("outliner.item_drag_drop", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
+ ("outliner.show_hierarchy", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("outliner.show_active", {"type": 'PERIOD', "value": 'PRESS'}, None),
+ ("outliner.show_active", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ (
+ "outliner.scroll_page",
+ {"type": 'PAGE_DOWN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("up", False),
+ ],
+ }
+ ),
+ (
+ "outliner.scroll_page",
+ {"type": 'PAGE_UP', "value": 'PRESS'},
+ {
+ "properties": [
+ ("up", True),
+ ],
+ }
+ ),
+ ("outliner.show_one_level", {"type": 'NUMPAD_PLUS', "value": 'PRESS'}, None),
+ (
+ "outliner.show_one_level",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("open", False),
+ ],
+ }
+ ),
+ (
+ "outliner.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ ("outliner.expanded_toggle", {"type": 'A', "value": 'PRESS', "shift": True}, None),
+ ("outliner.keyingset_add_selected", {"type": 'K', "value": 'PRESS'}, None),
+ ("outliner.keyingset_remove_selected", {"type": 'K', "value": 'PRESS', "alt": True}, None),
+ ("anim.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
+ ("anim.keyframe_delete", {"type": 'I', "value": 'PRESS', "alt": True}, None),
+ ("outliner.drivers_add_selected", {"type": 'D', "value": 'PRESS'}, None),
+ ("outliner.drivers_delete_selected", {"type": 'D', "value": 'PRESS', "alt": True}, None),
+ ("outliner.collection_new", {"type": 'C', "value": 'PRESS'}, None),
+ ("outliner.collection_delete", {"type": 'X', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "3D View Generic",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("view3d.properties", {"type": 'N', "value": 'PRESS'}, None),
+ ("view3d.toolshelf", {"type": 'T', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Grease Pencil",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "gpencil.draw",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "key_modifier": 'D'},
+ {
+ "properties": [
+ ("mode", 'DRAW'),
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.draw",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True, "key_modifier": 'D'},
+ {
+ "properties": [
+ ("mode", 'DRAW_STRAIGHT'),
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.draw",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "ctrl": True, "key_modifier": 'D'},
+ {
+ "properties": [
+ ("mode", 'DRAW_POLY'),
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.draw",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "key_modifier": 'D'},
+ {
+ "properties": [
+ ("mode", 'ERASER'),
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.draw",
+ {"type": 'ERASER', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'ERASER'),
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ ("gpencil.editmode_toggle", {"type": 'TAB', "value": 'PRESS', "key_modifier": 'D'}, None),
+ (
+ "wm.call_menu_pie",
+ {"type": 'Q', "value": 'PRESS', "key_modifier": 'D'},
+ {
+ "properties": [
+ ("name", 'GPENCIL_MT_pie_tool_palette'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu_pie",
+ {"type": 'W', "value": 'PRESS', "key_modifier": 'D'},
+ {
+ "properties": [
+ ("name", 'GPENCIL_MT_pie_settings_palette'),
+ ],
+ }
+ ),
+ ("gpencil.blank_frame_add", {"type": 'B', "value": 'PRESS', "key_modifier": 'D'}, None),
+ ("gpencil.active_frames_delete_all", {"type": 'X', "value": 'PRESS', "key_modifier": 'D'}, None),
+ ],
+ },
+ ),
+ (
+ "Grease Pencil Stroke Edit Mode",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("gpencil.editmode_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
+ (
+ "wm.call_menu_pie",
+ {"type": 'E', "value": 'PRESS', "key_modifier": 'D'},
+ {
+ "properties": [
+ ("name", 'GPENCIL_MT_pie_sculpt'),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path_primary", 'user_preferences.edit.grease_pencil_eraser_radius'),
+ ],
+ }
+ ),
+ ("gpencil.interpolate", {"type": 'E', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("gpencil.interpolate_sequence", {"type": 'E', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "gpencil.brush_paint",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "key_modifier": 'E'},
+ {
+ "properties": [
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_paint",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True, "key_modifier": 'E'},
+ {
+ "properties": [
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_paint",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "key_modifier": 'E'},
+ {
+ "properties": [
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.gpencil_sculpt.brush.strength'),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.gpencil_sculpt.brush.size'),
+ ],
+ }
+ ),
+ (
+ "gpencil.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "gpencil.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("gpencil.select_circle", {"type": 'C', "value": 'PRESS'}, None),
+ ("gpencil.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ (
+ "gpencil.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ (
+ "gpencil.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("gpencil.select", {"type": 'SELECTMOUSE', "value": 'PRESS'}, None),
+ (
+ "gpencil.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("toggle", True),
+ ],
+ }
+ ),
+ (
+ "gpencil.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("entire_strokes", True),
+ ],
+ }
+ ),
+ ("gpencil.select_linked", {"type": 'L', "value": 'PRESS'}, None),
+ ("gpencil.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
+ ("gpencil.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
+ ("gpencil.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("gpencil.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("gpencil.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'X', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_gpencil_delete'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_gpencil_delete'),
+ ],
+ }
+ ),
+ ("gpencil.dissolve", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
+ ("gpencil.dissolve", {"type": 'DEL', "value": 'PRESS', "ctrl": True}, None),
+ ("gpencil.active_frames_delete_all", {"type": 'X', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'GPENCIL_MT_gpencil_edit_specials'),
+ ],
+ }
+ ),
+ ("gpencil.stroke_join", {"type": 'J', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "gpencil.stroke_join",
+ {"type": 'J', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'JOINCOPY'),
+ ],
+ }
+ ),
+ ("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("gpencil.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'S', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'GPENCIL_MT_snap'),
+ ],
+ }
+ ),
+ ("gpencil.convert", {"type": 'C', "value": 'PRESS', "alt": True}, None),
+ ("gpencil.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ (
+ "gpencil.hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "gpencil.hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("gpencil.selection_opacity_toggle", {"type": 'H', "value": 'PRESS', "ctrl": True}, None),
+ ("gpencil.layer_isolate", {"type": 'NUMPAD_ASTERIX', "value": 'PRESS'}, None),
+ ("gpencil.move_to_layer", {"type": 'M', "value": 'PRESS'}, None),
+ (
+ "gpencil.brush_select",
+ {"type": 'ONE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 0),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'TWO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 1),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'THREE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 2),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'FOUR', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 3),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'FIVE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 4),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'SIX', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 5),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'SEVEN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 6),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'EIGHT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 7),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'NINE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 8),
+ ],
+ }
+ ),
+ (
+ "gpencil.brush_select",
+ {"type": 'ZERO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("index", 9),
+ ],
+ }
+ ),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ ("transform.mirror", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ ("transform.bend", {"type": 'W', "value": 'PRESS', "shift": True}, None),
+ ("transform.tosphere", {"type": 'S', "value": 'PRESS', "shift": True, "alt": True}, None),
+ ("transform.shear", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ (
+ "transform.transform",
+ {"type": 'S', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'GPENCIL_SHRINKFATTEN'),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'ENABLED'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'CONNECTED'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Face Mask",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "paint.face_select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "paint.face_select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ (
+ "paint.face_select_hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "paint.face_select_hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("paint.face_select_reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ ("paint.face_select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "paint.face_select_linked_pick",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "paint.face_select_linked_pick",
+ {"type": 'L', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Weight Paint Vertex Selection",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "paint.vert_select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "paint.vert_select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("view3d.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ (
+ "view3d.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "view3d.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("view3d.select_circle", {"type": 'C', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Pose",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("object.parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'INFO_MT_add'),
+ ],
+ }
+ ),
+ (
+ "pose.hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "pose.hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("pose.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_pose_apply'),
+ ],
+ }
+ ),
+ ("pose.rot_clear", {"type": 'R', "value": 'PRESS', "alt": True}, None),
+ ("pose.loc_clear", {"type": 'G', "value": 'PRESS', "alt": True}, None),
+ ("pose.scale_clear", {"type": 'S', "value": 'PRESS', "alt": True}, None),
+ ("pose.quaternions_flip", {"type": 'F', "value": 'PRESS', "alt": True}, None),
+ ("pose.rotation_mode_set", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
+ ("pose.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "pose.paste",
+ {"type": 'V', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("flipped", False),
+ ],
+ }
+ ),
+ (
+ "pose.paste",
+ {"type": 'V', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("flipped", True),
+ ],
+ }
+ ),
+ (
+ "pose.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "pose.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("pose.select_parent", {"type": 'P', "value": 'PRESS', "shift": True}, None),
+ (
+ "pose.select_hierarchy",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'PARENT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "pose.select_hierarchy",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'PARENT'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "pose.select_hierarchy",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'CHILD'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "pose.select_hierarchy",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'CHILD'),
+ ("extend", True),
+ ],
+ }
+ ),
+ ("pose.select_linked", {"type": 'L', "value": 'PRESS'}, None),
+ ("pose.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
+ ("pose.select_mirror", {"type": 'F', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("pose.constraint_add_with_targets", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("pose.constraints_clear", {"type": 'C', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("pose.ik_add", {"type": 'I', "value": 'PRESS', "shift": True}, None),
+ ("pose.ik_clear", {"type": 'I', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'G', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_pose_group'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_bone_options_toggle'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_bone_options_enable'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_bone_options_disable'),
+ ],
+ }
+ ),
+ ("armature.layers_show_all", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "ctrl": True}, None),
+ ("armature.armature_layers", {"type": 'M', "value": 'PRESS', "shift": True}, None),
+ ("pose.bone_layers", {"type": 'M', "value": 'PRESS'}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'Z', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.overlay.show_bone_select'),
+ ],
+ }
+ ),
+
+ (
+ "transform.transform",
+ {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("mode", 'BONE_SIZE'),
+ ],
+ }
+ ),
+ ("anim.keyframe_insert_menu", {"type": 'I', "value": 'PRESS'}, None),
+ ("anim.keyframe_delete_v3d", {"type": 'I', "value": 'PRESS', "alt": True}, None),
+ ("anim.keying_set_active_set", {"type": 'I', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ ("poselib.browse_interactive", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
+ ("poselib.pose_add", {"type": 'L', "value": 'PRESS', "shift": True}, None),
+ ("poselib.pose_remove", {"type": 'L', "value": 'PRESS', "alt": True}, None),
+ ("poselib.pose_rename", {"type": 'L', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("pose.push", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
+ ("pose.relax", {"type": 'E', "value": 'PRESS', "alt": True}, None),
+ ("pose.breakdown", {"type": 'E', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_pose_specials'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'P', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_pose_propagate'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Object Mode",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_proportional_edit_objects'),
+ ],
+ }
+ ),
+ (
+ "object.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "object.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("object.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("object.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("object.select_linked", {"type": 'L', "value": 'PRESS', "shift": True}, None),
+ ("object.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
+ ("object.select_mirror", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "object.select_hierarchy",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'PARENT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "object.select_hierarchy",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'PARENT'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "object.select_hierarchy",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'CHILD'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "object.select_hierarchy",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'CHILD'),
+ ("extend", True),
+ ],
+ }
+ ),
+ ("object.parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ ("object.parent_no_inverse_set", {"type": 'P', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("object.parent_clear", {"type": 'P', "value": 'PRESS', "alt": True}, None),
+ ("object.track_set", {"type": 'T', "value": 'PRESS', "ctrl": True}, None),
+ ("object.track_clear", {"type": 'T', "value": 'PRESS', "alt": True}, None),
+ ("object.constraint_add_with_targets", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("object.constraints_clear", {"type": 'C', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ (
+ "object.location_clear",
+ {"type": 'G', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("clear_delta", False),
+ ],
+ }
+ ),
+ (
+ "object.rotation_clear",
+ {"type": 'R', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("clear_delta", False),
+ ],
+ }
+ ),
+ (
+ "object.scale_clear",
+ {"type": 'S', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("clear_delta", False),
+ ],
+ }
+ ),
+ ("object.origin_clear", {"type": 'O', "value": 'PRESS', "alt": True}, None),
+ (
+ "object.delete",
+ {"type": 'X', "value": 'PRESS'},
+ {
+ "properties": [
+ ("use_global", False),
+ ],
+ }
+ ),
+ (
+ "object.delete",
+ {"type": 'X', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("use_global", True),
+ ],
+ }
+ ),
+ (
+ "object.delete",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("use_global", False),
+ ],
+ }
+ ),
+ (
+ "object.delete",
+ {"type": 'DEL', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("use_global", True),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'INFO_MT_add'),
+ ],
+ }
+ ),
+ ("object.duplicates_make_real", {"type": 'A', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_object_apply'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'U', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_make_single_user'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'L', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_make_links'),
+ ],
+ }
+ ),
+ ("object.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("object.duplicate_move_linked", {"type": 'D', "value": 'PRESS', "alt": True}, None),
+ ("object.join", {"type": 'J', "value": 'PRESS', "ctrl": True}, None),
+ ("object.convert", {"type": 'C', "value": 'PRESS', "alt": True}, None),
+ ("object.proxy_make", {"type": 'P', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("object.make_local", {"type": 'L', "value": 'PRESS'}, None),
+ ("anim.keyframe_insert_menu", {"type": 'I', "value": 'PRESS'}, None),
+ ("anim.keyframe_delete_v3d", {"type": 'I', "value": 'PRESS', "alt": True}, None),
+ ("anim.keying_set_active_set", {"type": 'I', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ ("collection.create", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
+ ("collection.objects_remove", {"type": 'G', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("collection.objects_remove_all", {"type": 'G', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ ("collection.objects_add_active", {"type": 'G', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("collection.objects_remove_active", {"type": 'G', "value": 'PRESS', "shift": True, "alt": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_object_specials'),
+ ],
+ }
+ ),
+ ("object.data_transfer", {"type": 'T', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "object.subdivision_set",
+ {"type": 'ZERO', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 0),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'ONE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 1),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'TWO', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 2),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'THREE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 3),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'FOUR', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 4),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'FIVE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 5),
+ ],
+ }
+ ),
+ ("object.move_to_collection", {"type": 'M', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Paint Curve",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("paintcurve.add_point_slide", {"type": 'ACTIONMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("paintcurve.select", {"type": 'SELECTMOUSE', "value": 'PRESS'}, None),
+ (
+ "paintcurve.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ ("paintcurve.slide", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ (
+ "paintcurve.slide",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("align", True),
+ ],
+ }
+ ),
+ (
+ "paintcurve.select",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("toggle", True),
+ ],
+ }
+ ),
+ ("paintcurve.cursor", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ ("paintcurve.delete_point", {"type": 'X', "value": 'PRESS'}, None),
+ ("paintcurve.delete_point", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("paintcurve.draw", {"type": 'RET', "value": 'PRESS'}, None),
+ ("paintcurve.draw", {"type": 'NUMPAD_ENTER', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Curve",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'INFO_MT_edit_curve_add'),
+ ],
+ }
+ ),
+ ("curve.handle_type_set", {"type": 'V', "value": 'PRESS'}, None),
+ ("curve.vertex_add", {"type": 'ACTIONMOUSE', "value": 'CLICK', "ctrl": True}, None),
+ (
+ "curve.draw",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "curve.draw",
+ {"type": 'PEN', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("wait_for_input", False),
+ ],
+ }
+ ),
+ (
+ "curve.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "curve.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("curve.select_row", {"type": 'R', "value": 'PRESS', "shift": True}, None),
+ ("curve.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("curve.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("curve.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
+ ("curve.select_similar", {"type": 'G', "value": 'PRESS', "shift": True}, None),
+ (
+ "curve.select_linked_pick",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "curve.select_linked_pick",
+ {"type": 'L', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("curve.shortest_path_pick", {"type": 'SELECTMOUSE', "value": 'CLICK', "ctrl": True}, None),
+ ("curve.separate", {"type": 'P', "value": 'PRESS'}, None),
+ ("curve.split", {"type": 'Y', "value": 'PRESS'}, None),
+ ("curve.extrude_move", {"type": 'E', "value": 'PRESS'}, None),
+ ("curve.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("curve.make_segment", {"type": 'F', "value": 'PRESS'}, None),
+ ("curve.cyclic_toggle", {"type": 'C', "value": 'PRESS', "alt": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'X', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_curve_delete'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_curve_delete'),
+ ],
+ }
+ ),
+ ("curve.dissolve_verts", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
+ ("curve.dissolve_verts", {"type": 'DEL', "value": 'PRESS', "ctrl": True}, None),
+ ("curve.tilt_clear", {"type": 'T', "value": 'PRESS', "alt": True}, None),
+ ("transform.tilt", {"type": 'T', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "transform.transform",
+ {"type": 'S', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'CURVE_SHRINKFATTEN'),
+ ],
+ }
+ ),
+ ("curve.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ (
+ "curve.hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "curve.hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("curve.normals_make_consistent", {"type": 'N', "value": 'PRESS', "ctrl": True}, None),
+ ("object.vertex_parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_curve_specials'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'H', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_hook'),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'ENABLED'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'CONNECTED'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Image Paint",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "paint.image_paint",
+ {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'NORMAL'),
+ ],
+ }
+ ),
+ (
+ "paint.image_paint",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'INVERT'),
+ ],
+ }
+ ),
+ ("paint.brush_colors_flip", {"type": 'X', "value": 'PRESS'}, None),
+ ("paint.grab_clone", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, None),
+ ("paint.sample_color", {"type": 'S', "value": 'PRESS'}, None),
+ (
+ "brush.active_index_set",
+ {"type": 'ONE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 0),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'TWO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 1),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'THREE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 2),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FOUR', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 3),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FIVE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 4),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SIX', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 5),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SEVEN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 6),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'EIGHT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 7),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'NINE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 8),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ZERO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 9),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ONE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 10),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'TWO', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 11),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'THREE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 12),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FOUR', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 13),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FIVE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 14),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SIX', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 15),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SEVEN', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 16),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'EIGHT', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 17),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'NINE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 18),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ZERO', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'image_paint'),
+ ("index", 19),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 0.9),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 1.1111112),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.image_paint.brush.size'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.size'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_size'),
+ ("rotation_path", 'tool_settings.image_paint.brush.mask_texture_slot.angle'),
+ ("color_path", 'tool_settings.image_paint.brush.cursor_color_add'),
+ ("fill_color_path", 'tool_settings.image_paint.brush.color'),
+ ("fill_color_override_path", 'tool_settings.unified_paint_settings.color'),
+ ("fill_color_override_test_path", 'tool_settings.unified_paint_settings.use_unified_color'),
+ ("zoom_path", 'space_data.zoom'),
+ ("image_id", 'tool_settings.image_paint.brush'),
+ ("secondary_tex", True),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.image_paint.brush.strength'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.strength'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_strength'),
+ ("rotation_path", 'tool_settings.image_paint.brush.mask_texture_slot.angle'),
+ ("color_path", 'tool_settings.image_paint.brush.cursor_color_add'),
+ ("fill_color_path", 'tool_settings.image_paint.brush.color'),
+ ("fill_color_override_path", 'tool_settings.unified_paint_settings.color'),
+ ("fill_color_override_test_path", 'tool_settings.unified_paint_settings.use_unified_color'),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.image_paint.brush'),
+ ("secondary_tex", True),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.image_paint.brush.texture_slot.angle'),
+ ("data_path_secondary", ''),
+ ("use_secondary", ''),
+ ("rotation_path", 'tool_settings.image_paint.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.image_paint.brush.cursor_color_add'),
+ ("fill_color_path", 'tool_settings.image_paint.brush.color'),
+ ("fill_color_override_path", 'tool_settings.unified_paint_settings.color'),
+ ("fill_color_override_test_path", 'tool_settings.unified_paint_settings.use_unified_color'),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.image_paint.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.image_paint.brush.mask_texture_slot.angle'),
+ ("data_path_secondary", ''),
+ ("use_secondary", ''),
+ ("rotation_path", 'tool_settings.image_paint.brush.mask_texture_slot.angle'),
+ ("color_path", 'tool_settings.image_paint.brush.cursor_color_add'),
+ ("fill_color_path", 'tool_settings.image_paint.brush.color'),
+ ("fill_color_override_path", 'tool_settings.unified_paint_settings.color'),
+ ("fill_color_override_test_path", 'tool_settings.unified_paint_settings.use_unified_color'),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.image_paint.brush'),
+ ("secondary_tex", True),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TRANSLATION'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'SCALE'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'ROTATION'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'TRANSLATION'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("mode", 'SCALE'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("mode", 'ROTATION'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'M', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'image_paint_object.data.use_paint_mask'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'S', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.image_paint.brush.use_smooth_stroke'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'R', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_angle_control'),
+ ],
+ }
+ ),
+ (
+ "wm.context_menu_enum",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.image_paint.brush.stroke_method'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Vertex Paint",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("paint.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("paint.brush_colors_flip", {"type": 'X', "value": 'PRESS'}, None),
+ ("paint.sample_color", {"type": 'S', "value": 'PRESS'}, None),
+ ("paint.vertex_color_set", {"type": 'K', "value": 'PRESS', "shift": True}, None),
+ (
+ "brush.active_index_set",
+ {"type": 'ONE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 0),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'TWO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 1),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'THREE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 2),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FOUR', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 3),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FIVE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 4),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SIX', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 5),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SEVEN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 6),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'EIGHT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 7),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'NINE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 8),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ZERO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 9),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ONE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 10),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'TWO', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 11),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'THREE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 12),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FOUR', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 13),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FIVE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 14),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SIX', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 15),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SEVEN', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 16),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'EIGHT', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 17),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'NINE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 18),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ZERO', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'vertex_paint'),
+ ("index", 19),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 0.9),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 1.1111112),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.vertex_paint.brush.size'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.size'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_size'),
+ ("rotation_path", 'tool_settings.vertex_paint.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.vertex_paint.brush.cursor_color_add'),
+ ("fill_color_path", 'tool_settings.vertex_paint.brush.color'),
+ ("fill_color_override_path", 'tool_settings.unified_paint_settings.color'),
+ ("fill_color_override_test_path", 'tool_settings.unified_paint_settings.use_unified_color'),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.vertex_paint.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.vertex_paint.brush.strength'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.strength'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_strength'),
+ ("rotation_path", 'tool_settings.vertex_paint.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.vertex_paint.brush.cursor_color_add'),
+ ("fill_color_path", 'tool_settings.vertex_paint.brush.color'),
+ ("fill_color_override_path", 'tool_settings.unified_paint_settings.color'),
+ ("fill_color_override_test_path", 'tool_settings.unified_paint_settings.use_unified_color'),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.vertex_paint.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.vertex_paint.brush.texture_slot.angle'),
+ ("data_path_secondary", ''),
+ ("use_secondary", ''),
+ ("rotation_path", 'tool_settings.vertex_paint.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.vertex_paint.brush.cursor_color_add'),
+ ("fill_color_path", 'tool_settings.vertex_paint.brush.color'),
+ ("fill_color_override_path", 'tool_settings.unified_paint_settings.color'),
+ ("fill_color_override_test_path", 'tool_settings.unified_paint_settings.use_unified_color'),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.vertex_paint.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TRANSLATION'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'SCALE'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'ROTATION'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'TRANSLATION'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("mode", 'SCALE'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("mode", 'ROTATION'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'M', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'vertex_paint_object.data.use_paint_mask'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'S', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.vertex_paint.brush.use_smooth_stroke'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'R', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_angle_control'),
+ ],
+ }
+ ),
+ (
+ "wm.context_menu_enum",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.vertex_paint.brush.stroke_method'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Weight Paint",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("paint.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("paint.weight_sample", {"type": 'ACTIONMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("paint.weight_sample_group", {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True}, None),
+ (
+ "paint.weight_gradient",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("type", 'LINEAR'),
+ ],
+ }
+ ),
+ (
+ "paint.weight_gradient",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("type", 'RADIAL'),
+ ],
+ }
+ ),
+ ("paint.weight_set", {"type": 'K', "value": 'PRESS', "shift": True}, None),
+ (
+ "brush.active_index_set",
+ {"type": 'ONE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 0),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'TWO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 1),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'THREE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 2),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FOUR', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 3),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FIVE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 4),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SIX', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 5),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SEVEN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 6),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'EIGHT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 7),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'NINE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 8),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ZERO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 9),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ONE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 10),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'TWO', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 11),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'THREE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 12),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FOUR', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 13),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FIVE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 14),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SIX', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 15),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SEVEN', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 16),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'EIGHT', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 17),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'NINE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 18),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ZERO', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'weight_paint'),
+ ("index", 19),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 0.9),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 1.1111112),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.weight_paint.brush.size'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.size'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_size'),
+ ("rotation_path", 'tool_settings.weight_paint.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.weight_paint.brush.cursor_color_add'),
+ ("fill_color_path", ''),
+ ("fill_color_override_path", ''),
+ ("fill_color_override_test_path", ''),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.weight_paint.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.weight_paint.brush.strength'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.strength'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_strength'),
+ ("rotation_path", 'tool_settings.weight_paint.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.weight_paint.brush.cursor_color_add'),
+ ("fill_color_path", ''),
+ ("fill_color_override_path", ''),
+ ("fill_color_override_test_path", ''),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.weight_paint.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.weight_paint.brush.weight'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.weight'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_weight'),
+ ("rotation_path", 'tool_settings.weight_paint.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.weight_paint.brush.cursor_color_add'),
+ ("fill_color_path", ''),
+ ("fill_color_override_path", ''),
+ ("fill_color_override_test_path", ''),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.weight_paint.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.context_menu_enum",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.vertex_paint.brush.stroke_method'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'M', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'weight_paint_object.data.use_paint_mask'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'V', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'weight_paint_object.data.use_paint_mask_vertex'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'S', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.weight_paint.brush.use_smooth_stroke'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Sculpt",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "sculpt.brush_stroke",
+ {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'NORMAL'),
+ ],
+ }
+ ),
+ (
+ "sculpt.brush_stroke",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'INVERT'),
+ ],
+ }
+ ),
+ (
+ "sculpt.brush_stroke",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'SMOOTH'),
+ ],
+ }
+ ),
+ (
+ "paint.hide_show",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("action", 'SHOW'),
+ ("area", 'INSIDE'),
+ ],
+ }
+ ),
+ (
+ "paint.hide_show",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'HIDE'),
+ ("area", 'INSIDE'),
+ ],
+ }
+ ),
+ (
+ "paint.hide_show",
+ {"type": 'H', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("action", 'SHOW'),
+ ("area", 'ALL'),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'ZERO', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 0),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'ONE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 1),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'TWO', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 2),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'THREE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 3),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'FOUR', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 4),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'FIVE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 5),
+ ],
+ }
+ ),
+ (
+ "paint.mask_flood_fill",
+ {"type": 'M', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'VALUE'),
+ ("value", 0.0),
+ ],
+ }
+ ),
+ (
+ "paint.mask_flood_fill",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'INVERT'),
+ ],
+ }
+ ),
+ ("paint.mask_lasso_gesture", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'M', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'scene.tool_settings.sculpt.show_mask'),
+ ],
+ }
+ ),
+ ("sculpt.dynamic_topology_toggle", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
+ ("sculpt.set_detail_size", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ (
+ "object.subdivision_set",
+ {"type": 'PAGE_UP', "value": 'PRESS'},
+ {
+ "properties": [
+ ("level", 1),
+ ("relative", True),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'PAGE_DOWN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("level", -1),
+ ("relative", True),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ONE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 0),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'TWO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 1),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'THREE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 2),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FOUR', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 3),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FIVE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 4),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SIX', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 5),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SEVEN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 6),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'EIGHT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 7),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'NINE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 8),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ZERO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 9),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ONE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 10),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'TWO', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 11),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'THREE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 12),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FOUR', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 13),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'FIVE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 14),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SIX', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 15),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'SEVEN', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 16),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'EIGHT', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 17),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'NINE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 18),
+ ],
+ }
+ ),
+ (
+ "brush.active_index_set",
+ {"type": 'ZERO', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'sculpt'),
+ ("index", 19),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 0.9),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 1.1111112),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.sculpt.brush.size'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.size'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_size'),
+ ("rotation_path", 'tool_settings.sculpt.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.sculpt.brush.cursor_color_add'),
+ ("fill_color_path", ''),
+ ("fill_color_override_path", ''),
+ ("fill_color_override_test_path", ''),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.sculpt.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.sculpt.brush.strength'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.strength'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_strength'),
+ ("rotation_path", 'tool_settings.sculpt.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.sculpt.brush.cursor_color_add'),
+ ("fill_color_path", ''),
+ ("fill_color_override_path", ''),
+ ("fill_color_override_test_path", ''),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.sculpt.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.sculpt.brush.texture_slot.angle'),
+ ("data_path_secondary", ''),
+ ("use_secondary", ''),
+ ("rotation_path", 'tool_settings.sculpt.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.sculpt.brush.cursor_color_add'),
+ ("fill_color_path", ''),
+ ("fill_color_override_path", ''),
+ ("fill_color_override_test_path", ''),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.sculpt.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TRANSLATION'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'SCALE'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'ROTATION'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'TRANSLATION'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("mode", 'SCALE'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "brush.stencil_control",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("mode", 'ROTATION'),
+ ("texmode", 'SECONDARY'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'X', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'DRAW'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'S', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'SMOOTH'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'P', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'PINCH'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'I', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'INFLATE'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'G', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'GRAB'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'LAYER'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'T', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'FLATTEN'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'C', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'CLAY'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'C', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'CREASE'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'K', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'SNAKE_HOOK'),
+ ],
+ }
+ ),
+ (
+ "paint.brush_select",
+ {"type": 'M', "value": 'PRESS'},
+ {
+ "properties": [
+ ("paint_mode", 'SCULPT'),
+ ("sculpt_tool", 'MASK'),
+ ("toggle", True),
+ ("create_missing", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_menu_enum",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.sculpt.brush.stroke_method'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'S', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.sculpt.brush.use_smooth_stroke'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'R', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_angle_control'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Mesh",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("mesh.loopcut_slide", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
+ ("mesh.offset_edge_loops_slide", {"type": 'R', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("mesh.inset", {"type": 'I', "value": 'PRESS'}, None),
+ ("mesh.poke", {"type": 'P', "value": 'PRESS', "alt": True}, None),
+ (
+ "mesh.bevel",
+ {"type": 'B', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("vertex_only", False),
+ ],
+ }
+ ),
+ (
+ "mesh.bevel",
+ {"type": 'B', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("vertex_only", True),
+ ],
+ }
+ ),
+ (
+ "mesh.loop_select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", False),
+ ],
+ }
+ ),
+ (
+ "mesh.loop_select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", True),
+ ],
+ }
+ ),
+ (
+ "mesh.edgering_select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", False),
+ ],
+ }
+ ),
+ (
+ "mesh.edgering_select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", True),
+ ],
+ }
+ ),
+ (
+ "mesh.shortest_path_pick",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("use_fill", False),
+ ],
+ }
+ ),
+ (
+ "mesh.shortest_path_pick",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("use_fill", True),
+ ],
+ }
+ ),
+ (
+ "mesh.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "mesh.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("mesh.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("mesh.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("mesh.select_next_item", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("mesh.select_prev_item", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("mesh.select_non_manifold", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ ("mesh.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "mesh.select_linked_pick",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "mesh.select_linked_pick",
+ {"type": 'L', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("mesh.faces_select_linked_flat", {"type": 'F', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'G', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_select_similar'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'TAB', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_select_mode'),
+ ],
+ }
+ ),
+ (
+ "mesh.hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "mesh.hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("mesh.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ (
+ "mesh.normals_make_consistent",
+ {"type": 'N', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("inside", False),
+ ],
+ }
+ ),
+ (
+ "mesh.normals_make_consistent",
+ {"type": 'N', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("inside", True),
+ ],
+ }
+ ),
+ ("view3d.edit_mesh_extrude_move_normal", {"type": 'E', "value": 'PRESS'}, None),
+ (
+ "wm.call_menu",
+ {"type": 'E', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_extrude'),
+ ],
+ }
+ ),
+ ("transform.edge_crease", {"type": 'E', "value": 'PRESS', "shift": True}, None),
+ ("mesh.spin", {"type": 'R', "value": 'PRESS', "alt": True}, None),
+ ("mesh.fill", {"type": 'F', "value": 'PRESS', "alt": True}, None),
+ ("mesh.beautify_fill", {"type": 'F', "value": 'PRESS', "shift": True, "alt": True}, None),
+ (
+ "mesh.quads_convert_to_tris",
+ {"type": 'T', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("quad_method", 'BEAUTY'),
+ ("ngon_method", 'BEAUTY'),
+ ],
+ }
+ ),
+ (
+ "mesh.quads_convert_to_tris",
+ {"type": 'T', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("quad_method", 'FIXED'),
+ ("ngon_method", 'CLIP'),
+ ],
+ }
+ ),
+ ("mesh.tris_convert_to_quads", {"type": 'J', "value": 'PRESS', "alt": True}, None),
+ (
+ "mesh.rip_move",
+ {"type": 'V', "value": 'PRESS'},
+ {
+ "properties": [
+ (
+ "MESH_OT_rip",
+ [
+ ("use_fill", False),
+ ],
+ ),
+ ],
+ }
+ ),
+ (
+ "mesh.rip_move",
+ {"type": 'V', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ (
+ "MESH_OT_rip",
+ [
+ ("use_fill", True),
+ ],
+ ),
+ ],
+ }
+ ),
+ ("mesh.rip_edge_move", {"type": 'D', "value": 'PRESS', "alt": True}, None),
+ ("mesh.merge", {"type": 'M', "value": 'PRESS', "alt": True}, None),
+ ("transform.shrink_fatten", {"type": 'S', "value": 'PRESS', "alt": True}, None),
+ ("mesh.edge_face_add", {"type": 'F', "value": 'PRESS'}, None),
+ ("mesh.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'INFO_MT_mesh_add'),
+ ],
+ }
+ ),
+ ("mesh.separate", {"type": 'P', "value": 'PRESS'}, None),
+ ("mesh.split", {"type": 'Y', "value": 'PRESS'}, None),
+ ("mesh.vert_connect_path", {"type": 'J', "value": 'PRESS'}, None),
+ ("transform.vert_slide", {"type": 'V', "value": 'PRESS', "shift": True}, None),
+ (
+ "mesh.dupli_extrude_cursor",
+ {"type": 'ACTIONMOUSE', "value": 'CLICK', "ctrl": True},
+ {
+ "properties": [
+ ("rotate_source", True),
+ ],
+ }
+ ),
+ (
+ "mesh.dupli_extrude_cursor",
+ {"type": 'ACTIONMOUSE', "value": 'CLICK', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("rotate_source", False),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'X', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_delete'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_delete'),
+ ],
+ }
+ ),
+ ("mesh.dissolve_mode", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
+ ("mesh.dissolve_mode", {"type": 'DEL', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "mesh.knife_tool",
+ {"type": 'K', "value": 'PRESS'},
+ {
+ "properties": [
+ ("use_occlude_geometry", True),
+ ("only_selected", False),
+ ],
+ }
+ ),
+ (
+ "mesh.knife_tool",
+ {"type": 'K', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("use_occlude_geometry", False),
+ ("only_selected", True),
+ ],
+ }
+ ),
+ ("object.vertex_parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_specials'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'F', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_faces'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'E', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_edges'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'V', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_mesh_vertices'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'H', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_hook'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'U', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_uv_map'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'G', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_vertex_group'),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'ZERO', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 0),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'ONE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 1),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'TWO', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 2),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'THREE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 3),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'FOUR', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 4),
+ ],
+ }
+ ),
+ (
+ "object.subdivision_set",
+ {"type": 'FIVE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("level", 5),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'ENABLED'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'CONNECTED'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Armature",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "armature.hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "armature.hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("armature.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ ("armature.align", {"type": 'A', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("armature.calculate_roll", {"type": 'N', "value": 'PRESS', "ctrl": True}, None),
+ ("armature.roll_clear", {"type": 'R', "value": 'PRESS', "alt": True}, None),
+ ("armature.switch_direction", {"type": 'F', "value": 'PRESS', "alt": True}, None),
+ ("armature.bone_primitive_add", {"type": 'A', "value": 'PRESS', "shift": True}, None),
+ ("armature.parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ ("armature.parent_clear", {"type": 'P', "value": 'PRESS', "alt": True}, None),
+ (
+ "armature.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "armature.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ (
+ "armature.select_mirror",
+ {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "armature.select_hierarchy",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'PARENT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "armature.select_hierarchy",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'PARENT'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "armature.select_hierarchy",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'CHILD'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "armature.select_hierarchy",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'CHILD'),
+ ("extend", True),
+ ],
+ }
+ ),
+ ("armature.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("armature.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("armature.select_similar", {"type": 'G', "value": 'PRESS', "shift": True}, None),
+ ("armature.select_linked", {"type": 'L', "value": 'PRESS'}, None),
+ ("armature.shortest_path_pick", {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'X', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_armature_delete'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_edit_armature_delete'),
+ ],
+ }
+ ),
+ ("armature.dissolve", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
+ ("armature.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("armature.extrude_move", {"type": 'E', "value": 'PRESS'}, None),
+ ("armature.extrude_forked", {"type": 'E', "value": 'PRESS', "shift": True}, None),
+ ("armature.click_extrude", {"type": 'ACTIONMOUSE', "value": 'CLICK', "ctrl": True}, None),
+ ("armature.fill", {"type": 'F', "value": 'PRESS'}, None),
+ ("armature.merge", {"type": 'M', "value": 'PRESS', "alt": True}, None),
+ ("armature.split", {"type": 'Y', "value": 'PRESS'}, None),
+ ("armature.separate", {"type": 'P', "value": 'PRESS'}, None),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_bone_options_toggle'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_bone_options_enable'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_bone_options_disable'),
+ ],
+ }
+ ),
+ ("armature.layers_show_all", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "ctrl": True}, None),
+ ("armature.armature_layers", {"type": 'M', "value": 'PRESS', "shift": True}, None),
+ ("armature.bone_layers", {"type": 'M', "value": 'PRESS'}, None),
+ (
+ "transform.transform",
+ {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("mode", 'BONE_SIZE'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'S', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'BONE_ENVELOPE'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'R', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'BONE_ROLL'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_armature_specials'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Metaball",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("object.metaball_add", {"type": 'A', "value": 'PRESS', "shift": True}, None),
+ ("mball.reveal_metaelems", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ (
+ "mball.hide_metaelems",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "mball.hide_metaelems",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("mball.delete_metaelems", {"type": 'X', "value": 'PRESS'}, None),
+ ("mball.delete_metaelems", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("mball.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ (
+ "mball.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "mball.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("mball.select_similar", {"type": 'G', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'ENABLED'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'CONNECTED'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Lattice",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "lattice.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "lattice.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("lattice.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("lattice.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("object.vertex_parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ ("lattice.flip", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'H', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_hook'),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'ENABLED'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Particle",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "particle.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "particle.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("particle.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("particle.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "particle.select_linked",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "particle.select_linked",
+ {"type": 'L', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("particle.delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("particle.delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("particle.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ (
+ "particle.hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "particle.hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("particle.brush_edit", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("particle.brush_edit", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.particle_edit.brush.size'),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.particle_edit.brush.strength'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_particle_specials'),
+ ],
+ }
+ ),
+ ("particle.weight_set", {"type": 'K', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'ENABLED'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Font",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "font.style_toggle",
+ {"type": 'B', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("style", 'BOLD'),
+ ],
+ }
+ ),
+ (
+ "font.style_toggle",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("style", 'ITALIC'),
+ ],
+ }
+ ),
+ (
+ "font.style_toggle",
+ {"type": 'U', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("style", 'UNDERLINE'),
+ ],
+ }
+ ),
+ (
+ "font.style_toggle",
+ {"type": 'P', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("style", 'SMALL_CAPS'),
+ ],
+ }
+ ),
+ (
+ "font.delete",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_OR_SELECTION'),
+ ],
+ }
+ ),
+ (
+ "font.delete",
+ {"type": 'DEL', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'NEXT_WORD'),
+ ],
+ }
+ ),
+ (
+ "font.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_OR_SELECTION'),
+ ],
+ }
+ ),
+ (
+ "font.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_OR_SELECTION'),
+ ],
+ }
+ ),
+ (
+ "font.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_WORD'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'HOME', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'LINE_BEGIN'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'END', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'LINE_END'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'LEFT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_WORD'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'NEXT_WORD'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'UP_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_LINE'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'DOWN_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_LINE'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'PAGE_UP', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_PAGE'),
+ ],
+ }
+ ),
+ (
+ "font.move",
+ {"type": 'PAGE_DOWN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_PAGE'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'HOME', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'LINE_BEGIN'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'END', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'LINE_END'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'NEXT_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_WORD'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'NEXT_WORD'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'UP_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_LINE'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'NEXT_LINE'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'PAGE_UP', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_PAGE'),
+ ],
+ }
+ ),
+ (
+ "font.move_select",
+ {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'NEXT_PAGE'),
+ ],
+ }
+ ),
+ (
+ "font.change_spacing",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ (
+ "font.change_spacing",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "font.change_character",
+ {"type": 'UP_ARROW', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "font.change_character",
+ {"type": 'DOWN_ARROW', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ ("font.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, None),
+ ("font.text_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("font.text_cut", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
+ ("font.text_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ ("font.line_break", {"type": 'RET', "value": 'PRESS'}, None),
+ ("font.text_insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
+ (
+ "font.text_insert",
+ {"type": 'BACK_SPACE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("accent", True),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Object Non-modal",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "object.mode_set",
+ {"type": 'TAB', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'EDIT'),
+ ("toggle", True),
+ ],
+ }
+ ),
+ (
+ "object.mode_set",
+ {"type": 'TAB', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'POSE'),
+ ("toggle", True),
+ ],
+ }
+ ),
+ (
+ "object.mode_set",
+ {"type": 'V', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'VERTEX_PAINT'),
+ ("toggle", True),
+ ],
+ }
+ ),
+ (
+ "object.mode_set",
+ {"type": 'TAB', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'WEIGHT_PAINT'),
+ ("toggle", True),
+ ],
+ }
+ ),
+ ("object.origin_set", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ ],
+ },
+ ),
+ (
+ "3D View",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("view3d.cursor3d", {"type": 'ACTIONMOUSE', "value": 'CLICK'}, None),
+ ("view3d.rotate", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("view3d.move", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("view3d.zoom", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("view3d.dolly", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "view3d.view_selected",
+ {"type": 'NUMPAD_PERIOD', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("use_all_regions", True),
+ ],
+ }
+ ),
+ (
+ "view3d.view_selected",
+ {"type": 'NUMPAD_PERIOD', "value": 'PRESS'},
+ {
+ "properties": [
+ ("use_all_regions", False),
+ ],
+ }
+ ),
+ ("view3d.view_lock_to_active", {"type": 'NUMPAD_PERIOD', "value": 'PRESS', "shift": True}, None),
+ ("view3d.view_lock_clear", {"type": 'NUMPAD_PERIOD', "value": 'PRESS', "alt": True}, None),
+ ("view3d.navigate", {"type": 'F', "value": 'PRESS', "shift": True}, None),
+ ("view3d.smoothview", {"type": 'TIMER1', "value": 'ANY', "any": True}, None),
+ ("view3d.rotate", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
+ ("view3d.rotate", {"type": 'MOUSEROTATE', "value": 'ANY'}, None),
+ ("view3d.move", {"type": 'TRACKPADPAN', "value": 'ANY', "shift": True}, None),
+ ("view3d.zoom", {"type": 'TRACKPADZOOM', "value": 'ANY'}, None),
+ ("view3d.zoom", {"type": 'TRACKPADPAN', "value": 'ANY', "ctrl": True}, None),
+ (
+ "view3d.zoom",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "view3d.zoom",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ (
+ "view3d.zoom",
+ {"type": 'EQUAL', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "view3d.zoom",
+ {"type": 'MINUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ (
+ "view3d.zoom",
+ {"type": 'WHEELINMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "view3d.zoom",
+ {"type": 'WHEELOUTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ (
+ "view3d.dolly",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "view3d.dolly",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ (
+ "view3d.dolly",
+ {"type": 'EQUAL', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("delta", 1),
+ ],
+ }
+ ),
+ (
+ "view3d.dolly",
+ {"type": 'MINUS', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("delta", -1),
+ ],
+ }
+ ),
+ ("view3d.zoom_camera_1_to_1", {"type": 'NUMPAD_ENTER', "value": 'PRESS', "shift": True}, None),
+ ("view3d.view_center_camera", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("view3d.view_center_lock", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("view3d.view_center_cursor", {"type": 'HOME', "value": 'PRESS', "alt": True}, None),
+ ("view3d.view_center_pick", {"type": 'F', "value": 'PRESS', "alt": True}, None),
+ (
+ "view3d.view_all",
+ {"type": 'HOME', "value": 'PRESS'},
+ {
+ "properties": [
+ ("center", False),
+ ],
+ }
+ ),
+ (
+ "view3d.view_all",
+ {"type": 'HOME', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("use_all_regions", True),
+ ("center", False),
+ ],
+ }
+ ),
+ (
+ "view3d.view_all",
+ {"type": 'C', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("center", True),
+ ],
+ }
+ ),
+ ("view3d.view_camera", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_1', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'FRONT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_orbit",
+ {"type": 'NUMPAD_2', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'ORBITDOWN'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_3', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'RIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_orbit",
+ {"type": 'NUMPAD_4', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'ORBITLEFT'),
+ ],
+ }
+ ),
+ ("view3d.view_persportho", {"type": 'NUMPAD_5', "value": 'PRESS'}, None),
+ (
+ "view3d.view_orbit",
+ {"type": 'NUMPAD_6', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'ORBITRIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_7', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'TOP'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_orbit",
+ {"type": 'NUMPAD_8', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'ORBITUP'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_1', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'BACK'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_3', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'LEFT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_7', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'BOTTOM'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_pan",
+ {"type": 'NUMPAD_2', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PANDOWN'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_pan",
+ {"type": 'NUMPAD_4', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PANLEFT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_pan",
+ {"type": 'NUMPAD_6', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PANRIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_pan",
+ {"type": 'NUMPAD_8', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PANUP'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_roll",
+ {"type": 'NUMPAD_4', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'LEFT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_roll",
+ {"type": 'NUMPAD_6', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'RIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_orbit",
+ {"type": 'NUMPAD_9', "value": 'PRESS'},
+ {
+ "properties": [
+ ("angle", 3.1415927),
+ ("type", 'ORBITRIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_pan",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PANRIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_pan",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PANLEFT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_pan",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PANUP'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_pan",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PANDOWN'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_orbit",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("type", 'ORBITLEFT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_orbit",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("type", 'ORBITRIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_orbit",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("type", 'ORBITUP'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_orbit",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("type", 'ORBITDOWN'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_roll",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'LEFT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_roll",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'RIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_1', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'FRONT'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_3', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'RIGHT'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_7', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'TOP'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_1', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'BACK'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_3', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'LEFT'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NUMPAD_7', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'BOTTOM'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ ("view3d.ndof_orbit_zoom", {"type": 'NDOF_MOTION', "value": 'ANY'}, None),
+ ("view3d.ndof_orbit", {"type": 'NDOF_MOTION', "value": 'ANY', "ctrl": True}, None),
+ ("view3d.ndof_pan", {"type": 'NDOF_MOTION', "value": 'ANY', "shift": True}, None),
+ ("view3d.ndof_all", {"type": 'NDOF_MOTION', "value": 'ANY', "shift": True, "ctrl": True}, None),
+ (
+ "view3d.view_selected",
+ {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("use_all_regions", False),
+ ],
+ }
+ ),
+ (
+ "view3d.view_roll",
+ {"type": 'NDOF_BUTTON_ROLL_CCW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'LEFT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_roll",
+ {"type": 'NDOF_BUTTON_ROLL_CCW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'RIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_FRONT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'FRONT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_BACK', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'BACK'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_LEFT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'LEFT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_RIGHT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'RIGHT'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_TOP', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'TOP'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_BOTTOM', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'BOTTOM'),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_FRONT', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'FRONT'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_RIGHT', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'RIGHT'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ (
+ "view3d.view_axis",
+ {"type": 'NDOF_BUTTON_TOP', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'TOP'),
+ ("align_active", True),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'ACCENT_GRAVE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("nr", 0),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'ONE', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 1),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'TWO', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 2),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'THREE', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 3),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'FOUR', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 4),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'FIVE', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 5),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'SIX', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 6),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'SEVEN', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 7),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'EIGHT', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 8),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'NINE', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 9),
+ ],
+ }
+ ),
+ (
+ "view3d.layers",
+ {"type": 'ZERO', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("nr", 10),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'Z', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.shading.type'),
+ ("value_1", 'SOLID'),
+ ("value_2", 'TEXTURED'),
+ ],
+ }
+ ),
+ ("view3d.toggle_render", {"type": 'Z', "value": 'PRESS', "shift": True}, None),
+ ("view3d.toggle_xray_draw_option", {"type": 'Z', "value": 'PRESS'}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'Z', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.use_occlude_geometry'),
+ ],
+ }
+ ),
+ (
+ "view3d.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", False),
+ ("center", False),
+ ("enumerate", False),
+ ("object", False),
+ ],
+ }
+ ),
+ (
+ "view3d.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", True),
+ ("center", False),
+ ("enumerate", False),
+ ("object", False),
+ ],
+ }
+ ),
+ (
+ "view3d.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", False),
+ ("center", True),
+ ("enumerate", False),
+ ("object", True),
+ ],
+ }
+ ),
+ (
+ "view3d.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", False),
+ ("center", False),
+ ("enumerate", True),
+ ("object", False),
+ ],
+ }
+ ),
+ (
+ "view3d.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("deselect", False),
+ ("toggle", True),
+ ("center", True),
+ ("enumerate", False),
+ ("object", False),
+ ],
+ }
+ ),
+ (
+ "view3d.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", False),
+ ("center", True),
+ ("enumerate", True),
+ ("object", False),
+ ],
+ }
+ ),
+ (
+ "view3d.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", True),
+ ("center", False),
+ ("enumerate", True),
+ ("object", False),
+ ],
+ }
+ ),
+ (
+ "view3d.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", True),
+ ("center", True),
+ ("enumerate", True),
+ ("object", False),
+ ],
+ }
+ ),
+ ("view3d.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ (
+ "view3d.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "view3d.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("view3d.select_circle", {"type": 'C', "value": 'PRESS'}, None),
+ ("view3d.clip_border", {"type": 'B', "value": 'PRESS', "alt": True}, None),
+ ("view3d.zoom_border", {"type": 'B', "value": 'PRESS', "shift": True}, None),
+ ("view3d.render_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
+ ("view3d.clear_render_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("view3d.camera_to_view", {"type": 'NUMPAD_0', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("view3d.object_as_camera", {"type": 'NUMPAD_0', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'S', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'VIEW3D_MT_snap'),
+ ],
+ }
+ ),
+ ("view3d.copybuffer", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("view3d.pastebuffer", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.context_set_enum",
+ {"type": 'COMMA', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.transform_pivot_point'),
+ ("value", 'BOUNDING_BOX_CENTER'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'COMMA', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.transform_pivot_point'),
+ ("value", 'MEDIAN_POINT'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'COMMA', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_transform_pivot_point_align'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'PERIOD', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.transform_pivot_point'),
+ ("value", 'CURSOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'PERIOD', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.transform_pivot_point'),
+ ("value", 'INDIVIDUAL_ORIGINS'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'PERIOD', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.transform_pivot_point'),
+ ("value", 'ACTIVE_ELEMENT'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'SPACE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.show_manipulator'),
+ ],
+ }
+ ),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ ("transform.bend", {"type": 'W', "value": 'PRESS', "shift": True}, None),
+ ("transform.tosphere", {"type": 'S', "value": 'PRESS', "shift": True, "alt": True}, None),
+ ("transform.shear", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ ("transform.select_orientation", {"type": 'SPACE', "value": 'PRESS', "alt": True}, None),
+ (
+ "transform.create_orientation",
+ {"type": 'SPACE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("use", True),
+ ],
+ }
+ ),
+ ("transform.mirror", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'TAB', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_snap'),
+ ],
+ }
+ ),
+ (
+ "wm.context_menu_enum",
+ {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.snap_element'),
+ ],
+ }
+ ),
+ ("object.transform_axis_target", {"type": 'T', "value": 'PRESS', "shift": True}, None),
+ (
+ "transform.translate",
+ {"type": 'T', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("texture_space", True),
+ ],
+ }
+ ),
+ (
+ "transform.resize",
+ {"type": 'T', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("texture_space", True),
+ ],
+ }
+ ),
+ ("transform.skin_resize", {"type": 'A', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "Manipulators",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ],
+ },
+ ),
+ (
+ "Backdrop Transform Widget",
+ {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Backdrop Crop Widget",
+ {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Sun Beams Widget",
+ {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Corner Pin Widget",
+ {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "UV Transform Manipulator",
+ {"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Spot Light Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Area Light Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Target Light Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Force Field Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Camera Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Camera View Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Armature Spline Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "View3D Navigate",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Animation",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("anim.change_frame", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'T', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.show_seconds'),
+ ],
+ }
+ ),
+ ("anim.previewrange_set", {"type": 'P', "value": 'PRESS'}, None),
+ ("anim.previewrange_clear", {"type": 'P', "value": 'PRESS', "alt": True}, None),
+ ],
+ },
+ ),
+ (
+ "Animation Channels",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("anim.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ (
+ "anim.channels_click",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "anim.channels_click",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("children_only", True),
+ ],
+ }
+ ),
+ ("anim.channels_rename", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("anim.channels_rename", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
+ ("anim.channel_select_keys", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
+ (
+ "anim.channel_select_keys",
+ {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ ("anim.channels_find", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "anim.channels_select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "anim.channels_select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("anim.channels_select_border", {"type": 'B', "value": 'PRESS'}, None),
+ ("anim.channels_select_border", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
+ ("anim.channels_delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("anim.channels_delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("anim.channels_setting_toggle", {"type": 'W', "value": 'PRESS', "shift": True}, None),
+ ("anim.channels_setting_enable", {"type": 'W', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("anim.channels_setting_disable", {"type": 'W', "value": 'PRESS', "alt": True}, None),
+ ("anim.channels_editable_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
+ ("anim.channels_expand", {"type": 'NUMPAD_PLUS', "value": 'PRESS'}, None),
+ ("anim.channels_collapse", {"type": 'NUMPAD_MINUS', "value": 'PRESS'}, None),
+ (
+ "anim.channels_expand",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("all", False),
+ ],
+ }
+ ),
+ (
+ "anim.channels_collapse",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("all", False),
+ ],
+ }
+ ),
+ (
+ "anim.channels_move",
+ {"type": 'PAGE_UP', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'UP'),
+ ],
+ }
+ ),
+ (
+ "anim.channels_move",
+ {"type": 'PAGE_DOWN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'DOWN'),
+ ],
+ }
+ ),
+ (
+ "anim.channels_move",
+ {"type": 'PAGE_UP', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'TOP'),
+ ],
+ }
+ ),
+ (
+ "anim.channels_move",
+ {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'BOTTOM'),
+ ],
+ }
+ ),
+ ("anim.channels_group", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
+ ("anim.channels_ungroup", {"type": 'G', "value": 'PRESS', "alt": True}, None),
+ ],
+ },
+ ),
+ (
+ "UV Editor",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "wm.context_toggle",
+ {"type": 'Q', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_uv_sculpt'),
+ ],
+ }
+ ),
+ ("uv.mark_seam", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "uv.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "uv.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "uv.select_loop",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "uv.select_loop",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ ("uv.select_split", {"type": 'Y', "value": 'PRESS'}, None),
+ (
+ "uv.select_border",
+ {"type": 'B', "value": 'PRESS'},
+ {
+ "properties": [
+ ("pinned", False),
+ ],
+ }
+ ),
+ (
+ "uv.select_border",
+ {"type": 'B', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("pinned", True),
+ ],
+ }
+ ),
+ ("uv.circle_select", {"type": 'C', "value": 'PRESS'}, None),
+ (
+ "uv.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "uv.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ (
+ "uv.select_linked",
+ {"type": 'L', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "uv.select_linked_pick",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", True),
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "uv.select_linked",
+ {"type": 'L', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", True),
+ ],
+ }
+ ),
+ (
+ "uv.select_linked_pick",
+ {"type": 'L', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("uv.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("uv.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "uv.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "uv.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("uv.select_pinned", {"type": 'P', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'IMAGE_MT_uvs_weldalign'),
+ ],
+ }
+ ),
+ ("uv.stitch", {"type": 'V', "value": 'PRESS'}, None),
+ (
+ "uv.pin",
+ {"type": 'P', "value": 'PRESS'},
+ {
+ "properties": [
+ ("clear", False),
+ ],
+ }
+ ),
+ (
+ "uv.pin",
+ {"type": 'P', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("clear", True),
+ ],
+ }
+ ),
+ ("uv.unwrap", {"type": 'E', "value": 'PRESS'}, None),
+ ("uv.minimize_stretch", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ ("uv.pack_islands", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ ("uv.average_islands_scale", {"type": 'A', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "uv.hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "uv.hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("uv.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ ("uv.cursor_set", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ (
+ "wm.call_menu",
+ {"type": 'S', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'IMAGE_MT_uvs_snap'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'TAB', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("name", 'IMAGE_MT_uvs_select_mode'),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit'),
+ ("value_1", 'DISABLED'),
+ ("value_2", 'ENABLED'),
+ ],
+ }
+ ),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ ("transform.shear", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ ("transform.mirror", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'TAB', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_snap'),
+ ],
+ }
+ ),
+ (
+ "wm.context_menu_enum",
+ {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.snap_uv_element'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "UV Sculpt",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "wm.context_toggle",
+ {"type": 'Q', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_uv_sculpt'),
+ ],
+ }
+ ),
+ (
+ "sculpt.uv_sculpt_stroke",
+ {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'NORMAL'),
+ ],
+ }
+ ),
+ (
+ "sculpt.uv_sculpt_stroke",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'INVERT'),
+ ],
+ }
+ ),
+ (
+ "sculpt.uv_sculpt_stroke",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'RELAX'),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 0.9),
+ ],
+ }
+ ),
+ (
+ "brush.scale_size",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("scalar", 1.1111112),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.uv_sculpt.brush.size'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.size'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_size'),
+ ("rotation_path", 'tool_settings.uv_sculpt.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.uv_sculpt.brush.cursor_color_add'),
+ ("fill_color_path", ''),
+ ("fill_color_override_path", ''),
+ ("fill_color_override_test_path", ''),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.uv_sculpt.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "wm.radial_control",
+ {"type": 'F', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path_primary", 'tool_settings.uv_sculpt.brush.strength'),
+ ("data_path_secondary", 'tool_settings.unified_paint_settings.strength'),
+ ("use_secondary", 'tool_settings.unified_paint_settings.use_unified_strength'),
+ ("rotation_path", 'tool_settings.uv_sculpt.brush.texture_slot.angle'),
+ ("color_path", 'tool_settings.uv_sculpt.brush.cursor_color_add'),
+ ("fill_color_path", ''),
+ ("fill_color_override_path", ''),
+ ("fill_color_override_test_path", ''),
+ ("zoom_path", ''),
+ ("image_id", 'tool_settings.uv_sculpt.brush'),
+ ("secondary_tex", False),
+ ],
+ }
+ ),
+ (
+ "brush.uv_sculpt_tool_set",
+ {"type": 'S', "value": 'PRESS'},
+ {
+ "properties": [
+ ("tool", 'RELAX'),
+ ],
+ }
+ ),
+ (
+ "brush.uv_sculpt_tool_set",
+ {"type": 'P', "value": 'PRESS'},
+ {
+ "properties": [
+ ("tool", 'PINCH'),
+ ],
+ }
+ ),
+ (
+ "brush.uv_sculpt_tool_set",
+ {"type": 'G', "value": 'PRESS'},
+ {
+ "properties": [
+ ("tool", 'GRAB'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Mask Editing",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("mask.new", {"type": 'N', "value": 'PRESS', "alt": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'MASK_MT_add'),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_enum",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.proportional_edit_falloff'),
+ ("wrap", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_proportional_edit_mask'),
+ ],
+ }
+ ),
+ ("mask.add_vertex_slide", {"type": 'ACTIONMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("mask.add_feather_vertex_slide", {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("mask.delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("mask.delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ (
+ "mask.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", False),
+ ],
+ }
+ ),
+ (
+ "mask.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("deselect", False),
+ ("toggle", True),
+ ],
+ }
+ ),
+ (
+ "mask.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "mask.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("mask.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "mask.select_linked_pick",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "mask.select_linked_pick",
+ {"type": 'L', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("mask.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ ("mask.select_circle", {"type": 'C', "value": 'PRESS'}, None),
+ (
+ "mask.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "mask.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("mask.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("mask.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("mask.hide_view_clear", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ (
+ "mask.hide_view_set",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "mask.hide_view_set",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ (
+ "clip.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ ("mask.cyclic_toggle", {"type": 'C', "value": 'PRESS', "alt": True}, None),
+ ("mask.slide_point", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ ("mask.slide_spline_curvature", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ ("mask.handle_type_set", {"type": 'V', "value": 'PRESS'}, None),
+ ("mask.normals_make_consistent", {"type": 'N', "value": 'PRESS', "ctrl": True}, None),
+ ("mask.parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ ("mask.parent_clear", {"type": 'P', "value": 'PRESS', "alt": True}, None),
+ ("mask.shape_key_insert", {"type": 'I', "value": 'PRESS'}, None),
+ ("mask.shape_key_clear", {"type": 'I', "value": 'PRESS', "alt": True}, None),
+ ("mask.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("mask.copy_splines", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("mask.paste_splines", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ ("uv.cursor_set", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ (
+ "transform.transform",
+ {"type": 'S', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'MASK_SHRINKFATTEN'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Markers",
+ {"space_type": 'EMPTY', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("marker.add", {"type": 'M', "value": 'PRESS'}, None),
+ ("marker.move", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ ("marker.duplicate", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("marker.select", {"type": 'SELECTMOUSE', "value": 'PRESS'}, None),
+ (
+ "marker.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "marker.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("camera", True),
+ ],
+ }
+ ),
+ (
+ "marker.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("camera", True),
+ ],
+ }
+ ),
+ ("marker.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ ("marker.select_all", {"type": 'A', "value": 'PRESS'}, None),
+ ("marker.delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("marker.delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ ("marker.move", {"type": 'G', "value": 'PRESS'}, None),
+ ("marker.camera_bind", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "Graph Editor Generic",
+ {"space_type": 'GRAPH_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("graph.properties", {"type": 'N', "value": 'PRESS'}, None),
+ ("graph.extrapolation_type", {"type": 'E', "value": 'PRESS', "shift": True}, None),
+ ("anim.channels_find", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "graph.hide",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "graph.hide",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("graph.reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ ],
+ },
+ ),
+ (
+ "Graph Editor",
+ {"space_type": 'GRAPH_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "wm.context_toggle",
+ {"type": 'H', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.show_handles'),
+ ],
+ }
+ ),
+ ("graph.cursor_set", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ (
+ "graph.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ("column", False),
+ ("curves", False),
+ ],
+ }
+ ),
+ (
+ "graph.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("column", True),
+ ("curves", False),
+ ],
+ }
+ ),
+ (
+ "graph.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("column", False),
+ ("curves", False),
+ ],
+ }
+ ),
+ (
+ "graph.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("column", True),
+ ("curves", False),
+ ],
+ }
+ ),
+ (
+ "graph.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("column", False),
+ ("curves", True),
+ ],
+ }
+ ),
+ (
+ "graph.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("column", False),
+ ("curves", True),
+ ],
+ }
+ ),
+ (
+ "graph.select_leftright",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'CHECK'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "graph.select_leftright",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'CHECK'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "graph.select_leftright",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'LEFT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "graph.select_leftright",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'RIGHT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "graph.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "graph.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ (
+ "graph.select_border",
+ {"type": 'B', "value": 'PRESS'},
+ {
+ "properties": [
+ ("axis_range", False),
+ ("include_handles", False),
+ ],
+ }
+ ),
+ (
+ "graph.select_border",
+ {"type": 'B', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("axis_range", True),
+ ("include_handles", False),
+ ],
+ }
+ ),
+ (
+ "graph.select_border",
+ {"type": 'B', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("axis_range", False),
+ ("include_handles", True),
+ ],
+ }
+ ),
+ (
+ "graph.select_border",
+ {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("axis_range", True),
+ ("include_handles", True),
+ ],
+ }
+ ),
+ (
+ "graph.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "graph.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("graph.select_circle", {"type": 'C', "value": 'PRESS'}, None),
+ (
+ "graph.select_column",
+ {"type": 'K', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'KEYS'),
+ ],
+ }
+ ),
+ (
+ "graph.select_column",
+ {"type": 'K', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'CFRA'),
+ ],
+ }
+ ),
+ (
+ "graph.select_column",
+ {"type": 'K', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'MARKERS_COLUMN'),
+ ],
+ }
+ ),
+ (
+ "graph.select_column",
+ {"type": 'K', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'MARKERS_BETWEEN'),
+ ],
+ }
+ ),
+ ("graph.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("graph.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("graph.select_linked", {"type": 'L', "value": 'PRESS'}, None),
+ ("graph.frame_jump", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
+ ("graph.snap", {"type": 'S', "value": 'PRESS', "shift": True}, None),
+ ("graph.mirror", {"type": 'M', "value": 'PRESS', "shift": True}, None),
+ ("graph.handle_type", {"type": 'V', "value": 'PRESS'}, None),
+ ("graph.interpolation_type", {"type": 'T', "value": 'PRESS'}, None),
+ ("graph.easing_type", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
+ ("graph.smooth", {"type": 'O', "value": 'PRESS', "alt": True}, None),
+ ("graph.sample", {"type": 'O', "value": 'PRESS', "shift": True}, None),
+ ("graph.bake", {"type": 'C', "value": 'PRESS', "alt": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'X', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'GRAPH_MT_delete'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'GRAPH_MT_delete'),
+ ],
+ }
+ ),
+ ("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
+ (
+ "graph.click_insert",
+ {"type": 'ACTIONMOUSE', "value": 'CLICK', "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "graph.click_insert",
+ {"type": 'ACTIONMOUSE', "value": 'CLICK', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ ("graph.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("graph.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "graph.paste",
+ {"type": 'V', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("flipped", True),
+ ],
+ }
+ ),
+ ("graph.previewrange_set", {"type": 'P', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("graph.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("graph.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("graph.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ ("graph.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
+ (
+ "graph.fmodifier_add",
+ {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("only_active", False),
+ ],
+ }
+ ),
+ ("anim.channels_editable_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ (
+ "transform.transform",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TIME_EXTEND'),
+ ],
+ }
+ ),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_proportional_fcurve'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'COMMA', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'BOUNDING_BOX_CENTER'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'PERIOD', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'CURSOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'PERIOD', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'INDIVIDUAL_ORIGINS'),
+ ],
+ }
+ ),
+ ("marker.add", {"type": 'M', "value": 'PRESS'}, None),
+ ("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "Image Generic",
+ {"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("image.new", {"type": 'N', "value": 'PRESS', "alt": True}, None),
+ ("image.open", {"type": 'O', "value": 'PRESS', "alt": True}, None),
+ ("image.reload", {"type": 'R', "value": 'PRESS', "alt": True}, None),
+ ("image.read_viewlayers", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
+ ("image.save", {"type": 'S', "value": 'PRESS', "alt": True}, None),
+ ("image.save_as", {"type": 'F3', "value": 'PRESS'}, None),
+ ("image.properties", {"type": 'N', "value": 'PRESS'}, None),
+ ("image.toolshelf", {"type": 'T', "value": 'PRESS'}, None),
+ ("image.cycle_render_slot", {"type": 'J', "value": 'PRESS'}, None),
+ (
+ "image.cycle_render_slot",
+ {"type": 'J', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("reverse", True),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Image",
+ {"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("image.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ (
+ "image.view_all",
+ {"type": 'HOME', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("fit_view", True),
+ ],
+ }
+ ),
+ ("image.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ ("image.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("image.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("image.view_pan", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
+ ("image.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("image.view_ndof", {"type": 'NDOF_MOTION', "value": 'ANY'}, None),
+ ("image.view_zoom_in", {"type": 'WHEELINMOUSE', "value": 'PRESS'}, None),
+ ("image.view_zoom_out", {"type": 'WHEELOUTMOUSE', "value": 'PRESS'}, None),
+ ("image.view_zoom_in", {"type": 'NUMPAD_PLUS', "value": 'PRESS'}, None),
+ ("image.view_zoom_out", {"type": 'NUMPAD_MINUS', "value": 'PRESS'}, None),
+ ("image.view_zoom", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("image.view_zoom", {"type": 'TRACKPADZOOM', "value": 'ANY'}, None),
+ ("image.view_zoom", {"type": 'TRACKPADPAN', "value": 'ANY', "ctrl": True}, None),
+ ("image.view_zoom_border", {"type": 'B', "value": 'PRESS', "shift": True}, None),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_8', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("ratio", 8.0),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_4', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("ratio", 4.0),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_2', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("ratio", 2.0),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_8', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("ratio", 8.0),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_4', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("ratio", 4.0),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_2', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("ratio", 2.0),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_1', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 1.0),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_2', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 0.5),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_4', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 0.25),
+ ],
+ }
+ ),
+ (
+ "image.view_zoom_ratio",
+ {"type": 'NUMPAD_8', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 0.125),
+ ],
+ }
+ ),
+ ("image.change_frame", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("image.sample", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ (
+ "image.curves_point_set",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("point", 'BLACK_POINT'),
+ ],
+ }
+ ),
+ (
+ "image.curves_point_set",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("point", 'WHITE_POINT'),
+ ],
+ }
+ ),
+ (
+ "object.mode_set",
+ {"type": 'TAB', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'EDIT'),
+ ("toggle", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_int",
+ {"type": 'ONE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.image.render_slots.active_index'),
+ ("value", 0),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_int",
+ {"type": 'TWO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.image.render_slots.active_index'),
+ ("value", 1),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_int",
+ {"type": 'THREE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.image.render_slots.active_index'),
+ ("value", 2),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_int",
+ {"type": 'FOUR', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.image.render_slots.active_index'),
+ ("value", 3),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_int",
+ {"type": 'FIVE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.image.render_slots.active_index'),
+ ("value", 4),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_int",
+ {"type": 'SIX', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.image.render_slots.active_index'),
+ ("value", 5),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_int",
+ {"type": 'SEVEN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.image.render_slots.active_index'),
+ ("value", 6),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_int",
+ {"type": 'EIGHT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.image.render_slots.active_index'),
+ ("value", 7),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'COMMA', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'CENTER'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'COMMA', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'MEDIAN'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'PERIOD', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'CURSOR'),
+ ],
+ }
+ ),
+ ("image.render_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
+ ("image.clear_render_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ],
+ },
+ ),
+ (
+ "Node Generic",
+ {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("node.properties", {"type": 'N', "value": 'PRESS'}, None),
+ ("node.toolbar", {"type": 'T', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Node Editor",
+ {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "node.select",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'ACTIONMOUSE', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select_border",
+ {"type": 'EVT_TWEAK_S', "value": 'ANY'},
+ {
+ "properties": [
+ ("tweak", True),
+ ],
+ }
+ ),
+ (
+ "node.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "node.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("node.select_circle", {"type": 'C', "value": 'PRESS'}, None),
+ (
+ "node.link",
+ {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("detach", False),
+ ],
+ }
+ ),
+ (
+ "node.link",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("detach", True),
+ ],
+ }
+ ),
+ ("node.resize", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("node.add_reroute", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("node.links_cut", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("node.select_link_viewer", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("node.backimage_move", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None),
+ (
+ "node.backimage_zoom",
+ {"type": 'V', "value": 'PRESS'},
+ {
+ "properties": [
+ ("factor", 0.8333333),
+ ],
+ }
+ ),
+ (
+ "node.backimage_zoom",
+ {"type": 'V', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("factor", 1.2),
+ ],
+ }
+ ),
+ ("node.backimage_fit", {"type": 'HOME', "value": 'PRESS', "alt": True}, None),
+ ("node.backimage_sample", {"type": 'ACTIONMOUSE', "value": 'PRESS', "alt": True}, None),
+ (
+ "node.link_make",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("replace", False),
+ ],
+ }
+ ),
+ (
+ "node.link_make",
+ {"type": 'F', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("replace", True),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'NODE_MT_add'),
+ ],
+ }
+ ),
+ ("node.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("node.duplicate_move_keep_inputs", {"type": 'D', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("node.parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
+ ("node.detach", {"type": 'P', "value": 'PRESS', "alt": True}, None),
+ ("node.join", {"type": 'J', "value": 'PRESS', "ctrl": True}, None),
+ ("node.hide_toggle", {"type": 'H', "value": 'PRESS'}, None),
+ ("node.mute_toggle", {"type": 'M', "value": 'PRESS'}, None),
+ ("node.preview_toggle", {"type": 'H', "value": 'PRESS', "shift": True}, None),
+ ("node.hide_socket_toggle", {"type": 'H', "value": 'PRESS', "ctrl": True}, None),
+ ("node.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("node.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("node.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ (
+ "node.select_border",
+ {"type": 'B', "value": 'PRESS'},
+ {
+ "properties": [
+ ("tweak", False),
+ ],
+ }
+ ),
+ ("node.delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("node.delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("node.delete_reconnect", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "node.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "node.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("node.select_linked_to", {"type": 'L', "value": 'PRESS', "shift": True}, None),
+ ("node.select_linked_from", {"type": 'L', "value": 'PRESS'}, None),
+ (
+ "node.select_grouped",
+ {"type": 'G', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "node.select_grouped",
+ {"type": 'G', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "node.select_same_type_step",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("prev", False),
+ ],
+ }
+ ),
+ (
+ "node.select_same_type_step",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("prev", True),
+ ],
+ }
+ ),
+ ("node.find_node", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
+ ("node.group_make", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
+ ("node.group_ungroup", {"type": 'G', "value": 'PRESS', "alt": True}, None),
+ ("node.group_separate", {"type": 'P', "value": 'PRESS'}, None),
+ (
+ "node.group_edit",
+ {"type": 'TAB', "value": 'PRESS'},
+ {
+ "properties": [
+ ("exit", False),
+ ],
+ }
+ ),
+ (
+ "node.group_edit",
+ {"type": 'TAB', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("exit", True),
+ ],
+ }
+ ),
+ ("node.read_viewlayers", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
+ ("node.render_changed", {"type": 'Z', "value": 'PRESS'}, None),
+ ("node.clipboard_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("node.clipboard_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ ("node.viewer_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
+ ("node.clear_viewer_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("node.translate_attach", {"type": 'G', "value": 'PRESS'}, None),
+ ("node.translate_attach", {"type": 'EVT_TWEAK_A', "value": 'ANY'}, None),
+ ("node.translate_attach", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ (
+ "transform.translate",
+ {"type": 'G', "value": 'PRESS'},
+ {
+ "properties": [
+ ("release_confirm", True),
+ ],
+ }
+ ),
+ (
+ "transform.translate",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY'},
+ {
+ "properties": [
+ ("release_confirm", True),
+ ],
+ }
+ ),
+ (
+ "transform.translate",
+ {"type": 'EVT_TWEAK_S', "value": 'ANY'},
+ {
+ "properties": [
+ ("release_confirm", True),
+ ],
+ }
+ ),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ ("node.move_detach_links", {"type": 'D', "value": 'PRESS', "alt": True}, None),
+ ("node.move_detach_links_release", {"type": 'EVT_TWEAK_A', "value": 'ANY', "alt": True}, None),
+ ("node.move_detach_links", {"type": 'EVT_TWEAK_S', "value": 'ANY', "alt": True}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'TAB', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_snap'),
+ ],
+ }
+ ),
+ (
+ "wm.context_menu_enum",
+ {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.snap_node_element'),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "File Browser",
+ {"space_type": 'FILE_BROWSER', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("file.parent", {"type": 'UP_ARROW', "value": 'PRESS', "alt": True}, None),
+ ("file.previous", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True}, None),
+ ("file.next", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True}, None),
+ ("file.refresh", {"type": 'R', "value": 'PRESS'}, None),
+ ("file.parent", {"type": 'P', "value": 'PRESS'}, None),
+ ("file.previous", {"type": 'BACK_SPACE', "value": 'PRESS'}, None),
+ ("file.next", {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.params.show_hidden'),
+ ],
+ }
+ ),
+ ("file.directory_new", {"type": 'I', "value": 'PRESS'}, None),
+ ("file.delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("file.delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("file.smoothscroll", {"type": 'TIMER1', "value": 'ANY', "any": True}, None),
+ ("file.bookmark_toggle", {"type": 'T', "value": 'PRESS'}, None),
+ ("file.bookmark_add", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "File Browser Main",
+ {"space_type": 'FILE_BROWSER', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "file.execute",
+ {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'},
+ {
+ "properties": [
+ ("need_active", True),
+ ],
+ }
+ ),
+ ("file.refresh", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ ("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK'}, None),
+ (
+ "file.select",
+ {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "file.select",
+ {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("fill", True),
+ ],
+ }
+ ),
+ (
+ "file.select",
+ {"type": 'RIGHTMOUSE', "value": 'CLICK'},
+ {
+ "properties": [
+ ("open", False),
+ ],
+ }
+ ),
+ (
+ "file.select",
+ {"type": 'RIGHTMOUSE', "value": 'CLICK', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("open", False),
+ ],
+ }
+ ),
+ (
+ "file.select",
+ {"type": 'RIGHTMOUSE', "value": 'CLICK', "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("fill", True),
+ ("open", False),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'UP_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'UP'),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'UP_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'UP'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'UP_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("direction", 'UP'),
+ ("extend", True),
+ ("fill", True),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'DOWN_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'DOWN'),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'DOWN'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("direction", 'DOWN'),
+ ("extend", True),
+ ("fill", True),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'LEFT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'LEFT'),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'LEFT'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("direction", 'LEFT'),
+ ("extend", True),
+ ("fill", True),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("direction", 'RIGHT'),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("direction", 'RIGHT'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "file.select_walk",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("direction", 'RIGHT'),
+ ("extend", True),
+ ("fill", True),
+ ],
+ }
+ ),
+ ("file.previous", {"type": 'BUTTON4MOUSE', "value": 'CLICK'}, None),
+ ("file.next", {"type": 'BUTTON5MOUSE', "value": 'CLICK'}, None),
+ ("file.select_all_toggle", {"type": 'A', "value": 'PRESS'}, None),
+ ("file.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ ("file.select_border", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
+ ("file.rename", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("file.highlight", {"type": 'MOUSEMOVE', "value": 'ANY', "any": True}, None),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("increment", 1),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("increment", 10),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("increment", 100),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("increment", -1),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("increment", -10),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("increment", -100),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "File Browser Buttons",
+ {"space_type": 'FILE_BROWSER', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("increment", 1),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("increment", 10),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("increment", 100),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS'},
+ {
+ "properties": [
+ ("increment", -1),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("increment", -10),
+ ],
+ }
+ ),
+ (
+ "file.filenum",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("increment", -100),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "Dopesheet Generic",
+ {"space_type": 'DOPESHEET_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("action.properties", {"type": 'N', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Dopesheet",
+ {"space_type": 'DOPESHEET_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "action.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ("column", False),
+ ("channel", False),
+ ],
+ }
+ ),
+ (
+ "action.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("column", True),
+ ("channel", False),
+ ],
+ }
+ ),
+ (
+ "action.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("column", False),
+ ("channel", False),
+ ],
+ }
+ ),
+ (
+ "action.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("column", True),
+ ("channel", False),
+ ],
+ }
+ ),
+ (
+ "action.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("column", False),
+ ("channel", True),
+ ],
+ }
+ ),
+ (
+ "action.clickselect",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("column", False),
+ ("channel", True),
+ ],
+ }
+ ),
+ (
+ "action.select_leftright",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'CHECK'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "action.select_leftright",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'CHECK'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "action.select_leftright",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'LEFT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "action.select_leftright",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'RIGHT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "action.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "action.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ (
+ "action.select_border",
+ {"type": 'B', "value": 'PRESS'},
+ {
+ "properties": [
+ ("axis_range", False),
+ ],
+ }
+ ),
+ (
+ "action.select_border",
+ {"type": 'B', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("axis_range", True),
+ ],
+ }
+ ),
+ (
+ "action.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "action.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("action.select_circle", {"type": 'C', "value": 'PRESS'}, None),
+ (
+ "action.select_column",
+ {"type": 'K', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'KEYS'),
+ ],
+ }
+ ),
+ (
+ "action.select_column",
+ {"type": 'K', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'CFRA'),
+ ],
+ }
+ ),
+ (
+ "action.select_column",
+ {"type": 'K', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'MARKERS_COLUMN'),
+ ],
+ }
+ ),
+ (
+ "action.select_column",
+ {"type": 'K', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("mode", 'MARKERS_BETWEEN'),
+ ],
+ }
+ ),
+ ("action.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("action.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ ("action.select_linked", {"type": 'L', "value": 'PRESS'}, None),
+ ("action.frame_jump", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
+ ("action.snap", {"type": 'S', "value": 'PRESS', "shift": True}, None),
+ ("action.mirror", {"type": 'M', "value": 'PRESS', "shift": True}, None),
+ ("action.handle_type", {"type": 'V', "value": 'PRESS'}, None),
+ ("action.interpolation_type", {"type": 'T', "value": 'PRESS'}, None),
+ ("action.extrapolation_type", {"type": 'E', "value": 'PRESS', "shift": True}, None),
+ ("action.keyframe_type", {"type": 'R', "value": 'PRESS'}, None),
+ ("action.sample", {"type": 'O', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'X', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'DOPESHEET_MT_delete'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'DOPESHEET_MT_delete'),
+ ],
+ }
+ ),
+ ("action.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("action.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
+ ("action.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("action.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "action.paste",
+ {"type": 'V', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("flipped", True),
+ ],
+ }
+ ),
+ ("action.previewrange_set", {"type": 'P', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("action.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("action.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("action.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ ("action.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
+ ("anim.channels_editable_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
+ ("anim.channels_find", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "transform.transform",
+ {"type": 'G', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TIME_TRANSLATE'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'EVT_TWEAK_S', "value": 'ANY'},
+ {
+ "properties": [
+ ("mode", 'TIME_TRANSLATE'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TIME_EXTEND'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'S', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TIME_SCALE'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'T', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("mode", 'TIME_SLIDE'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'tool_settings.use_proportional_action'),
+ ],
+ }
+ ),
+ ("marker.add", {"type": 'M', "value": 'PRESS'}, None),
+ ("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "NLA Generic",
+ {"space_type": 'NLA_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("nla.properties", {"type": 'N', "value": 'PRESS'}, None),
+ ("nla.tweakmode_enter", {"type": 'TAB', "value": 'PRESS'}, None),
+ ("nla.tweakmode_exit", {"type": 'TAB', "value": 'PRESS'}, None),
+ (
+ "nla.tweakmode_enter",
+ {"type": 'TAB', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("isolate_action", True),
+ ],
+ }
+ ),
+ (
+ "nla.tweakmode_exit",
+ {"type": 'TAB', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("isolate_action", True),
+ ],
+ }
+ ),
+ ("anim.channels_find", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "NLA Channels",
+ {"space_type": 'NLA_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "nla.channels_click",
+ {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "nla.channels_click",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "nla.tracks_add",
+ {"type": 'A', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("above_selected", False),
+ ],
+ }
+ ),
+ (
+ "nla.tracks_add",
+ {"type": 'A', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("above_selected", True),
+ ],
+ }
+ ),
+ ("nla.tracks_delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("nla.tracks_delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "NLA Editor",
+ {"space_type": 'NLA_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "nla.click_select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "nla.click_select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "nla.select_leftright",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'CHECK'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "nla.select_leftright",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("mode", 'CHECK'),
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "nla.select_leftright",
+ {"type": 'LEFT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'LEFT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "nla.select_leftright",
+ {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'RIGHT'),
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "nla.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "nla.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ (
+ "nla.select_border",
+ {"type": 'B', "value": 'PRESS'},
+ {
+ "properties": [
+ ("axis_range", False),
+ ],
+ }
+ ),
+ (
+ "nla.select_border",
+ {"type": 'B', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("axis_range", True),
+ ],
+ }
+ ),
+ ("nla.previewrange_set", {"type": 'P', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ ("nla.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("nla.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("nla.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ ("nla.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
+ ("nla.actionclip_add", {"type": 'A', "value": 'PRESS', "shift": True}, None),
+ ("nla.transition_add", {"type": 'T', "value": 'PRESS', "shift": True}, None),
+ ("nla.soundclip_add", {"type": 'K', "value": 'PRESS', "shift": True}, None),
+ ("nla.meta_add", {"type": 'G', "value": 'PRESS', "shift": True}, None),
+ ("nla.meta_remove", {"type": 'G', "value": 'PRESS', "alt": True}, None),
+ (
+ "nla.duplicate",
+ {"type": 'D', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("linked", False),
+ ],
+ }
+ ),
+ (
+ "nla.duplicate",
+ {"type": 'D', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("linked", True),
+ ],
+ }
+ ),
+ ("nla.make_single_user", {"type": 'U', "value": 'PRESS'}, None),
+ ("nla.delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("nla.delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("nla.split", {"type": 'Y', "value": 'PRESS'}, None),
+ ("nla.mute_toggle", {"type": 'H', "value": 'PRESS'}, None),
+ ("nla.swap", {"type": 'F', "value": 'PRESS', "alt": True}, None),
+ ("nla.move_up", {"type": 'PAGE_UP', "value": 'PRESS'}, None),
+ ("nla.move_down", {"type": 'PAGE_DOWN', "value": 'PRESS'}, None),
+ ("nla.apply_scale", {"type": 'A', "value": 'PRESS', "ctrl": True}, None),
+ ("nla.clear_scale", {"type": 'S', "value": 'PRESS', "alt": True}, None),
+ ("nla.snap", {"type": 'S', "value": 'PRESS', "shift": True}, None),
+ ("nla.fmodifier_add", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "transform.transform",
+ {"type": 'G', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TRANSLATION'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'EVT_TWEAK_S', "value": 'ANY'},
+ {
+ "properties": [
+ ("mode", 'TRANSLATION'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TIME_EXTEND'),
+ ],
+ }
+ ),
+ (
+ "transform.transform",
+ {"type": 'S', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TIME_SCALE'),
+ ],
+ }
+ ),
+ ("marker.add", {"type": 'M', "value": 'PRESS'}, None),
+ ("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "Text Generic",
+ {"space_type": 'TEXT_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("text.start_find", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
+ ("text.jump", {"type": 'J', "value": 'PRESS', "ctrl": True}, None),
+ ("text.find", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
+ ("text.replace", {"type": 'H', "value": 'PRESS', "ctrl": True}, None),
+ ("text.properties", {"type": 'T', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "Text",
+ {"space_type": 'TEXT_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "wm.context_cycle_int",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.font_size'),
+ ("reverse", False),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_int",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.font_size'),
+ ("reverse", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_int",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.font_size'),
+ ("reverse", False),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_int",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.font_size'),
+ ("reverse", True),
+ ],
+ }
+ ),
+ ("text.new", {"type": 'N', "value": 'PRESS', "ctrl": True}, None),
+ ("text.open", {"type": 'O', "value": 'PRESS', "alt": True}, None),
+ ("text.reload", {"type": 'R', "value": 'PRESS', "alt": True}, None),
+ ("text.save", {"type": 'S', "value": 'PRESS', "alt": True}, None),
+ ("text.save_as", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
+ ("text.run_script", {"type": 'P', "value": 'PRESS', "alt": True}, None),
+ ("text.cut", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
+ ("text.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("text.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ ("text.cut", {"type": 'DEL', "value": 'PRESS', "shift": True}, None),
+ ("text.copy", {"type": 'INSERT', "value": 'PRESS', "ctrl": True}, None),
+ ("text.paste", {"type": 'INSERT', "value": 'PRESS', "shift": True}, None),
+ ("text.duplicate_line", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
+ ("text.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, None),
+ ("text.select_line", {"type": 'A', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("text.select_word", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
+ (
+ "text.move_lines",
+ {"type": 'UP_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("direction", 'UP'),
+ ],
+ }
+ ),
+ (
+ "text.move_lines",
+ {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("direction", 'DOWN'),
+ ],
+ }
+ ),
+ ("text.indent", {"type": 'TAB', "value": 'PRESS'}, None),
+ ("text.unindent", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
+ ("text.uncomment", {"type": 'D', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ (
+ "text.move",
+ {"type": 'HOME', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'LINE_BEGIN'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'END', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'LINE_END'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'E', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'LINE_END'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'E', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'LINE_END'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'LEFT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_WORD'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'NEXT_WORD'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'UP_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_LINE'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'DOWN_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_LINE'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'PAGE_UP', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_PAGE'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'PAGE_DOWN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_PAGE'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'HOME', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'FILE_TOP'),
+ ],
+ }
+ ),
+ (
+ "text.move",
+ {"type": 'END', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'FILE_BOTTOM'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'HOME', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'LINE_BEGIN'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'END', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'LINE_END'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'NEXT_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_WORD'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'NEXT_WORD'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'UP_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_LINE'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'NEXT_LINE'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'PAGE_UP', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_PAGE'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'NEXT_PAGE'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'HOME', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'FILE_TOP'),
+ ],
+ }
+ ),
+ (
+ "text.move_select",
+ {"type": 'END', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("type", 'FILE_BOTTOM'),
+ ],
+ }
+ ),
+ (
+ "text.delete",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "text.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "text.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "text.delete",
+ {"type": 'DEL', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'NEXT_WORD'),
+ ],
+ }
+ ),
+ (
+ "text.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_WORD'),
+ ],
+ }
+ ),
+ ("text.overwrite_toggle", {"type": 'INSERT', "value": 'PRESS'}, None),
+ ("text.scroll_bar", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("text.scroll_bar", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("text.scroll", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("text.scroll", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
+ ("text.selection_set", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
+ ("text.cursor_set", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ (
+ "text.selection_set",
+ {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("select", True),
+ ],
+ }
+ ),
+ (
+ "text.scroll",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("lines", -1),
+ ],
+ }
+ ),
+ (
+ "text.scroll",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("lines", 1),
+ ],
+ }
+ ),
+ ("text.line_break", {"type": 'RET', "value": 'PRESS'}, None),
+ ("text.line_break", {"type": 'NUMPAD_ENTER', "value": 'PRESS'}, None),
+ (
+ "wm.call_menu",
+ {"type": 'RIGHTMOUSE', "value": 'PRESS', "any": True},
+ {
+ "properties": [
+ ("name", 'TEXT_MT_toolbox'),
+ ],
+ }
+ ),
+ ("text.autocomplete", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, None),
+ ("text.line_number", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
+ ("text.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "SequencerCommon",
+ {"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("sequencer.properties", {"type": 'N', "value": 'PRESS'}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'O', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("data_path", 'scene.sequence_editor.show_overlay'),
+ ],
+ }
+ ),
+ ("sequencer.view_toggle", {"type": 'TAB', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "Sequencer",
+ {"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "sequencer.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "sequencer.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut",
+ {"type": 'K', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'SOFT'),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut",
+ {"type": 'K', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'HARD'),
+ ],
+ }
+ ),
+ (
+ "sequencer.mute",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.mute",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ (
+ "sequencer.unmute",
+ {"type": 'H', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.unmute",
+ {"type": 'H', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("sequencer.lock", {"type": 'L', "value": 'PRESS', "shift": True}, None),
+ ("sequencer.unlock", {"type": 'L', "value": 'PRESS', "shift": True, "alt": True}, None),
+ ("sequencer.reassign_inputs", {"type": 'R', "value": 'PRESS'}, None),
+ ("sequencer.reload", {"type": 'R', "value": 'PRESS', "alt": True}, None),
+ (
+ "sequencer.reload",
+ {"type": 'R', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("adjust_length", True),
+ ],
+ }
+ ),
+ ("sequencer.offset_clear", {"type": 'O', "value": 'PRESS', "alt": True}, None),
+ ("sequencer.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("sequencer.delete", {"type": 'X', "value": 'PRESS'}, None),
+ ("sequencer.delete", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("sequencer.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("sequencer.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ ("sequencer.images_separate", {"type": 'Y', "value": 'PRESS'}, None),
+ ("sequencer.meta_toggle", {"type": 'TAB', "value": 'PRESS'}, None),
+ ("sequencer.meta_make", {"type": 'G', "value": 'PRESS', "ctrl": True}, None),
+ ("sequencer.meta_separate", {"type": 'G', "value": 'PRESS', "alt": True}, None),
+ ("sequencer.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("sequencer.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("sequencer.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ ("sequencer.view_frame", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
+ (
+ "sequencer.strip_jump",
+ {"type": 'PAGE_UP', "value": 'PRESS'},
+ {
+ "properties": [
+ ("next", True),
+ ("center", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.strip_jump",
+ {"type": 'PAGE_DOWN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("next", False),
+ ("center", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.strip_jump",
+ {"type": 'PAGE_UP', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("next", True),
+ ("center", True),
+ ],
+ }
+ ),
+ (
+ "sequencer.strip_jump",
+ {"type": 'PAGE_DOWN', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("next", False),
+ ("center", True),
+ ],
+ }
+ ),
+ (
+ "sequencer.swap",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("side", 'LEFT'),
+ ],
+ }
+ ),
+ (
+ "sequencer.swap",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("side", 'RIGHT'),
+ ],
+ }
+ ),
+ (
+ "sequencer.gap_remove",
+ {"type": 'BACK_SPACE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("all", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.gap_remove",
+ {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("all", True),
+ ],
+ }
+ ),
+ ("sequencer.gap_insert", {"type": 'EQUAL', "value": 'PRESS', "shift": True}, None),
+ ("sequencer.snap", {"type": 'S', "value": 'PRESS', "shift": True}, None),
+ ("sequencer.swap_inputs", {"type": 'S', "value": 'PRESS', "alt": True}, None),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'ONE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 1),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'TWO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 2),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'THREE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 3),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'FOUR', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 4),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'FIVE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 5),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'SIX', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 6),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'SEVEN', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 7),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'EIGHT', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 8),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'NINE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 9),
+ ],
+ }
+ ),
+ (
+ "sequencer.cut_multicam",
+ {"type": 'ZERO', "value": 'PRESS'},
+ {
+ "properties": [
+ ("camera", 10),
+ ],
+ }
+ ),
+ (
+ "sequencer.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ("linked_handle", False),
+ ("left_right", 'NONE'),
+ ("linked_time", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("linked_handle", False),
+ ("left_right", 'NONE'),
+ ("linked_time", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("linked_handle", True),
+ ("left_right", 'NONE'),
+ ("linked_time", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("linked_handle", True),
+ ("left_right", 'NONE'),
+ ("linked_time", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("extend", False),
+ ("linked_handle", False),
+ ("left_right", 'MOUSE'),
+ ("linked_time", True),
+ ],
+ }
+ ),
+ (
+ "sequencer.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("extend", True),
+ ("linked_handle", False),
+ ("left_right", 'NONE'),
+ ("linked_time", True),
+ ],
+ }
+ ),
+ ("sequencer.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True}, None),
+ ("sequencer.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "sequencer.select_linked_pick",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "sequencer.select_linked_pick",
+ {"type": 'L', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ ("sequencer.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
+ ("sequencer.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ ("sequencer.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'A', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'SEQUENCER_MT_add'),
+ ],
+ }
+ ),
+ (
+ "wm.call_menu",
+ {"type": 'C', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'SEQUENCER_MT_change'),
+ ],
+ }
+ ),
+ ("sequencer.slip", {"type": 'S', "value": 'PRESS'}, None),
+ (
+ "wm.context_set_int",
+ {"type": 'O', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'scene.sequence_editor.overlay_frame'),
+ ("value", 0),
+ ],
+ }
+ ),
+ ("transform.seq_slide", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.seq_slide", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ (
+ "transform.transform",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("mode", 'TIME_EXTEND'),
+ ],
+ }
+ ),
+ ("marker.add", {"type": 'M', "value": 'PRESS'}, None),
+ ("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "SequencerPreview",
+ {"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("sequencer.view_all_preview", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("sequencer.view_all_preview", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("sequencer.view_ghost_border", {"type": 'O', "value": 'PRESS'}, None),
+ (
+ "sequencer.view_zoom_ratio",
+ {"type": 'NUMPAD_1', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 1.0),
+ ],
+ }
+ ),
+ ("sequencer.sample", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Console",
+ {"space_type": 'CONSOLE', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "console.move",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_WORD'),
+ ],
+ }
+ ),
+ (
+ "console.move",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'NEXT_WORD'),
+ ],
+ }
+ ),
+ (
+ "console.move",
+ {"type": 'HOME', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'LINE_BEGIN'),
+ ],
+ }
+ ),
+ (
+ "console.move",
+ {"type": 'END', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'LINE_END'),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_int",
+ {"type": 'WHEELUPMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.font_size'),
+ ("reverse", False),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_int",
+ {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.font_size'),
+ ("reverse", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_int",
+ {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.font_size'),
+ ("reverse", False),
+ ],
+ }
+ ),
+ (
+ "wm.context_cycle_int",
+ {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.font_size'),
+ ("reverse", True),
+ ],
+ }
+ ),
+ (
+ "console.move",
+ {"type": 'LEFT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "console.move",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "console.history_cycle",
+ {"type": 'UP_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("reverse", True),
+ ],
+ }
+ ),
+ (
+ "console.history_cycle",
+ {"type": 'DOWN_ARROW', "value": 'PRESS'},
+ {
+ "properties": [
+ ("reverse", False),
+ ],
+ }
+ ),
+ (
+ "console.delete",
+ {"type": 'DEL', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'NEXT_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "console.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "console.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_CHARACTER'),
+ ],
+ }
+ ),
+ (
+ "console.delete",
+ {"type": 'DEL', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'NEXT_WORD'),
+ ],
+ }
+ ),
+ (
+ "console.delete",
+ {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("type", 'PREVIOUS_WORD'),
+ ],
+ }
+ ),
+ ("console.clear_line", {"type": 'RET', "value": 'PRESS', "shift": True}, None),
+ ("console.clear_line", {"type": 'NUMPAD_ENTER', "value": 'PRESS', "shift": True}, None),
+ (
+ "console.execute",
+ {"type": 'RET', "value": 'PRESS'},
+ {
+ "properties": [
+ ("interactive", True),
+ ],
+ }
+ ),
+ (
+ "console.execute",
+ {"type": 'NUMPAD_ENTER', "value": 'PRESS'},
+ {
+ "properties": [
+ ("interactive", True),
+ ],
+ }
+ ),
+ ("console.autocomplete", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, None),
+ ("console.copy_as_script", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True}, None),
+ ("console.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("console.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ ("console.select_set", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ ("console.select_word", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
+ (
+ "console.insert",
+ {"type": 'TAB', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("text", '\t'),
+ ],
+ }
+ ),
+ ("console.indent", {"type": 'TAB', "value": 'PRESS'}, None),
+ ("console.unindent", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
+ ("console.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Clip",
+ {"space_type": 'CLIP_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("clip.open", {"type": 'O', "value": 'PRESS', "alt": True}, None),
+ ("clip.tools", {"type": 'T', "value": 'PRESS'}, None),
+ ("clip.properties", {"type": 'N', "value": 'PRESS'}, None),
+ (
+ "clip.track_markers",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("backwards", True),
+ ("sequence", False),
+ ],
+ }
+ ),
+ (
+ "clip.track_markers",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("backwards", False),
+ ("sequence", False),
+ ],
+ }
+ ),
+ (
+ "clip.track_markers",
+ {"type": 'T', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("backwards", False),
+ ("sequence", True),
+ ],
+ }
+ ),
+ (
+ "clip.track_markers",
+ {"type": 'T', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("backwards", True),
+ ("sequence", True),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle_enum",
+ {"type": 'TAB', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.mode'),
+ ("value_1", 'TRACKING'),
+ ("value_2", 'MASK'),
+ ],
+ }
+ ),
+ ("clip.solve_camera", {"type": 'S', "value": 'PRESS', "shift": True}, None),
+ (
+ "clip.set_solver_keyframe",
+ {"type": 'Q', "value": 'PRESS'},
+ {
+ "properties": [
+ ("keyframe", 'KEYFRAME_A'),
+ ],
+ }
+ ),
+ (
+ "clip.set_solver_keyframe",
+ {"type": 'E', "value": 'PRESS'},
+ {
+ "properties": [
+ ("keyframe", 'KEYFRAME_B'),
+ ],
+ }
+ ),
+ ("clip.prefetch", {"type": 'P', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Clip Editor",
+ {"space_type": 'CLIP_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("clip.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
+ ("clip.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
+ ("clip.view_pan", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
+ ("clip.view_zoom", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("clip.view_zoom", {"type": 'TRACKPADZOOM', "value": 'ANY'}, None),
+ ("clip.view_zoom", {"type": 'TRACKPADPAN', "value": 'ANY', "ctrl": True}, None),
+ ("clip.view_zoom_in", {"type": 'WHEELINMOUSE', "value": 'PRESS'}, None),
+ ("clip.view_zoom_out", {"type": 'WHEELOUTMOUSE', "value": 'PRESS'}, None),
+ ("clip.view_zoom_in", {"type": 'NUMPAD_PLUS', "value": 'PRESS'}, None),
+ ("clip.view_zoom_out", {"type": 'NUMPAD_MINUS', "value": 'PRESS'}, None),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_8', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("ratio", 8.0),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_4', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("ratio", 4.0),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_2', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("ratio", 2.0),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_8', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("ratio", 8.0),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_4', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("ratio", 4.0),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_2', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("ratio", 2.0),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_1', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 1.0),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_2', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 0.5),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_4', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 0.25),
+ ],
+ }
+ ),
+ (
+ "clip.view_zoom_ratio",
+ {"type": 'NUMPAD_8', "value": 'PRESS'},
+ {
+ "properties": [
+ ("ratio", 0.125),
+ ],
+ }
+ ),
+ ("clip.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ (
+ "clip.view_all",
+ {"type": 'F', "value": 'PRESS'},
+ {
+ "properties": [
+ ("fit_view", True),
+ ],
+ }
+ ),
+ ("clip.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ ("clip.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("clip.view_ndof", {"type": 'NDOF_MOTION', "value": 'ANY'}, None),
+ (
+ "clip.frame_jump",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("position", 'PATHSTART'),
+ ],
+ }
+ ),
+ (
+ "clip.frame_jump",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
+ {
+ "properties": [
+ ("position", 'PATHEND'),
+ ],
+ }
+ ),
+ (
+ "clip.frame_jump",
+ {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("position", 'FAILEDPREV'),
+ ],
+ }
+ ),
+ (
+ "clip.frame_jump",
+ {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("position", 'PATHSTART'),
+ ],
+ }
+ ),
+ ("clip.change_frame", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ (
+ "clip.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "clip.select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "clip.select_all",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "clip.select_all",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("clip.select_border", {"type": 'B', "value": 'PRESS'}, None),
+ ("clip.select_circle", {"type": 'C', "value": 'PRESS'}, None),
+ (
+ "wm.call_menu",
+ {"type": 'G', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("name", 'CLIP_MT_select_grouped'),
+ ],
+ }
+ ),
+ (
+ "clip.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("deselect", False),
+ ],
+ }
+ ),
+ (
+ "clip.select_lasso",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY', "shift": True, "ctrl": True, "alt": True},
+ {
+ "properties": [
+ ("deselect", True),
+ ],
+ }
+ ),
+ ("clip.add_marker_slide", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, None),
+ ("clip.delete_marker", {"type": 'DEL', "value": 'PRESS', "shift": True}, None),
+ ("clip.delete_marker", {"type": 'X', "value": 'PRESS', "shift": True}, None),
+ ("clip.slide_marker", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+ (
+ "clip.disable_markers",
+ {"type": 'D', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ ("clip.delete_track", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("clip.delete_track", {"type": 'X', "value": 'PRESS'}, None),
+ (
+ "clip.lock_tracks",
+ {"type": 'L', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'LOCK'),
+ ],
+ }
+ ),
+ (
+ "clip.lock_tracks",
+ {"type": 'L', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("action", 'UNLOCK'),
+ ],
+ }
+ ),
+ (
+ "clip.hide_tracks",
+ {"type": 'H', "value": 'PRESS'},
+ {
+ "properties": [
+ ("unselected", False),
+ ],
+ }
+ ),
+ (
+ "clip.hide_tracks",
+ {"type": 'H', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("unselected", True),
+ ],
+ }
+ ),
+ ("clip.hide_tracks_clear", {"type": 'H', "value": 'PRESS', "alt": True}, None),
+ ("clip.slide_plane_marker", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ ("clip.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
+ ("clip.keyframe_delete", {"type": 'I', "value": 'PRESS', "alt": True}, None),
+ ("clip.join_tracks", {"type": 'J', "value": 'PRESS', "ctrl": True}, None),
+ (
+ "wm.call_menu",
+ {"type": 'W', "value": 'PRESS'},
+ {
+ "properties": [
+ ("name", 'CLIP_MT_tracking_specials'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.lock_selection'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'D', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.show_disabled'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'S', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.show_marker_search'),
+ ],
+ }
+ ),
+ (
+ "wm.context_toggle",
+ {"type": 'M', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.use_mute_footage'),
+ ],
+ }
+ ),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ (
+ "clip.clear_track_path",
+ {"type": 'T', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("action", 'REMAINED'),
+ ("clear_active", False),
+ ],
+ }
+ ),
+ (
+ "clip.clear_track_path",
+ {"type": 'T', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("action", 'UPTO'),
+ ("clear_active", False),
+ ],
+ }
+ ),
+ (
+ "clip.clear_track_path",
+ {"type": 'T', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("action", 'ALL'),
+ ("clear_active", False),
+ ],
+ }
+ ),
+ ("clip.cursor_set", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ (
+ "wm.context_set_enum",
+ {"type": 'COMMA', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'BOUNDING_BOX_CENTER'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'COMMA', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'MEDIAN_POINT'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'PERIOD', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'CURSOR'),
+ ],
+ }
+ ),
+ (
+ "wm.context_set_enum",
+ {"type": 'PERIOD', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("data_path", 'space_data.pivot_point'),
+ ("value", 'INDIVIDUAL_ORIGINS'),
+ ],
+ }
+ ),
+ ("clip.copy_tracks", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
+ ("clip.paste_tracks", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
+ ],
+ },
+ ),
+ (
+ "Clip Graph Editor",
+ {"space_type": 'CLIP_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("clip.change_frame", {"type": 'ACTIONMOUSE', "value": 'PRESS'}, None),
+ (
+ "clip.graph_select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", False),
+ ],
+ }
+ ),
+ (
+ "clip.graph_select",
+ {"type": 'SELECTMOUSE', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ (
+ "clip.graph_select_all_markers",
+ {"type": 'A', "value": 'PRESS'},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ (
+ "clip.graph_select_all_markers",
+ {"type": 'I', "value": 'PRESS', "ctrl": True},
+ {
+ "properties": [
+ ("action", 'INVERT'),
+ ],
+ }
+ ),
+ ("clip.graph_select_border", {"type": 'B', "value": 'PRESS'}, None),
+ ("clip.graph_delete_curve", {"type": 'DEL', "value": 'PRESS'}, None),
+ ("clip.graph_delete_curve", {"type": 'X', "value": 'PRESS'}, None),
+ ("clip.graph_delete_knot", {"type": 'DEL', "value": 'PRESS', "shift": True}, None),
+ ("clip.graph_delete_knot", {"type": 'X', "value": 'PRESS', "shift": True}, None),
+ ("clip.graph_view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("clip.graph_view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ("clip.graph_center_current_frame", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
+ (
+ "wm.context_toggle",
+ {"type": 'L', "value": 'PRESS'},
+ {
+ "properties": [
+ ("data_path", 'space_data.lock_time_cursor'),
+ ],
+ }
+ ),
+ (
+ "clip.clear_track_path",
+ {"type": 'T', "value": 'PRESS', "alt": True},
+ {
+ "properties": [
+ ("action", 'REMAINED'),
+ ("clear_active", True),
+ ],
+ }
+ ),
+ (
+ "clip.clear_track_path",
+ {"type": 'T', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("action", 'UPTO'),
+ ("clear_active", True),
+ ],
+ }
+ ),
+ (
+ "clip.clear_track_path",
+ {"type": 'T', "value": 'PRESS', "shift": True, "alt": True},
+ {
+ "properties": [
+ ("action", 'ALL'),
+ ("clear_active", True),
+ ],
+ }
+ ),
+ (
+ "clip.graph_disable_markers",
+ {"type": 'D', "value": 'PRESS', "shift": True},
+ {
+ "properties": [
+ ("action", 'TOGGLE'),
+ ],
+ }
+ ),
+ ("transform.translate", {"type": 'G', "value": 'PRESS'}, None),
+ ("transform.translate", {"type": 'EVT_TWEAK_S', "value": 'ANY'}, None),
+ ("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
+ ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "Clip Dopesheet Editor",
+ {"space_type": 'CLIP_EDITOR', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "clip.dopesheet_select_channel",
+ {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {
+ "properties": [
+ ("extend", True),
+ ],
+ }
+ ),
+ ("clip.dopesheet_view_all", {"type": 'HOME', "value": 'PRESS'}, None),
+ ("clip.dopesheet_view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
+ ],
+ },
+ ),
+ (
+ "3D View Tool: OBJECT, Move",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "transform.translate",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY'},
+ {
+ "properties": [
+ ("release_confirm", True),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "3D View Tool: OBJECT, Rotate",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "transform.rotate",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY'},
+ {
+ "properties": [
+ ("release_confirm", True),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "3D View Tool: OBJECT, Scale",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ (
+ "transform.resize",
+ {"type": 'EVT_TWEAK_A', "value": 'ANY'},
+ {
+ "properties": [
+ ("release_confirm", True),
+ ],
+ }
+ ),
+ ],
+ },
+ ),
+ (
+ "3D View Tool: OBJECT, Ruler/Protractor",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("view3d.ruler_add", {"type": 'EVT_TWEAK_A', "value": 'ANY'}, None),
+ ],
+ },
+ ),
+ (
+ "3D View Tool: PARTICLE, Cursor Click",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("view3d.cursor3d", {"type": 'ACTIONMOUSE', "value": 'CLICK'}, None),
+ ],
+ },
+ ),
+ (
+ "Spot Lamp Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Area Lamp Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+ (
+ "Target Lamp Widgets",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {
+ "items": [
+ ("manipulatorgroup.manipulator_tweak", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
+ ],
+ },
+ ),
+]
+
+
+if __name__ == "__main__":
+ import os
+ from bpy_extras.keyconfig_utils import keyconfig_import_from_data
+ keyconfig_import_from_data(os.path.splitext(os.path.basename(__file__))[0], keyconfig_data)
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index 855f8d928cd..da1446f6f43 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -8,7 +8,7 @@ kc = wm.keyconfigs.new(os.path.splitext(os.path.basename(__file__))[0])
# Map Window
km = kc.keymaps.new('Window', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.keymap_items.new('wm.window_duplicate', 'W', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.window_new', 'W', 'PRESS', ctrl=True, alt=True)
kmi = km.keymap_items.new('wm.read_homefile', 'N', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.save_homefile', 'U', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.call_menu', 'O', 'PRESS', shift=True, ctrl=True)
@@ -33,9 +33,6 @@ kmi = km.keymap_items.new('wm.call_menu', 'NDOF_BUTTON_MENU', 'PRESS')
kmi.properties.name = 'USERPREF_MT_ndof_settings'
kmi = km.keymap_items.new('wm.context_set_enum', 'F2', 'PRESS', shift=True)
kmi.properties.data_path = 'area.type'
-kmi.properties.value = 'LOGIC_EDITOR'
-kmi = km.keymap_items.new('wm.context_set_enum', 'F3', 'PRESS', shift=True)
-kmi.properties.data_path = 'area.type'
kmi.properties.value = 'NODE_EDITOR'
kmi = km.keymap_items.new('wm.context_set_enum', 'F4', 'PRESS', shift=True)
kmi.properties.data_path = 'area.type'
@@ -383,7 +380,6 @@ kmi = km.keymap_items.new('object.hide_view_clear', 'H', 'PRESS', shift=True, ct
kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', alt=True)
kmi.properties.unselected = True
-kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'BACK_SPACE', 'PRESS')
kmi = km.keymap_items.new('object.delete', 'DEL', 'PRESS')
kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
@@ -773,17 +769,6 @@ kmi.properties.value_2 = 'CONNECTED'
# Map Armature
km = kc.keymaps.new('Armature', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.keymap_items.new('sketch.delete', 'BACK_SPACE', 'PRESS')
-kmi = km.keymap_items.new('sketch.delete', 'DEL', 'PRESS')
-kmi = km.keymap_items.new('sketch.finish_stroke', 'RIGHTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('sketch.cancel_stroke', 'ESC', 'PRESS')
-kmi = km.keymap_items.new('sketch.gesture', 'LEFTMOUSE', 'PRESS', shift=True)
-kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS')
-kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS', ctrl=True)
-kmi.properties.snap = True
-kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY')
-kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY', ctrl=True)
-kmi.properties.snap = True
kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS', ctrl=True)
kmi.properties.unselected = False
kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS', alt=True)
@@ -1001,11 +986,11 @@ kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', shift=
kmi.properties.type = 'ORBITDOWN'
kmi = km.keymap_items.new('view3d.localview', 'I', 'PRESS', shift=True)
kmi = km.keymap_items.new('wm.context_toggle_enum', 'FOUR', 'PRESS')
-kmi.properties.data_path = 'space_data.viewport_shade'
+kmi.properties.data_path = 'space_data.shading.type'
kmi.properties.value_1 = 'WIREFRAME'
kmi.properties.value_2 = 'WIREFRAME'
kmi = km.keymap_items.new('wm.context_toggle_enum', 'FIVE', 'PRESS')
-kmi.properties.data_path = 'space_data.viewport_shade'
+kmi.properties.data_path = 'space_data.shading.type'
kmi.properties.value_1 = 'TEXTURED'
kmi.properties.value_2 = 'SOLID'
kmi = km.keymap_items.new('view3d.select_or_deselect_all', 'SELECTMOUSE', 'CLICK')
@@ -1094,7 +1079,7 @@ kmi.properties.rotate = True
kmi = km.keymap_items.new('view3d.enable_manipulator', 'R', 'PRESS')
kmi.properties.scale = True
kmi = km.keymap_items.new('wm.context_toggle_enum', 'SIX', 'PRESS')
-kmi.properties.data_path = 'space_data.viewport_shade'
+kmi.properties.data_path = 'space_data.shading.type'
kmi.properties.value_1 = 'TEXTURED'
kmi.properties.value_2 = 'TEXTURED'
kmi = km.keymap_items.new('wm.context_set_enum', 'X', 'PRESS')
@@ -1499,7 +1484,7 @@ kmi.properties.prev = False
kmi = km.keymap_items.new('node.group_make', 'G', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('node.group_ungroup', 'G', 'PRESS', alt=True)
kmi = km.keymap_items.new('node.group_edit', 'TAB', 'PRESS')
-kmi = km.keymap_items.new('node.read_renderlayers', 'R', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('node.read_viewlayers', 'R', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('node.read_fullsamplelayers', 'R', 'PRESS', shift=True)
kmi = km.keymap_items.new('node.render_changed', 'Z', 'PRESS')
kmi = km.keymap_items.new('node.translate_attach', 'W', 'PRESS')
diff --git a/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py
index deb23d76d91..7825a4d0f32 100644
--- a/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py
+++ b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_rigged.py
@@ -10,7 +10,7 @@ op.include_armatures = True
op.include_shapekeys = False
op.deform_bones_only = True
op.active_uv_only = True
-op.export_texture_type_selection = 'uv'
+op.include_uv_textures = True
op.use_texture_copies = True
op.triangulate = True
op.use_object_instantiation = False
diff --git a/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py
index ca9de8bf005..a13ba5c4ccc 100644
--- a/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py
+++ b/release/scripts/presets/operator/wm.collada_export/sl_plus_open_sim_static.py
@@ -10,7 +10,6 @@ op.include_armatures = False
op.include_shapekeys = False
op.deform_bones_only = False
op.active_uv_only = True
-op.export_texture_type_selection = 'uv'
op.use_texture_copies = True
op.triangulate = True
op.use_object_instantiation = False
diff --git a/release/scripts/presets/sunsky/classic.py b/release/scripts/presets/sunsky/classic.py
deleted file mode 100644
index edb065d553c..00000000000
--- a/release/scripts/presets/sunsky/classic.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import bpy
-bpy.context.lamp.sky.atmosphere_turbidity = 4.0
-bpy.context.lamp.sky.sky_blend_type = 'ADD'
-bpy.context.lamp.sky.sky_blend = 1.0
-bpy.context.lamp.sky.horizon_brightness = 10.0
-bpy.context.lamp.sky.spread = 1.49011614159e-09
-bpy.context.lamp.sky.sky_color_space = 'SMPTE'
-bpy.context.lamp.sky.sky_exposure = 1.0
-bpy.context.lamp.sky.sun_brightness = 1.00000011921
-bpy.context.lamp.sky.sun_size = 1.00000166893
-bpy.context.lamp.sky.backscattered_light = 0.0
-bpy.context.lamp.sky.sun_intensity = 4.0
-bpy.context.lamp.sky.atmosphere_inscattering = 1.0
-bpy.context.lamp.sky.atmosphere_extinction = 1.0
diff --git a/release/scripts/presets/sunsky/desert.py b/release/scripts/presets/sunsky/desert.py
deleted file mode 100644
index 8dd587a6eaf..00000000000
--- a/release/scripts/presets/sunsky/desert.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import bpy
-bpy.context.lamp.sky.atmosphere_turbidity = 6.0
-bpy.context.lamp.sky.sky_blend_type = 'ADD'
-bpy.context.lamp.sky.sky_blend = 1.0
-bpy.context.lamp.sky.horizon_brightness = 4.99999761581
-bpy.context.lamp.sky.spread = 1.49011614159e-09
-bpy.context.lamp.sky.sky_color_space = 'SMPTE'
-bpy.context.lamp.sky.sky_exposure = 1.0
-bpy.context.lamp.sky.sun_brightness = 1.00000011921
-bpy.context.lamp.sky.sun_size = 4.0
-bpy.context.lamp.sky.backscattered_light = 1.0
-bpy.context.lamp.sky.sun_intensity = 1.0
-bpy.context.lamp.sky.atmosphere_inscattering = 1.0
-bpy.context.lamp.sky.atmosphere_extinction = 1.0
diff --git a/release/scripts/presets/sunsky/mountain.py b/release/scripts/presets/sunsky/mountain.py
deleted file mode 100644
index f0540af8100..00000000000
--- a/release/scripts/presets/sunsky/mountain.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import bpy
-bpy.context.lamp.sky.atmosphere_turbidity = 2.00000023842
-bpy.context.lamp.sky.sky_blend_type = 'ADD'
-bpy.context.lamp.sky.sky_blend = 1.0
-bpy.context.lamp.sky.horizon_brightness = 0.100000016391
-bpy.context.lamp.sky.spread = 1.0
-bpy.context.lamp.sky.sky_color_space = 'SMPTE'
-bpy.context.lamp.sky.sky_exposure = 1.0
-bpy.context.lamp.sky.sun_brightness = 1.99999988079
-bpy.context.lamp.sky.sun_size = 4.0
-bpy.context.lamp.sky.backscattered_light = -1.0
-bpy.context.lamp.sky.sun_intensity = 10.0
-bpy.context.lamp.sky.atmosphere_inscattering = 1.0
-bpy.context.lamp.sky.atmosphere_extinction = 1.0
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 4af600473d1..4460af173ff 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -79,7 +79,7 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
def add_uvs(mesh, minor_seg, major_seg):
from math import fmod
- mesh.uv_textures.new()
+ mesh.uv_layers.new()
uv_data = mesh.uv_layers.active.data
polygons = mesh.polygons
u_step = 1.0 / major_seg
@@ -134,19 +134,19 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
self.abso_major_rad = self.major_radius + self.minor_radius
self.abso_minor_rad = self.major_radius - self.minor_radius
- major_segments = IntProperty(
+ major_segments: IntProperty(
name="Major Segments",
description="Number of segments for the main ring of the torus",
min=3, max=256,
default=48,
)
- minor_segments = IntProperty(
+ minor_segments: IntProperty(
name="Minor Segments",
description="Number of segments for the minor ring of the torus",
min=3, max=256,
default=12,
)
- mode = bpy.props.EnumProperty(
+ mode: bpy.props.EnumProperty(
name="Torus Dimensions",
items=(("MAJOR_MINOR", "Major/Minor",
"Use the major/minor radii for torus dimensions"),
@@ -154,7 +154,7 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
"Use the exterior/interior radii for torus dimensions")),
update=mode_update_callback,
)
- major_radius = FloatProperty(
+ major_radius: FloatProperty(
name="Major Radius",
description=("Radius from the origin to the "
"center of the cross sections"),
@@ -163,7 +163,7 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
subtype='DISTANCE',
unit='LENGTH',
)
- minor_radius = FloatProperty(
+ minor_radius: FloatProperty(
name="Minor Radius",
description="Radius of the torus' cross section",
min=0.01, max=100.0,
@@ -171,7 +171,7 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
subtype='DISTANCE',
unit='LENGTH',
)
- abso_major_rad = FloatProperty(
+ abso_major_rad: FloatProperty(
name="Exterior Radius",
description="Total Exterior Radius of the torus",
min=0.01, max=100.0,
@@ -179,7 +179,7 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
subtype='DISTANCE',
unit='LENGTH',
)
- abso_minor_rad = FloatProperty(
+ abso_minor_rad: FloatProperty(
name="Interior Radius",
description="Total Interior Radius of the torus",
min=0.01, max=100.0,
@@ -187,7 +187,7 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
subtype='DISTANCE',
unit='LENGTH',
)
- generate_uvs = BoolProperty(
+ generate_uvs: BoolProperty(
name="Generate UVs",
description="Generate a default UV map",
default=False,
diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py
index 250c88b9009..31325cf0b50 100644
--- a/release/scripts/startup/bl_operators/anim.py
+++ b/release/scripts/startup/bl_operators/anim.py
@@ -40,20 +40,20 @@ class ANIM_OT_keying_set_export(Operator):
bl_idname = "anim.keying_set_export"
bl_label = "Export Keying Set..."
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
)
- filter_folder = BoolProperty(
+ filter_folder: BoolProperty(
name="Filter folders",
default=True,
options={'HIDDEN'},
)
- filter_text = BoolProperty(
+ filter_text: BoolProperty(
name="Filter text",
default=True,
options={'HIDDEN'},
)
- filter_python = BoolProperty(
+ filter_python: BoolProperty(
name="Filter python",
default=True,
options={'HIDDEN'},
@@ -110,7 +110,7 @@ class ANIM_OT_keying_set_export(Operator):
# - special handling is needed for "nested" ID-blocks
# (e.g. nodetree in Material)
if ksp.id.bl_rna.identifier.startswith("ShaderNodeTree"):
- # Find material or lamp using this node tree...
+ # Find material or light using this node tree...
id_bpy_path = "bpy.data.nodes[\"%s\"]"
found = False
@@ -121,14 +121,14 @@ class ANIM_OT_keying_set_export(Operator):
break
if not found:
- for lamp in bpy.data.lamps:
- if lamp.node_tree == ksp.id:
- id_bpy_path = "bpy.data.lamps[\"%s\"].node_tree" % (lamp.name)
+ for light in bpy.data.lights:
+ if light.node_tree == ksp.id:
+ id_bpy_path = "bpy.data.lights[\"%s\"].node_tree" % (light.name)
found = True
break
if not found:
- self.report({'WARN'}, "Could not find material or lamp using Shader Node Tree - %s" % (ksp.id))
+ self.report({'WARN'}, "Could not find material or light using Shader Node Tree - %s" % (ksp.id))
elif ksp.id.bl_rna.identifier.startswith("CompositorNodeTree"):
# Find compositor nodetree using this node tree...
for scene in bpy.data.scenes:
@@ -203,51 +203,51 @@ class BakeAction(Operator):
bl_label = "Bake Action"
bl_options = {'REGISTER', 'UNDO'}
- frame_start = IntProperty(
+ frame_start: IntProperty(
name="Start Frame",
description="Start frame for baking",
min=0, max=300000,
default=1,
)
- frame_end = IntProperty(
+ frame_end: IntProperty(
name="End Frame",
description="End frame for baking",
min=1, max=300000,
default=250,
)
- step = IntProperty(
+ step: IntProperty(
name="Frame Step",
description="Frame Step",
min=1, max=120,
default=1,
)
- only_selected = BoolProperty(
+ only_selected: BoolProperty(
name="Only Selected Bones",
description="Only key selected bones (Pose baking only)",
default=True,
)
- visual_keying = BoolProperty(
+ visual_keying: BoolProperty(
name="Visual Keying",
description="Keyframe from the final transformations (with constraints applied)",
default=False,
)
- clear_constraints = BoolProperty(
+ clear_constraints: BoolProperty(
name="Clear Constraints",
description="Remove all constraints from keyed object/bones, and do 'visual' keying",
default=False,
)
- clear_parents = BoolProperty(
+ clear_parents: BoolProperty(
name="Clear Parents",
description="Bake animation onto the object then clear parents (objects only)",
default=False,
)
- use_current_action = BoolProperty(
+ use_current_action: BoolProperty(
name="Overwrite Current Action",
description="Bake animation into current action, instead of creating a new one "
"(useful for baking only part of bones in an armature)",
default=False,
)
- bake_types = EnumProperty(
+ bake_types: EnumProperty(
name="Bake Data",
description="Which data's transformations to bake",
options={'ENUM_FLAG'},
@@ -302,7 +302,7 @@ class ClearUselessActions(Operator):
bl_label = "Clear Useless Actions"
bl_options = {'REGISTER', 'UNDO'}
- only_unused = BoolProperty(
+ only_unused: BoolProperty(
name="Only Unused",
description="Only unused (Fake User only) actions get considered",
default=True,
@@ -341,7 +341,7 @@ class UpdateAnimatedTransformConstraint(Operator):
bl_label = "Update Animated Transform Constraints"
bl_options = {'REGISTER', 'UNDO'}
- use_convert_to_radians = BoolProperty(
+ use_convert_to_radians: BoolProperty(
name="Convert To Radians",
description="Convert fcurves/drivers affecting rotations to radians (Warning: use this only once!)",
default=True,
diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py
index dda6b2fa5ab..2717a4f62a3 100644
--- a/release/scripts/startup/bl_operators/clip.py
+++ b/release/scripts/startup/bl_operators/clip.py
@@ -133,7 +133,7 @@ class CLIP_OT_filter_tracks(bpy.types.Operator):
bl_idname = "clip.filter_tracks"
bl_options = {'UNDO', 'REGISTER'}
- track_threshold = FloatProperty(
+ track_threshold: FloatProperty(
name="Track Threshold",
description="Filter Threshold to select problematic tracks",
default=5.0,
@@ -236,7 +236,7 @@ class CLIP_OT_track_to_empty(Operator):
ob = None
ob = bpy.data.objects.new(name=track.name, object_data=None)
- ob.select = True
+ ob.select_set(action='SELECT')
context.scene.objects.link(ob)
context.scene.objects.active = ob
@@ -516,7 +516,7 @@ object's movement caused by this constraint"""
# XXX, should probably use context.selected_editable_objects
# since selected objects can be from a lib or in hidden layer!
for ob in scene.objects:
- if ob.select:
+ if ob.select_set(action='SELECT'):
self._bake_object(scene, ob)
return {'FINISHED'}
@@ -613,24 +613,24 @@ class CLIP_OT_setup_tracking_scene(Operator):
CLIP_set_viewport_background(context, True, sc.clip, sc.clip_user)
@staticmethod
- def _setupRenderLayers(context):
+ def _setupViewLayers(context):
scene = context.scene
- rlayers = scene.render.layers
+ view_layers = scene.view_layers
- if not scene.render.layers.get("Foreground"):
- if len(rlayers) == 1:
- fg = rlayers[0]
+ if not view_layers.get("Foreground"):
+ if len(view_layers) == 1:
+ fg = view_layers[0]
fg.name = 'Foreground'
else:
- fg = scene.render.layers.new("Foreground")
+ fg = view_layers.new("Foreground")
fg.use_sky = True
fg.layers = [True] + [False] * 19
fg.layers_zmask = [False] * 10 + [True] + [False] * 9
fg.use_pass_vector = True
- if not scene.render.layers.get("Background"):
- bg = scene.render.layers.new("Background")
+ if not view_layers.get("Background"):
+ bg = view_layers.new("Background")
bg.use_pass_shadow = True
bg.use_pass_ambient_occlusion = True
bg.layers = [False] * 10 + [True] + [False] * 9
@@ -915,17 +915,17 @@ class CLIP_OT_setup_tracking_scene(Operator):
return [(layers_a[i] | layers_b[i]) for i in range(len(layers_a))]
@staticmethod
- def _createLamp(scene):
- lamp = bpy.data.lamps.new(name="Lamp", type='POINT')
- lampob = bpy.data.objects.new(name="Lamp", object_data=lamp)
- scene.objects.link(lampob)
+ def _createLight(scene):
+ light = bpy.data.lights.new(name="Light", type='POINT')
+ lightob = bpy.data.objects.new(name="Light", object_data=light)
+ scene.objects.link(lightob)
- lampob.matrix_local = Matrix.Translation((4.076, 1.005, 5.904))
+ lightob.matrix_local = Matrix.Translation((4.076, 1.005, 5.904))
- lamp.distance = 30
- lamp.shadow_method = 'RAY_SHADOW'
+ light.distance = 30
+ light.shadow_method = 'RAY_SHADOW'
- return lampob
+ return lightob
def _createSampleObject(self, scene):
vertices = self._getPlaneVertices(1.0, -1.0) + \
@@ -942,25 +942,25 @@ class CLIP_OT_setup_tracking_scene(Operator):
def _setupObjects(self, context):
scene = context.scene
- fg = scene.render.layers.get("Foreground")
- bg = scene.render.layers.get("Background")
+ fg = scene.view_layers.get("Foreground")
+ bg = scene.view_layers.get("Background")
all_layers = self._mergeLayers(fg.layers, bg.layers)
- # ensure all lamps are active on foreground and background
- has_lamp = False
+ # ensure all lights are active on foreground and background
+ has_light = False
has_mesh = False
for ob in scene.objects:
- if ob.type == 'LAMP':
+ if ob.type == 'LIGHT':
ob.layers = all_layers
- has_lamp = True
+ has_light = True
elif ob.type == 'MESH' and "is_ground" not in ob:
has_mesh = True
- # create sample lamp if there's no lamps in the scene
- if not has_lamp:
- lamp = self._createLamp(scene)
- lamp.layers = all_layers
+ # create sample light if there's no lights in the scene
+ if not has_light:
+ light = self._createLight(scene)
+ light.layers = all_layers
# create sample object if there's no meshes in the scene
if not has_mesh:
@@ -987,7 +987,7 @@ class CLIP_OT_setup_tracking_scene(Operator):
self._setupWorld(context)
self._setupCamera(context)
self._setupViewport(context)
- self._setupRenderLayers(context)
+ self._setupViewLayers(context)
self._setupNodes(context)
self._setupObjects(context)
diff --git a/release/scripts/startup/bl_operators/console.py b/release/scripts/startup/bl_operators/console.py
index 2d32f84805e..b62b9310224 100644
--- a/release/scripts/startup/bl_operators/console.py
+++ b/release/scripts/startup/bl_operators/console.py
@@ -37,7 +37,7 @@ class ConsoleExec(Operator):
bl_idname = "console.execute"
bl_label = "Console Execute"
- interactive = BoolProperty(
+ interactive: BoolProperty(
options={'SKIP_SAVE'},
)
@@ -137,7 +137,7 @@ class ConsoleLanguage(Operator):
bl_idname = "console.language"
bl_label = "Console Language"
- language = StringProperty(
+ language: StringProperty(
name="Language",
maxlen=32,
)
diff --git a/release/scripts/startup/bl_operators/file.py b/release/scripts/startup/bl_operators/file.py
index 5bb97ff298a..44948879fe6 100644
--- a/release/scripts/startup/bl_operators/file.py
+++ b/release/scripts/startup/bl_operators/file.py
@@ -37,56 +37,56 @@ class WM_OT_previews_batch_generate(Operator):
# -----------
# File props.
- files = CollectionProperty(
+ files: CollectionProperty(
type=bpy.types.OperatorFileListElement,
options={'HIDDEN', 'SKIP_SAVE'},
)
- directory = StringProperty(
+ directory: StringProperty(
maxlen=1024,
subtype='FILE_PATH',
options={'HIDDEN', 'SKIP_SAVE'},
)
# Show only images/videos, and directories!
- filter_blender = BoolProperty(
+ filter_blender: BoolProperty(
default=True,
options={'HIDDEN', 'SKIP_SAVE'},
)
- filter_folder = BoolProperty(
+ filter_folder: BoolProperty(
default=True,
options={'HIDDEN', 'SKIP_SAVE'},
)
# -----------
# Own props.
- use_scenes = BoolProperty(
+ use_scenes: BoolProperty(
default=True,
name="Scenes",
description="Generate scenes' previews",
)
- use_groups = BoolProperty(
+ use_collections: BoolProperty(
default=True,
- name="Groups",
- description="Generate groups' previews",
+ name="Collections",
+ description="Generate collections' previews",
)
- use_objects = BoolProperty(
+ use_objects: BoolProperty(
default=True,
name="Objects",
description="Generate objects' previews",
)
- use_intern_data = BoolProperty(
+ use_intern_data: BoolProperty(
default=True,
name="Mat/Tex/...",
description="Generate 'internal' previews (materials, textures, images, etc.)",
)
- use_trusted = BoolProperty(
+ use_trusted: BoolProperty(
default=False,
name="Trusted Blend Files",
description="Enable python evaluation for selected files",
)
- use_backups = BoolProperty(
+ use_backups: BoolProperty(
default=True,
name="Save Backups",
description="Keep a backup (.blend1) version of the files when saving with generated previews",
@@ -121,8 +121,8 @@ class WM_OT_previews_batch_generate(Operator):
])
if not self.use_scenes:
cmd.append('--no_scenes')
- if not self.use_groups:
- cmd.append('--no_groups')
+ if not self.use_collections:
+ cmd.append('--no_collections')
if not self.use_objects:
cmd.append('--no_objects')
if not self.use_intern_data:
@@ -147,55 +147,56 @@ class WM_OT_previews_batch_clear(Operator):
# -----------
# File props.
- files = CollectionProperty(
+ files: CollectionProperty(
type=bpy.types.OperatorFileListElement,
options={'HIDDEN', 'SKIP_SAVE'},
)
- directory = StringProperty(
+ directory: StringProperty(
maxlen=1024,
subtype='FILE_PATH',
options={'HIDDEN', 'SKIP_SAVE'},
)
# Show only images/videos, and directories!
- filter_blender = BoolProperty(
+ filter_blender: BoolProperty(
default=True,
options={'HIDDEN', 'SKIP_SAVE'},
)
- filter_folder = BoolProperty(
+ filter_folder: BoolProperty(
default=True,
options={'HIDDEN', 'SKIP_SAVE'},
)
# -----------
# Own props.
- use_scenes = BoolProperty(
+ use_scenes: BoolProperty(
default=True,
name="Scenes",
description="Clear scenes' previews",
)
- use_groups = BoolProperty(default=True,
- name="Groups",
- description="Clear groups' previews",
- )
- use_objects = BoolProperty(
+ use_collections: BoolProperty(
+ default=True,
+ name="Collections",
+ description="Clear collections' previews",
+ )
+ use_objects: BoolProperty(
default=True,
name="Objects",
description="Clear objects' previews",
)
- use_intern_data = BoolProperty(
+ use_intern_data: BoolProperty(
default=True,
name="Mat/Tex/...",
description="Clear 'internal' previews (materials, textures, images, etc.)",
)
- use_trusted = BoolProperty(
+ use_trusted: BoolProperty(
default=False,
name="Trusted Blend Files",
description="Enable python evaluation for selected files",
)
- use_backups = BoolProperty(
+ use_backups: BoolProperty(
default=True,
name="Save Backups",
description="Keep a backup (.blend1) version of the files when saving with cleared previews",
@@ -231,8 +232,8 @@ class WM_OT_previews_batch_clear(Operator):
])
if not self.use_scenes:
cmd.append('--no_scenes')
- if not self.use_groups:
- cmd.append('--no_groups')
+ if not self.use_collections:
+ cmd.append('--no_collections')
if not self.use_objects:
cmd.append('--no_objects')
if not self.use_intern_data:
diff --git a/release/scripts/startup/bl_operators/freestyle.py b/release/scripts/startup/bl_operators/freestyle.py
index 6ee840ffc75..894808de3ed 100644
--- a/release/scripts/startup/bl_operators/freestyle.py
+++ b/release/scripts/startup/bl_operators/freestyle.py
@@ -34,28 +34,28 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
bl_label = "Fill Range by Selection"
bl_options = {'INTERNAL'}
- type = EnumProperty(
+ type: EnumProperty(
name="Type", description="Type of the modifier to work on",
items=(("COLOR", "Color", "Color modifier type"),
("ALPHA", "Alpha", "Alpha modifier type"),
("THICKNESS", "Thickness", "Thickness modifier type")),
)
- name = StringProperty(
+ name: StringProperty(
name="Name",
description="Name of the modifier to work on",
)
@classmethod
def poll(cls, context):
- rl = context.scene.render.layers.active
- return rl and rl.freestyle_settings.linesets.active
+ view_layer = context.view_layer
+ return view_layer and view_layer.freestyle_settings.linesets.active
def execute(self, context):
import sys
scene = context.scene
- rl = scene.render.layers.active
- lineset = rl.freestyle_settings.linesets.active
+ view_layer = context.view_layer
+ lineset = view_layer.freestyle_settings.linesets.active
linestyle = lineset.linestyle
# Find the modifier to work on
if self.type == 'COLOR':
@@ -104,7 +104,7 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
m.range_max = max_dist
return {'FINISHED'}
# Find selected mesh objects
- selection = [ob for ob in scene.objects if ob.select and ob.type == 'MESH' and ob.name != ref.name]
+ selection = [ob for ob in scene.objects if ob.select_get() and ob.type == 'MESH' and ob.name != source.name]
if selection:
# Compute the min/max distance from the reference to mesh vertices
min_dist = sys.float_info.max
@@ -198,17 +198,17 @@ class SCENE_OT_freestyle_module_open(bpy.types.Operator):
bl_label = "Open Style Module File"
bl_options = {'INTERNAL'}
- filepath = StringProperty(subtype='FILE_PATH')
+ filepath: StringProperty(subtype='FILE_PATH')
- make_internal = BoolProperty(
+ make_internal: BoolProperty(
name="Make internal",
description="Make module file internal after loading",
default=True)
@classmethod
def poll(cls, context):
- rl = context.scene.render.layers.active
- return rl and rl.freestyle_settings.mode == 'SCRIPT'
+ view_layer = context.view_layer
+ return view_layer and view_layer.freestyle_settings.mode == 'SCRIPT'
def invoke(self, context, event):
self.freestyle_module = context.freestyle_module
diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py
index 5c5ca329cda..28e5e59d780 100644
--- a/release/scripts/startup/bl_operators/image.py
+++ b/release/scripts/startup/bl_operators/image.py
@@ -29,7 +29,7 @@ class EditExternally(Operator):
bl_label = "Image Edit Externally"
bl_options = {'REGISTER'}
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
)
diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py
index 7fb1877d191..a7475dcc6ef 100644
--- a/release/scripts/startup/bl_operators/mesh.py
+++ b/release/scripts/startup/bl_operators/mesh.py
@@ -33,7 +33,7 @@ class MeshMirrorUV(Operator):
bl_label = "Copy Mirrored UV coords"
bl_options = {'REGISTER', 'UNDO'}
- direction = EnumProperty(
+ direction: EnumProperty(
name="Axis Direction",
items=(
('POSITIVE', "Positive", ""),
@@ -41,7 +41,7 @@ class MeshMirrorUV(Operator):
),
)
- precision = IntProperty(
+ precision: IntProperty(
name="Precision",
description=("Tolerance for finding vertex duplicates"),
min=1, max=16,
@@ -52,7 +52,7 @@ class MeshMirrorUV(Operator):
@classmethod
def poll(cls, context):
obj = context.active_object
- return (obj and obj.type == 'MESH' and obj.data.uv_textures.active)
+ return (obj and obj.type == 'MESH' and obj.data.uv_layers.active)
def execute(self, context):
DIR = (self.direction == 'NEGATIVE')
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index bb8f991e526..fbebee2d8a1 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -34,7 +34,7 @@ from bpy.props import (
class NodeSetting(PropertyGroup):
- value = StringProperty(
+ value: StringProperty(
name="Value",
description="Python expression to be evaluated "
"as the initial node setting",
@@ -45,16 +45,16 @@ class NodeSetting(PropertyGroup):
# Base class for node 'Add' operators
class NodeAddOperator:
- type = StringProperty(
+ type: StringProperty(
name="Node Type",
description="Node type",
)
- use_transform = BoolProperty(
+ use_transform: BoolProperty(
name="Use Transform",
description="Start transform operator after inserting the node",
default=False,
)
- settings = CollectionProperty(
+ settings: CollectionProperty(
name="Settings",
description="Settings to be applied on the newly created node",
type=NodeSetting,
@@ -152,7 +152,7 @@ class NODE_OT_add_and_link_node(NodeAddOperator, Operator):
bl_label = "Add and Link Node"
bl_options = {'REGISTER', 'UNDO'}
- link_socket_index = IntProperty(
+ link_socket_index: IntProperty(
name="Link Socket Index",
description="Index of the socket to link",
)
@@ -210,7 +210,7 @@ class NODE_OT_add_search(NodeAddOperator, Operator):
return item
return None
- node_item = EnumProperty(
+ node_item: EnumProperty(
name="Node Type",
description="Node type",
items=node_enum_items,
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index 91e5859d2c0..be379ec6089 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -35,19 +35,19 @@ class SelectPattern(Operator):
bl_label = "Select Pattern"
bl_options = {'REGISTER', 'UNDO'}
- pattern = StringProperty(
+ pattern: StringProperty(
name="Pattern",
description="Name filter using '*', '?' and "
"'[abc]' unix style wildcards",
maxlen=64,
default="*",
)
- case_sensitive = BoolProperty(
+ case_sensitive: BoolProperty(
name="Case Sensitive",
description="Do a case sensitive compare",
default=False,
)
- extend = BoolProperty(
+ extend: BoolProperty(
name="Extend",
description="Extend the existing selection",
default=True,
@@ -81,16 +81,18 @@ class SelectPattern(Operator):
# Can be pose bones or objects
for item in items:
if pattern_match(item.name, self.pattern):
- item.select = True
# hrmf, perhaps there should be a utility function for this.
if is_ebone:
+ item.select = True
item.select_head = True
item.select_tail = True
if item.use_connect:
item_parent = item.parent
if item_parent is not None:
item_parent.select_tail = True
+ else:
+ item.select_set(action='SELECT')
return {'FINISHED'}
@@ -113,7 +115,7 @@ class SelectCamera(Operator):
bl_label = "Select Camera"
bl_options = {'REGISTER', 'UNDO'}
- extend = BoolProperty(
+ extend: BoolProperty(
name="Extend",
description="Extend the selection",
default=False
@@ -121,6 +123,7 @@ class SelectCamera(Operator):
def execute(self, context):
scene = context.scene
+ view_layer = context.view_layer
view = context.space_data
if view.type == 'VIEW_3D' and not view.lock_camera_and_layers:
camera = view.camera
@@ -134,9 +137,9 @@ class SelectCamera(Operator):
else:
if not self.extend:
bpy.ops.object.select_all(action='DESELECT')
- scene.objects.active = camera
- camera.hide = False
- camera.select = True
+ view_layer.objects.active = camera
+ # camera.hide = False # XXX TODO where is this now?
+ camera.select_set(action='SELECT')
return {'FINISHED'}
return {'CANCELLED'}
@@ -149,15 +152,15 @@ class SelectHierarchy(Operator):
bl_label = "Select Hierarchy"
bl_options = {'REGISTER', 'UNDO'}
- direction = EnumProperty(
+ direction: EnumProperty(
items=(('PARENT', "Parent", ""),
('CHILD', "Child", ""),
),
name="Direction",
description="Direction to select in the hierarchy",
- default='PARENT')
-
- extend = BoolProperty(
+ default='PARENT',
+ )
+ extend: BoolProperty(
name="Extend",
description="Extend the existing selection",
default=False,
@@ -169,6 +172,7 @@ class SelectHierarchy(Operator):
def execute(self, context):
scene = context.scene
+ view_layer = context.view_layer
select_new = []
act_new = None
@@ -202,9 +206,9 @@ class SelectHierarchy(Operator):
bpy.ops.object.select_all(action='DESELECT')
for obj in select_new:
- obj.select = True
+ obj.select_set(action='SELECT')
- scene.objects.active = act_new
+ view_layer.objects.active = act_new
return {'FINISHED'}
return {'CANCELLED'}
@@ -217,14 +221,13 @@ class SubdivisionSet(Operator):
bl_label = "Subdivision Set"
bl_options = {'REGISTER', 'UNDO'}
- level = IntProperty(
+ level: IntProperty(
name="Level",
min=-100, max=100,
soft_min=-6, soft_max=6,
default=1,
)
-
- relative = BoolProperty(
+ relative: BoolProperty(
name="Relative",
description=("Apply the subsurf level as an offset "
"relative to the current level"),
@@ -308,7 +311,7 @@ class ShapeTransfer(Operator):
bl_label = "Transfer Shape Key"
bl_options = {'REGISTER', 'UNDO'}
- mode = EnumProperty(
+ mode: EnumProperty(
items=(('OFFSET',
"Offset",
"Apply the relative positional offset",
@@ -326,7 +329,7 @@ class ShapeTransfer(Operator):
description="Relative shape positions to the new shape method",
default='OFFSET',
)
- use_clamp = BoolProperty(
+ use_clamp: BoolProperty(
name="Clamp Offset",
description=("Clamp the transformation to the distance each "
"vertex moves in the original shape"),
@@ -513,7 +516,7 @@ class JoinUVs(Operator):
if is_editmode:
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
- if not mesh.uv_textures:
+ if not mesh.uv_layers:
self.report({'WARNING'},
"Object: %s, Mesh: '%s' has no UVs"
% (obj.name, mesh.name))
@@ -551,7 +554,7 @@ class JoinUVs(Operator):
else:
uv_other = mesh_other.uv_layers.active
if not uv_other:
- mesh_other.uv_textures.new()
+ mesh_other.uv_layers.new()
uv_other = mesh_other.uv_layers.active
if not uv_other:
self.report({'ERROR'}, "Could not add "
@@ -644,8 +647,8 @@ class MakeDupliFace(Operator):
ob_new.use_dupli_faces_scale = True
ob_new.dupli_faces_scale = 1.0 / SCALE_FAC
- ob_inst.select = True
- ob_new.select = True
+ ob_inst.select_set(action='SELECT')
+ ob_new.select_set(action='SELECT')
def execute(self, context):
self._main(context)
@@ -664,7 +667,7 @@ class IsolateTypeRender(Operator):
for obj in context.visible_objects:
- if obj.select:
+ if obj.select_get():
obj.hide_render = False
else:
if obj.type == act_type:
@@ -692,7 +695,7 @@ class TransformsToDeltas(Operator):
bl_label = "Transforms to Deltas"
bl_options = {'REGISTER', 'UNDO'}
- mode = EnumProperty(
+ mode: EnumProperty(
items=(
('ALL', "All Transforms", "Transfer location, rotation, and scale transforms"),
('LOC', "Location", "Transfer location transforms only"),
@@ -703,7 +706,7 @@ class TransformsToDeltas(Operator):
description="Which transforms to transfer",
default='ALL',
)
- reset_values = BoolProperty(
+ reset_values: BoolProperty(
name="Reset Values",
description=("Clear transform values after transferring to deltas"),
default=True,
@@ -850,7 +853,7 @@ class TransformsToDeltasAnim(Operator):
class DupliOffsetFromCursor(Operator):
- """Set offset used for DupliGroup based on cursor position"""
+ """Set offset used for collection instances based on cursor position"""
bl_idname = "object.dupli_offset_from_cursor"
bl_label = "Set Offset From Cursor"
bl_options = {'INTERNAL', 'UNDO'}
@@ -861,166 +864,9 @@ class DupliOffsetFromCursor(Operator):
def execute(self, context):
scene = context.scene
- group = context.group
-
- group.dupli_offset = scene.cursor_location
-
- return {'FINISHED'}
-
-
-class LodByName(Operator):
- """Add levels of detail to this object based on object names"""
- bl_idname = "object.lod_by_name"
- bl_label = "Setup Levels of Detail By Name"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return (context.active_object is not None)
-
- def execute(self, context):
- ob = context.active_object
-
- prefix = ""
- suffix = ""
- name = ""
- if ob.name.lower().startswith("lod0"):
- prefix = ob.name[:4]
- name = ob.name[4:]
- elif ob.name.lower().endswith("lod0"):
- name = ob.name[:-4]
- suffix = ob.name[-4:]
- else:
- return {'CANCELLED'}
-
- level = 0
- while True:
- level += 1
-
- if prefix:
- prefix = prefix[:3] + str(level)
- if suffix:
- suffix = suffix[:3] + str(level)
-
- lod = None
- try:
- lod = bpy.data.objects[prefix + name + suffix]
- except KeyError:
- break
-
- try:
- ob.lod_levels[level]
- except IndexError:
- bpy.ops.object.lod_add()
-
- ob.lod_levels[level].object = lod
-
- return {'FINISHED'}
-
-
-class LodClearAll(Operator):
- """Remove all levels of detail from this object"""
- bl_idname = "object.lod_clear_all"
- bl_label = "Clear All Levels of Detail"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return (context.active_object is not None)
-
- def execute(self, context):
- ob = context.active_object
-
- if ob.lod_levels:
- while 'CANCELLED' not in bpy.ops.object.lod_remove():
- pass
-
- return {'FINISHED'}
-
-
-class LodGenerate(Operator):
- """Generate levels of detail using the decimate modifier"""
- bl_idname = "object.lod_generate"
- bl_label = "Generate Levels of Detail"
- bl_options = {'REGISTER', 'UNDO'}
-
- count = IntProperty(
- name="Count",
- default=3,
- )
- target = FloatProperty(
- name="Target Size",
- min=0.0, max=1.0,
- default=0.1,
- )
- package = BoolProperty(
- name="Package into Group",
- default=False,
- )
-
- @classmethod
- def poll(cls, context):
- return (context.active_object is not None)
-
- def execute(self, context):
- scene = context.scene
- ob = scene.objects.active
-
- lod_name = ob.name
- lod_suffix = "lod"
- lod_prefix = ""
- if lod_name.lower().endswith("lod0"):
- lod_suffix = lod_name[-3:-1]
- lod_name = lod_name[:-3]
- elif lod_name.lower().startswith("lod0"):
- lod_suffix = ""
- lod_prefix = lod_name[:3]
- lod_name = lod_name[4:]
-
- group_name = lod_name.strip(' ._')
- if self.package:
- try:
- bpy.ops.object.group_link(group=group_name)
- except TypeError:
- bpy.ops.group.create(name=group_name)
-
- step = (1.0 - self.target) / (self.count - 1)
- for i in range(1, self.count):
- scene.objects.active = ob
- bpy.ops.object.duplicate()
- lod = context.selected_objects[0]
-
- scene.objects.active = ob
- bpy.ops.object.lod_add()
- scene.objects.active = lod
-
- if lod_prefix:
- lod.name = lod_prefix + str(i) + lod_name
- else:
- lod.name = lod_name + lod_suffix + str(i)
-
- lod.location.y = ob.location.y + 3.0 * i
-
- if i == 1:
- modifier = lod.modifiers.new("lod_decimate", 'DECIMATE')
- else:
- modifier = lod.modifiers[-1]
-
- modifier.ratio = 1.0 - step * i
-
- ob.lod_levels[i].object = lod
-
- if self.package:
- bpy.ops.object.group_link(group=group_name)
- lod.parent = ob
-
- if self.package:
- for level in ob.lod_levels[1:]:
- level.object.hide = level.object.hide_render = True
+ collection = context.collection
- lod.select = False
- ob.select = True
- scene.objects.active = ob
+ collection.dupli_offset = scene.cursor_location
return {'FINISHED'}
@@ -1030,9 +876,6 @@ classes = (
DupliOffsetFromCursor,
IsolateTypeRender,
JoinUVs,
- LodByName,
- LodClearAll,
- LodGenerate,
MakeDupliFace,
SelectCamera,
SelectHierarchy,
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index 11c1514e4bf..f627fd30162 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -363,7 +363,7 @@ class AlignObjects(Operator):
bl_label = "Align Objects"
bl_options = {'REGISTER', 'UNDO'}
- bb_quality = BoolProperty(
+ bb_quality: BoolProperty(
name="High Quality",
description=(
"Enables high quality calculation of the "
@@ -372,7 +372,7 @@ class AlignObjects(Operator):
),
default=True,
)
- align_mode = EnumProperty(
+ align_mode: EnumProperty(
name="Align Mode:",
description="Side of object to use for alignment",
items=(
@@ -382,7 +382,7 @@ class AlignObjects(Operator):
),
default='OPT_2',
)
- relative_to = EnumProperty(
+ relative_to: EnumProperty(
name="Relative To:",
description="Reference location to align to",
items=(
@@ -393,7 +393,7 @@ class AlignObjects(Operator):
),
default='OPT_4',
)
- align_axis = EnumProperty(
+ align_axis: EnumProperty(
name="Align",
description="Align to axis",
items=(
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index c2592f13d66..36dc1b46590 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -52,7 +52,7 @@ class QuickFur(Operator):
bl_label = "Quick Fur"
bl_options = {'REGISTER', 'UNDO'}
- density = EnumProperty(
+ density: EnumProperty(
name="Fur Density",
items=(
('LIGHT', "Light", ""),
@@ -61,13 +61,13 @@ class QuickFur(Operator):
),
default='MEDIUM',
)
- view_percentage = IntProperty(
+ view_percentage: IntProperty(
name="View %",
min=1, max=100,
soft_min=1, soft_max=100,
default=10,
)
- length = FloatProperty(
+ length: FloatProperty(
name="Length",
min=0.001, max=100,
soft_min=0.01, soft_max=10,
@@ -118,7 +118,7 @@ class QuickExplode(Operator):
bl_label = "Quick Explode"
bl_options = {'REGISTER', 'UNDO'}
- style = EnumProperty(
+ style: EnumProperty(
name="Explode Style",
items=(
('EXPLODE', "Explode", ""),
@@ -126,40 +126,40 @@ class QuickExplode(Operator):
),
default='EXPLODE',
)
- amount = IntProperty(
+ amount: IntProperty(
name="Amount of pieces",
min=2, max=10000,
soft_min=2, soft_max=10000,
default=100,
)
- frame_duration = IntProperty(
+ frame_duration: IntProperty(
name="Duration",
min=1, max=300000,
soft_min=1, soft_max=10000,
default=50,
)
- frame_start = IntProperty(
+ frame_start: IntProperty(
name="Start Frame",
min=1, max=300000,
soft_min=1, soft_max=10000,
default=1,
)
- frame_end = IntProperty(
+ frame_end: IntProperty(
name="End Frame",
min=1, max=300000,
soft_min=1, soft_max=10000,
default=10,
)
- velocity = FloatProperty(
+ velocity: FloatProperty(
name="Outwards Velocity",
min=0, max=300000,
soft_min=0, soft_max=10,
default=1,
)
- fade = BoolProperty(
+ fade: BoolProperty(
name="Fade",
description="Fade the pieces over time",
default=True,
@@ -226,7 +226,7 @@ class QuickExplode(Operator):
if self.fade:
explode.show_dead = False
- uv = obj.data.uv_textures.new("Explode fade")
+ uv = obj.data.uv_layers.new("Explode fade")
explode.particle_uv = uv.name
mat = object_ensure_material(obj, "Explode Fade")
@@ -306,7 +306,7 @@ class QuickSmoke(Operator):
bl_label = "Quick Smoke"
bl_options = {'REGISTER', 'UNDO'}
- style = EnumProperty(
+ style: EnumProperty(
name="Smoke Style",
items=(
('SMOKE', "Smoke", ""),
@@ -316,7 +316,7 @@ class QuickSmoke(Operator):
default='SMOKE',
)
- show_flows = BoolProperty(
+ show_flows: BoolProperty(
name="Render Smoke Objects",
description="Keep the smoke objects visible during rendering",
default=False,
@@ -369,88 +369,38 @@ class QuickSmoke(Operator):
# Setup material
- # Cycles
- if context.scene.render.use_shading_nodes:
- bpy.ops.object.material_slot_add()
-
- mat = bpy.data.materials.new("Smoke Domain Material")
- obj.material_slots[0].material = mat
-
- # Make sure we use nodes
- mat.use_nodes = True
-
- # Set node variables and clear the default nodes
- tree = mat.node_tree
- nodes = tree.nodes
- links = tree.links
-
- nodes.clear()
+ # Cycles and Eevee
+ bpy.ops.object.material_slot_add()
- # Create shader nodes
+ mat = bpy.data.materials.new("Smoke Domain Material")
+ obj.material_slots[0].material = mat
- # Material output
- node_out = nodes.new(type='ShaderNodeOutputMaterial')
- node_out.location = grid_location(6, 1)
+ # Make sure we use nodes
+ mat.use_nodes = True
- # Add Principled Volume
- node_principled = nodes.new(type='ShaderNodeVolumePrincipled')
- node_principled.location = grid_location(4, 1)
- links.new(node_principled.outputs["Volume"],
- node_out.inputs["Volume"])
+ # Set node variables and clear the default nodes
+ tree = mat.node_tree
+ nodes = tree.nodes
+ links = tree.links
- node_principled.inputs["Density"].default_value = 5.0
+ nodes.clear()
- if self.style in {'FIRE', 'BOTH'}:
- node_principled.inputs["Blackbody Intensity"].default_value = 1.0
+ # Create shader nodes
- # Blender Internal
- else:
- # create a volume material with a voxel data texture for the domain
- bpy.ops.object.material_slot_add()
-
- mat = bpy.data.materials.new("Smoke Domain Material")
- obj.material_slots[0].material = mat
- mat.type = 'VOLUME'
- mat.volume.density = 0
- mat.volume.density_scale = 5
- mat.volume.step_size = 0.1
-
- tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
- tex.voxel_data.domain_object = obj
- tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
-
- tex_slot = mat.texture_slots.add()
- tex_slot.texture = tex
- tex_slot.texture_coords = 'ORCO'
- tex_slot.use_map_color_emission = False
- tex_slot.use_map_density = True
- tex_slot.use_map_color_reflection = True
-
- # for fire add a second texture for flame emission
- mat.volume.emission_color = Vector((0.0, 0.0, 0.0))
- tex = bpy.data.textures.new("Flame", 'VOXEL_DATA')
- tex.voxel_data.domain_object = obj
- tex.voxel_data.smoke_data_type = 'SMOKEFLAME'
- tex.voxel_data.interpolation = 'TRICUBIC_BSPLINE'
- tex.use_color_ramp = True
+ # Material output
+ node_out = nodes.new(type='ShaderNodeOutputMaterial')
+ node_out.location = grid_location(6, 1)
- tex_slot = mat.texture_slots.add()
- tex_slot.texture = tex
- tex_slot.texture_coords = 'ORCO'
+ # Add Principled Volume
+ node_principled = nodes.new(type='ShaderNodeVolumePrincipled')
+ node_principled.location = grid_location(4, 1)
+ links.new(node_principled.outputs["Volume"],
+ node_out.inputs["Volume"])
- # add color ramp for flame color
- ramp = tex.color_ramp
- # dark orange
- elem = ramp.elements.new(0.333)
- elem.color = (0.2, 0.03, 0.0, 1.0)
+ node_principled.inputs["Density"].default_value = 5.0
- # yellow glow
- elem = ramp.elements.new(0.666)
- elem.color = (1, 0.65, 0.25, 1.0)
-
- mat.texture_slots[1].use_map_density = True
- mat.texture_slots[1].use_map_emission = True
- mat.texture_slots[1].emission_factor = 5
+ if self.style in {'FIRE', 'BOTH'}:
+ node_principled.inputs["Blackbody Intensity"].default_value = 1.0
return {'FINISHED'}
@@ -460,7 +410,7 @@ class QuickFluid(Operator):
bl_label = "Quick Fluid"
bl_options = {'REGISTER', 'UNDO'}
- style = EnumProperty(
+ style: EnumProperty(
name="Fluid Style",
items=(
('INFLOW', "Inflow", ""),
@@ -468,19 +418,19 @@ class QuickFluid(Operator):
),
default='BASIC',
)
- initial_velocity = FloatVectorProperty(
+ initial_velocity: FloatVectorProperty(
name="Initial Velocity",
description="Initial velocity of the fluid",
min=-100.0, max=100.0,
default=(0.0, 0.0, 0.0),
subtype='VELOCITY',
)
- show_flows = BoolProperty(
+ show_flows: BoolProperty(
name="Render Fluid Objects",
description="Keep the fluid objects visible during rendering",
default=False,
)
- start_baking = BoolProperty(
+ start_baking: BoolProperty(
name="Start Fluid Bake",
description=("Start baking the fluid immediately "
"after creating the domain object"),
@@ -554,13 +504,33 @@ class QuickFluid(Operator):
mat = bpy.data.materials.new("Fluid Domain Material")
obj.material_slots[0].material = mat
- mat.specular_intensity = 1
- mat.specular_hardness = 100
- mat.use_transparency = True
- mat.alpha = 0.0
- mat.transparency_method = 'RAYTRACE'
- mat.raytrace_transparency.ior = 1.33
- mat.raytrace_transparency.depth = 4
+ # Make sure we use nodes
+ mat.use_nodes = True
+
+ # Set node variables and clear the default nodes
+ tree = mat.node_tree
+ nodes = tree.nodes
+ links = tree.links
+
+ nodes.clear()
+
+ # Create shader nodes
+
+ # Material output
+ node_out = nodes.new(type='ShaderNodeOutputMaterial')
+ node_out.location = grid_location(6, 1)
+
+ # Add Glass
+ node_glass = nodes.new(type='ShaderNodeBsdfGlass')
+ node_glass.location = grid_location(4, 1)
+ links.new(node_glass.outputs["BSDF"], node_out.inputs["Surface"])
+ node_glass.inputs["IOR"].default_value = 1.33
+
+ # Add Absorption
+ node_absorption = nodes.new(type='ShaderNodeVolumeAbsorption')
+ node_absorption.location = grid_location(4, 2)
+ links.new(node_absorption.outputs["Volume"], node_out.inputs["Volume"])
+ node_absorption.inputs["Color"].default_value = (0.8, 0.9, 1.0, 1.0)
if self.start_baking:
bpy.ops.fluid.bake('INVOKE_DEFAULT')
diff --git a/release/scripts/startup/bl_operators/object_randomize_transform.py b/release/scripts/startup/bl_operators/object_randomize_transform.py
index dbc9461ad5a..6e2dad079ee 100644
--- a/release/scripts/startup/bl_operators/object_randomize_transform.py
+++ b/release/scripts/startup/bl_operators/object_randomize_transform.py
@@ -103,25 +103,25 @@ class RandomizeLocRotSize(Operator):
bl_label = "Randomize Transform"
bl_options = {'REGISTER', 'UNDO'}
- random_seed = IntProperty(
+ random_seed: IntProperty(
name="Random Seed",
description="Seed value for the random generator",
min=0,
max=10000,
default=0,
)
- use_delta = BoolProperty(
+ use_delta: BoolProperty(
name="Transform Delta",
description=("Randomize delta transform values "
"instead of regular transform"),
default=False,
)
- use_loc = BoolProperty(
+ use_loc: BoolProperty(
name="Randomize Location",
description="Randomize the location values",
default=True,
)
- loc = FloatVectorProperty(
+ loc: FloatVectorProperty(
name="Location",
description=("Maximum distance the objects "
"can spread over each axis"),
@@ -130,12 +130,12 @@ class RandomizeLocRotSize(Operator):
default=(0.0, 0.0, 0.0),
subtype='TRANSLATION',
)
- use_rot = BoolProperty(
+ use_rot: BoolProperty(
name="Randomize Rotation",
description="Randomize the rotation values",
default=True,
)
- rot = FloatVectorProperty(
+ rot: FloatVectorProperty(
name="Rotation",
description="Maximum rotation over each axis",
min=-3.141592, # math.pi
@@ -143,25 +143,25 @@ class RandomizeLocRotSize(Operator):
default=(0.0, 0.0, 0.0),
subtype='EULER',
)
- use_scale = BoolProperty(
+ use_scale: BoolProperty(
name="Randomize Scale",
description="Randomize the scale values",
default=True,
)
- scale_even = BoolProperty(
+ scale_even: BoolProperty(
name="Scale Even",
description="Use the same scale value for all axis",
default=False,
)
- '''scale_min = FloatProperty(
+ '''scale_min: FloatProperty(
name="Minimun Scale Factor",
description="Lowest scale percentage possible",
min=-1.0, max=1.0, precision=3,
default=0.15,
)'''
- scale = FloatVectorProperty(
+ scale: FloatVectorProperty(
name="Scale",
description="Maximum scale randomization over each axis",
min=-100.0,
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 8852bca971d..530194e5bb7 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -19,9 +19,16 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Operator
+from bpy.types import Menu, Operator, Panel, WindowManager
from bpy.props import StringProperty, BoolProperty
+# For preset popover menu
+WindowManager.preset_name = StringProperty(
+ name="Preset Name",
+ description="Name for new preset",
+ default="New Preset"
+)
+
class AddPresetBase:
"""Base preset class, only for subclassing
@@ -34,22 +41,20 @@ class AddPresetBase:
# only because invoke_props_popup requires. Also do not add to search menu.
bl_options = {'REGISTER', 'INTERNAL'}
- name = StringProperty(
+ name: StringProperty(
name="Name",
description="Name of the preset, used to make the path name",
maxlen=64,
options={'SKIP_SAVE'},
)
- remove_active = BoolProperty(
+ remove_name: BoolProperty(
+ default=False,
+ options={'HIDDEN', 'SKIP_SAVE'},
+ )
+ remove_active: BoolProperty(
default=False,
options={'HIDDEN', 'SKIP_SAVE'},
)
-
- # needed for mix-ins
- order = [
- "name",
- "remove_active",
- ]
@staticmethod
def as_filename(name): # could reuse for other presets
@@ -85,11 +90,17 @@ class AddPresetBase:
else:
ext = ".py"
- if not self.remove_active:
- name = self.name.strip()
+ name = self.name.strip()
+ if not (self.remove_name or self.remove_active):
+
if not name:
return {'FINISHED'}
+ # Reset preset name
+ wm = bpy.data.window_managers[0]
+ if name == wm.preset_name:
+ wm.preset_name = 'New Preset'
+
filename = self.as_filename(name)
target_path = os.path.join("presets", self.preset_subdir)
@@ -155,15 +166,16 @@ class AddPresetBase:
preset_menu_class.bl_label = bpy.path.display_name(filename)
else:
- preset_active = preset_menu_class.bl_label
+ if self.remove_active:
+ name = preset_menu_class.bl_label
# fairly sloppy but convenient.
- filepath = bpy.utils.preset_find(preset_active,
+ filepath = bpy.utils.preset_find(name,
self.preset_subdir,
ext=ext)
if not filepath:
- filepath = bpy.utils.preset_find(preset_active,
+ filepath = bpy.utils.preset_find(name,
self.preset_subdir,
display_name=True,
ext=ext)
@@ -194,7 +206,7 @@ class AddPresetBase:
self.name = self.as_filename(self.name.strip())
def invoke(self, context, event):
- if not self.remove_active:
+ if not (self.remove_active or self.remove_name):
wm = context.window_manager
return wm.invoke_props_dialog(self)
else:
@@ -206,11 +218,11 @@ class ExecutePreset(Operator):
bl_idname = "script.execute_preset"
bl_label = "Execute a Python Preset"
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
options={'SKIP_SAVE'},
)
- menu_idname = StringProperty(
+ menu_idname: StringProperty(
name="Menu ID Name",
description="ID name of the menu this was called from",
options={'SKIP_SAVE'},
@@ -241,18 +253,51 @@ class ExecutePreset(Operator):
return {'FINISHED'}
+class PresetMenu(Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'HEADER'
+ bl_label = "Presets"
+ path_menu: Menu.path_menu
+
+ @classmethod
+ def draw_panel_header(cls, layout):
+ layout.emboss = 'NONE'
+ layout.popover(
+ panel=cls.__name__,
+ icon='PRESET',
+ text="",
+ )
+
+ @classmethod
+ def draw_menu(cls, layout, text=None):
+ if text is None:
+ text = cls.bl_label
+
+ layout.popover(
+ panel=cls.__name__,
+ icon='PRESET',
+ text=text,
+ )
+
+ def draw(self, context):
+ layout = self.layout
+ layout.emboss = 'PULLDOWN_MENU'
+ layout.operator_context = 'EXEC_DEFAULT'
+
+ Menu.draw_preset(self, context)
+
+
class AddPresetRender(AddPresetBase, Operator):
"""Add or remove a Render Preset"""
bl_idname = "render.preset_add"
bl_label = "Add Render Preset"
- preset_menu = "RENDER_MT_presets"
+ preset_menu = "RENDER_PT_presets"
preset_defines = [
"scene = bpy.context.scene"
]
preset_values = [
- "scene.render.field_order",
"scene.render.fps",
"scene.render.fps_base",
"scene.render.pixel_aspect_x",
@@ -260,8 +305,6 @@ class AddPresetRender(AddPresetBase, Operator):
"scene.render.resolution_percentage",
"scene.render.resolution_x",
"scene.render.resolution_y",
- "scene.render.use_fields",
- "scene.render.use_fields_still",
]
preset_subdir = "render"
@@ -271,7 +314,7 @@ class AddPresetCamera(AddPresetBase, Operator):
"""Add or remove a Camera Preset"""
bl_idname = "camera.preset_add"
bl_label = "Add Camera Preset"
- preset_menu = "CAMERA_MT_presets"
+ preset_menu = "CAMERA_PT_presets"
preset_defines = [
"cam = bpy.context.camera"
@@ -279,7 +322,7 @@ class AddPresetCamera(AddPresetBase, Operator):
preset_subdir = "camera"
- use_focal_length = BoolProperty(
+ use_focal_length: BoolProperty(
name="Include Focal Length",
description="Include focal length into the preset",
options={'SKIP_SAVE'},
@@ -302,7 +345,7 @@ class AddPresetSafeAreas(AddPresetBase, Operator):
"""Add or remove a Safe Areas Preset"""
bl_idname = "safe_areas.preset_add"
bl_label = "Add Safe Area Preset"
- preset_menu = "SAFE_AREAS_MT_presets"
+ preset_menu = "SAFE_AREAS_PT_presets"
preset_defines = [
"safe_areas = bpy.context.scene.safe_areas"
@@ -318,39 +361,11 @@ class AddPresetSafeAreas(AddPresetBase, Operator):
preset_subdir = "safe_areas"
-class AddPresetSSS(AddPresetBase, Operator):
- """Add or remove a Subsurface Scattering Preset"""
- bl_idname = "material.sss_preset_add"
- bl_label = "Add SSS Preset"
- preset_menu = "MATERIAL_MT_sss_presets"
-
- preset_defines = [
- ("material = "
- "bpy.context.material.active_node_material "
- "if bpy.context.material.active_node_material "
- "else bpy.context.material")
- ]
-
- preset_values = [
- "material.subsurface_scattering.back",
- "material.subsurface_scattering.color",
- "material.subsurface_scattering.color_factor",
- "material.subsurface_scattering.error_threshold",
- "material.subsurface_scattering.front",
- "material.subsurface_scattering.ior",
- "material.subsurface_scattering.radius",
- "material.subsurface_scattering.scale",
- "material.subsurface_scattering.texture_factor",
- ]
-
- preset_subdir = "sss"
-
-
class AddPresetCloth(AddPresetBase, Operator):
"""Add or remove a Cloth Preset"""
bl_idname = "cloth.preset_add"
bl_label = "Add Cloth Preset"
- preset_menu = "CLOTH_MT_presets"
+ preset_menu = "CLOTH_PT_presets"
preset_defines = [
"cloth = bpy.context.cloth"
@@ -372,7 +387,7 @@ class AddPresetFluid(AddPresetBase, Operator):
"""Add or remove a Fluid Preset"""
bl_idname = "fluid.preset_add"
bl_label = "Add Fluid Preset"
- preset_menu = "FLUID_MT_presets"
+ preset_menu = "FLUID_PT_presets"
preset_defines = [
"fluid = bpy.context.fluid"
@@ -390,7 +405,7 @@ class AddPresetHairDynamics(AddPresetBase, Operator):
"""Add or remove a Hair Dynamics Preset"""
bl_idname = "particle.hair_dynamics_preset_add"
bl_label = "Add Hair Dynamics Preset"
- preset_menu = "PARTICLE_MT_hair_dynamics_presets"
+ preset_menu = "PARTICLE_PT_hair_dynamics_presets"
preset_defines = [
"psys = bpy.context.particle_system",
@@ -416,35 +431,6 @@ class AddPresetHairDynamics(AddPresetBase, Operator):
]
-class AddPresetSunSky(AddPresetBase, Operator):
- """Add or remove a Sky & Atmosphere Preset"""
- bl_idname = "lamp.sunsky_preset_add"
- bl_label = "Add Sunsky Preset"
- preset_menu = "LAMP_MT_sunsky_presets"
-
- preset_defines = [
- "sky = bpy.context.lamp.sky"
- ]
-
- preset_values = [
- "sky.atmosphere_extinction",
- "sky.atmosphere_inscattering",
- "sky.atmosphere_turbidity",
- "sky.backscattered_light",
- "sky.horizon_brightness",
- "sky.spread",
- "sky.sun_brightness",
- "sky.sun_intensity",
- "sky.sun_size",
- "sky.sky_blend",
- "sky.sky_blend_type",
- "sky.sky_color_space",
- "sky.sky_exposure",
- ]
-
- preset_subdir = "sunsky"
-
-
class AddPresetInteraction(AddPresetBase, Operator):
"""Add or remove an Application Interaction Preset"""
bl_idname = "wm.interaction_preset_add"
@@ -475,7 +461,7 @@ class AddPresetTrackingCamera(AddPresetBase, Operator):
"""Add or remove a Tracking Camera Intrinsics Preset"""
bl_idname = "clip.camera_preset_add"
bl_label = "Add Camera Preset"
- preset_menu = "CLIP_MT_camera_presets"
+ preset_menu = "CLIP_PT_camera_presets"
preset_defines = [
"camera = bpy.context.edit_movieclip.tracking.camera"
@@ -483,7 +469,7 @@ class AddPresetTrackingCamera(AddPresetBase, Operator):
preset_subdir = "tracking_camera"
- use_focal_length = BoolProperty(
+ use_focal_length: BoolProperty(
name="Include Focal Length",
description="Include focal length into the preset",
options={'SKIP_SAVE'},
@@ -509,7 +495,7 @@ class AddPresetTrackingTrackColor(AddPresetBase, Operator):
"""Add or remove a Clip Track Color Preset"""
bl_idname = "clip.track_color_preset_add"
bl_label = "Add Track Color Preset"
- preset_menu = "CLIP_MT_track_color_presets"
+ preset_menu = "CLIP_PT_track_color_presets"
preset_defines = [
"track = bpy.context.edit_movieclip.tracking.tracks.active"
@@ -527,7 +513,7 @@ class AddPresetTrackingSettings(AddPresetBase, Operator):
"""Add or remove a motion tracking settings preset"""
bl_idname = "clip.tracking_settings_preset_add"
bl_label = "Add Tracking Settings Preset"
- preset_menu = "CLIP_MT_tracking_settings_presets"
+ preset_menu = "CLIP_PT_tracking_settings_presets"
preset_defines = [
"settings = bpy.context.edit_movieclip.tracking.settings"
@@ -557,7 +543,7 @@ class AddPresetNodeColor(AddPresetBase, Operator):
"""Add or remove a Node Color Preset"""
bl_idname = "node.node_color_preset_add"
bl_label = "Add Node Color Preset"
- preset_menu = "NODE_MT_node_color_presets"
+ preset_menu = "NODE_PT_node_color_presets"
preset_defines = [
"node = bpy.context.active_node"
@@ -608,7 +594,7 @@ class AddPresetOperator(AddPresetBase, Operator):
bl_label = "Operator Preset"
preset_menu = "WM_MT_operator_presets"
- operator = StringProperty(
+ operator: StringProperty(
name="Operator",
maxlen=64,
options={'HIDDEN', 'SKIP_SAVE'},
@@ -670,7 +656,7 @@ class AddPresetUnitsLength(AddPresetBase, Operator):
"""Add or remove length units preset"""
bl_idname = "scene.units_length_preset_add"
bl_label = "Add Length Units Preset"
- preset_menu = "SCENE_MT_units_length_presets"
+ preset_menu = "SCENE_PT_units_length_presets"
preset_defines = [
"scene = bpy.context.scene"
@@ -695,9 +681,7 @@ classes = (
AddPresetNodeColor,
AddPresetOperator,
AddPresetRender,
- AddPresetSSS,
AddPresetSafeAreas,
- AddPresetSunSky,
AddPresetTrackingCamera,
AddPresetTrackingSettings,
AddPresetTrackingTrackColor,
diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py
index 8fbc9b29b46..36150a63895 100644
--- a/release/scripts/startup/bl_operators/rigidbody.py
+++ b/release/scripts/startup/bl_operators/rigidbody.py
@@ -65,7 +65,7 @@ class CopyRigidbodySettings(Operator):
# deselect all but mesh objects
for o in context.selected_objects:
if o.type != 'MESH':
- o.select = False
+ o.select_set(action='DESELECT')
elif o.rigid_body is None:
# Add rigidbody to object!
scene.objects.active = o
@@ -92,19 +92,19 @@ class BakeToKeyframes(Operator):
bl_label = "Bake To Keyframes"
bl_options = {'REGISTER', 'UNDO'}
- frame_start = IntProperty(
+ frame_start: IntProperty(
name="Start Frame",
description="Start frame for baking",
min=0, max=300000,
default=1,
)
- frame_end = IntProperty(
+ frame_end: IntProperty(
name="End Frame",
description="End frame for baking",
min=1, max=300000,
default=250,
)
- step = IntProperty(
+ step: IntProperty(
name="Frame Step",
description="Frame Step",
min=1, max=120,
@@ -127,7 +127,7 @@ class BakeToKeyframes(Operator):
# filter objects selection
for obj in context.selected_objects:
if not obj.rigid_body or obj.rigid_body.type != 'ACTIVE':
- obj.select = False
+ obj.select_set(action='DESELECT')
objects = context.selected_objects
@@ -216,7 +216,7 @@ class ConnectRigidBodies(Operator):
bl_label = "Connect Rigid Bodies"
bl_options = {'REGISTER', 'UNDO'}
- con_type = EnumProperty(
+ con_type: EnumProperty(
name="Type",
description="Type of generated constraint",
# XXX Would be nice to get icons too, but currently not possible ;)
@@ -226,7 +226,7 @@ class ConnectRigidBodies(Operator):
),
default='FIXED',
)
- pivot_type = EnumProperty(
+ pivot_type: EnumProperty(
name="Location",
description="Constraint pivot location",
items=(
@@ -236,7 +236,7 @@ class ConnectRigidBodies(Operator):
),
default='CENTER',
)
- connection_pattern = EnumProperty(
+ connection_pattern: EnumProperty(
name="Connection Pattern",
description="Pattern used to connect objects",
items=(
@@ -266,7 +266,7 @@ class ConnectRigidBodies(Operator):
ob.location = loc
context.scene.objects.link(ob)
context.scene.objects.active = ob
- ob.select = True
+ ob.select_set(action='SELECT')
bpy.ops.rigidbody.constraint_add()
con_obj = context.active_object
@@ -311,7 +311,7 @@ class ConnectRigidBodies(Operator):
# restore selection
bpy.ops.object.select_all(action='DESELECT')
for obj in objects:
- obj.select = True
+ obj.select_set(action='SELECT')
scene.objects.active = obj_act
return {'FINISHED'}
else:
diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py
index c9a7aa93805..b1152157cf8 100644
--- a/release/scripts/startup/bl_operators/sequencer.py
+++ b/release/scripts/startup/bl_operators/sequencer.py
@@ -82,7 +82,7 @@ class SequencerCutMulticam(Operator):
bl_label = "Cut multicam"
bl_options = {'REGISTER', 'UNDO'}
- camera = IntProperty(
+ camera: IntProperty(
name="Camera",
min=1, max=32,
soft_min=1, soft_max=32,
diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index 72445be6950..5c870849cc5 100644
--- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -30,8 +30,8 @@ def extend(obj, operator, EXTEND_MODE):
import bmesh
me = obj.data
# script will fail without UVs
- if not me.uv_textures:
- me.uv_textures.new()
+ if not me.uv_layers:
+ me.uv_layers.new()
bm = bmesh.from_edit_mesh(me)
@@ -226,7 +226,7 @@ class FollowActiveQuads(Operator):
bl_label = "Follow Active Quads"
bl_options = {'REGISTER', 'UNDO'}
- mode = bpy.props.EnumProperty(
+ mode: bpy.props.EnumProperty(
name="Edge Length Mode",
description="Method to space UV edge loops",
items=(('EVEN', "Even", "Space all UVs evenly"),
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 0b0dd58e80f..95a3d18304b 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -275,12 +275,12 @@ def lightmap_uvpack(meshes,
face_groups.append(faces)
if PREF_NEW_UVLAYER:
- me.uv_textures.new()
+ me.uv_layers.new()
# Add face UV if it does not exist.
# All new faces are selected.
- if not me.uv_textures:
- me.uv_textures.new()
+ if not me.uv_layers:
+ me.uv_layers.new()
for face_sel in face_groups:
print("\nStarting unwrap")
@@ -538,6 +538,9 @@ def lightmap_uvpack(meshes,
print("done")
if PREF_APPLY_IMAGE:
+ pass
+ # removed with texface
+ '''
if not PREF_PACK_IN_ONE:
image = bpy.data.images.new(name="lightmap",
width=PREF_IMG_PX_SIZE,
@@ -545,8 +548,8 @@ def lightmap_uvpack(meshes,
)
for f in face_sel:
- # f.image = image
- f.id_data.uv_textures.active.data[f.index].image = image # XXX25
+ f.image = image
+ '''
for me in meshes:
me.update()
@@ -613,7 +616,7 @@ class LightMapPack(Operator):
# This fixes infinite image creation reported there [#30968] (sergey)
bl_options = {'UNDO'}
- PREF_CONTEXT = bpy.props.EnumProperty(
+ PREF_CONTEXT: bpy.props.EnumProperty(
name="Selection",
items=(
('SEL_FACES', "Selected Faces", "Space all UVs evenly"),
@@ -623,7 +626,7 @@ class LightMapPack(Operator):
)
# Image & UVs...
- PREF_PACK_IN_ONE = BoolProperty(
+ PREF_PACK_IN_ONE: BoolProperty(
name="Share Tex Space",
description=(
"Objects Share texture space, map all objects "
@@ -631,12 +634,12 @@ class LightMapPack(Operator):
),
default=True,
)
- PREF_NEW_UVLAYER = BoolProperty(
+ PREF_NEW_UVLAYER: BoolProperty(
name="New UV Map",
description="Create a new UV map for every mesh packed",
default=False,
)
- PREF_APPLY_IMAGE = BoolProperty(
+ PREF_APPLY_IMAGE: BoolProperty(
name="New Image",
description=(
"Assign new images for every mesh (only one if "
@@ -644,20 +647,20 @@ class LightMapPack(Operator):
),
default=False,
)
- PREF_IMG_PX_SIZE = IntProperty(
+ PREF_IMG_PX_SIZE: IntProperty(
name="Image Size",
description="Width and Height for the new image",
min=64, max=5000,
default=512,
)
# UV Packing...
- PREF_BOX_DIV = IntProperty(
+ PREF_BOX_DIV: IntProperty(
name="Pack Quality",
description="Pre Packing before the complex boxpack",
min=1, max=48,
default=12,
)
- PREF_MARGIN_DIV = FloatProperty(
+ PREF_MARGIN_DIV: FloatProperty(
name="Margin",
description="Size of the margin as a division of the UV",
min=0.001, max=1.0,
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index f0b1f934e38..fe15b9fa345 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -816,8 +816,8 @@ def main(context,
# Tag as used
me.tag = True
- if not me.uv_textures: # Mesh has no UV Coords, don't bother.
- me.uv_textures.new()
+ if not me.uv_layers: # Mesh has no UV Coords, don't bother.
+ me.uv_layers.new()
uv_layer = me.uv_layers.active.data
me_verts = list(me.vertices)
@@ -1055,31 +1055,31 @@ class SmartProject(Operator):
bl_label = "Smart UV Project"
bl_options = {'REGISTER', 'UNDO'}
- angle_limit = FloatProperty(
+ angle_limit: FloatProperty(
name="Angle Limit",
description="Lower for more projection groups, higher for less distortion",
min=1.0, max=89.0,
default=66.0,
)
- island_margin = FloatProperty(
+ island_margin: FloatProperty(
name="Island Margin",
description="Margin to reduce bleed from adjacent islands",
unit='LENGTH', subtype='DISTANCE',
min=0.0, max=1.0,
default=0.0,
)
- user_area_weight = FloatProperty(
+ user_area_weight: FloatProperty(
name="Area Weight",
description="Weight projections vector by faces with larger areas",
min=0.0, max=1.0,
default=0.0,
)
- use_aspect = BoolProperty(
+ use_aspect: BoolProperty(
name="Correct Aspect",
description="Map UVs taking image aspect ratio into account",
default=True
)
- stretch_to_bounds = BoolProperty(
+ stretch_to_bounds: BoolProperty(
name="Stretch to UV Bounds",
description="Stretch the final output to texture bounds",
default=True,
diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index 1173e0047bb..335c3d8bbda 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -138,33 +138,33 @@ class VertexPaintDirt(Operator):
bl_label = "Dirty Vertex Colors"
bl_options = {'REGISTER', 'UNDO'}
- blur_strength = FloatProperty(
+ blur_strength: FloatProperty(
name="Blur Strength",
description="Blur strength per iteration",
min=0.01, max=1.0,
default=1.0,
)
- blur_iterations = IntProperty(
+ blur_iterations: IntProperty(
name="Blur Iterations",
description="Number of times to blur the colors (higher blurs more)",
min=0, max=40,
default=1,
)
- clean_angle = FloatProperty(
+ clean_angle: FloatProperty(
name="Highlight Angle",
description="Less than 90 limits the angle used in the tonal range",
min=0.0, max=pi,
default=pi,
unit="ROTATION",
)
- dirt_angle = FloatProperty(
+ dirt_angle: FloatProperty(
name="Dirt Angle",
description="Less than 90 limits the angle used in the tonal range",
min=0.0, max=pi,
default=0.0,
unit="ROTATION",
)
- dirt_only = BoolProperty(
+ dirt_only: BoolProperty(
name="Dirt Only",
description="Don't calculate cleans for convex areas",
default=False,
diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py
index f56c83be7d1..b43f4446802 100644
--- a/release/scripts/startup/bl_operators/view3d.py
+++ b/release/scripts/startup/bl_operators/view3d.py
@@ -143,37 +143,37 @@ class VIEW3D_OT_select_or_deselect_all(Operator):
bl_idname = "view3d.select_or_deselect_all"
bl_options = {'UNDO'}
- extend = BoolProperty(
+ extend: BoolProperty(
name="Extend",
description="Extend selection instead of deselecting everything first",
default=False,
)
- toggle = BoolProperty(
+ toggle: BoolProperty(
name="Toggle",
description="Toggle the selection",
default=False,
)
- deselect = BoolProperty(
+ deselect: BoolProperty(
name="Deselect",
description="Remove from selection",
default=False,
)
- center = BoolProperty(
+ center: BoolProperty(
name="Center",
description="Use the object center when selecting, in editmode used to extend object selection",
default=False,
)
- enumerate = BoolProperty(
+ enumerate: BoolProperty(
name="Enumerate",
description="List objects under the mouse (object mode only)",
default=False,
)
- object = BoolProperty(
+ object: BoolProperty(
name="Object",
description="Use object selection (editmode only)",
default=False,
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 5b12f6196a4..fe367973323 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -19,13 +19,17 @@
# <pep8 compliant>
import bpy
-from bpy.types import Operator
+from bpy.types import (
+ Operator,
+ OperatorFileListElement
+)
from bpy.props import (
BoolProperty,
EnumProperty,
FloatProperty,
IntProperty,
StringProperty,
+ CollectionProperty,
)
from bpy.app.translations import pgettext_tip as tip_
@@ -55,6 +59,15 @@ rna_relative_prop = BoolProperty(
default=False,
)
+rna_space_type_prop = EnumProperty(
+ name="Type",
+ items=tuple(
+ (e.identifier, e.name, "", e. value)
+ for e in bpy.types.Space.bl_rna.properties["type"].enum_items
+ ),
+ default='EMPTY',
+)
+
def context_path_validate(context, data_path):
try:
@@ -149,12 +162,12 @@ class BRUSH_OT_active_index_set(Operator):
bl_idname = "brush.active_index_set"
bl_label = "Set Brush Number"
- mode = StringProperty(
+ mode: StringProperty(
name="Mode",
description="Paint mode to set brush for",
maxlen=1024,
)
- index = IntProperty(
+ index: IntProperty(
name="Number",
description="Brush number",
)
@@ -186,8 +199,8 @@ class WM_OT_context_set_boolean(Operator):
bl_label = "Context Set Boolean"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = BoolProperty(
+ data_path: rna_path_prop
+ value: BoolProperty(
name="Value",
description="Assignment value",
default=True,
@@ -202,13 +215,13 @@ class WM_OT_context_set_int(Operator): # same as enum
bl_label = "Context Set"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = IntProperty(
+ data_path: rna_path_prop
+ value: IntProperty(
name="Value",
description="Assign value",
default=0,
)
- relative = rna_relative_prop
+ relative: rna_relative_prop
execute = execute_context_assign
@@ -219,8 +232,8 @@ class WM_OT_context_scale_float(Operator):
bl_label = "Context Scale Float"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = FloatProperty(
+ data_path: rna_path_prop
+ value: FloatProperty(
name="Value",
description="Assign value",
default=1.0,
@@ -247,13 +260,13 @@ class WM_OT_context_scale_int(Operator):
bl_label = "Context Scale Int"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = FloatProperty(
+ data_path: rna_path_prop
+ value: FloatProperty(
name="Value",
description="Assign value",
default=1.0,
)
- always_step = BoolProperty(
+ always_step: BoolProperty(
name="Always Step",
description="Always adjust the value by a minimum of 1 when 'value' is not 1.0",
default=True,
@@ -290,13 +303,13 @@ class WM_OT_context_set_float(Operator): # same as enum
bl_label = "Context Set Float"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = FloatProperty(
+ data_path: rna_path_prop
+ value: FloatProperty(
name="Value",
description="Assignment value",
default=0.0,
)
- relative = rna_relative_prop
+ relative: rna_relative_prop
execute = execute_context_assign
@@ -307,8 +320,8 @@ class WM_OT_context_set_string(Operator): # same as enum
bl_label = "Context Set String"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = StringProperty(
+ data_path: rna_path_prop
+ value: StringProperty(
name="Value",
description="Assign value",
maxlen=1024,
@@ -323,8 +336,8 @@ class WM_OT_context_set_enum(Operator):
bl_label = "Context Set Enum"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = StringProperty(
+ data_path: rna_path_prop
+ value: StringProperty(
name="Value",
description="Assignment value (as a string)",
maxlen=1024,
@@ -339,8 +352,8 @@ class WM_OT_context_set_value(Operator):
bl_label = "Context Set Value"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = StringProperty(
+ data_path: rna_path_prop
+ value: StringProperty(
name="Value",
description="Assignment value (as a string)",
maxlen=1024,
@@ -360,7 +373,7 @@ class WM_OT_context_toggle(Operator):
bl_label = "Context Toggle"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
+ data_path: rna_path_prop
def execute(self, context):
data_path = self.data_path
@@ -379,13 +392,13 @@ class WM_OT_context_toggle_enum(Operator):
bl_label = "Context Toggle Values"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value_1 = StringProperty(
+ data_path: rna_path_prop
+ value_1: StringProperty(
name="Value",
description="Toggle enum",
maxlen=1024,
)
- value_2 = StringProperty(
+ value_2: StringProperty(
name="Value",
description="Toggle enum",
maxlen=1024,
@@ -418,9 +431,9 @@ class WM_OT_context_cycle_int(Operator):
bl_label = "Context Int Cycle"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- reverse = rna_reverse_prop
- wrap = rna_wrap_prop
+ data_path: rna_path_prop
+ reverse: rna_reverse_prop
+ wrap: rna_wrap_prop
def execute(self, context):
data_path = self.data_path
@@ -454,9 +467,9 @@ class WM_OT_context_cycle_enum(Operator):
bl_label = "Context Enum Cycle"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- reverse = rna_reverse_prop
- wrap = rna_wrap_prop
+ data_path: rna_path_prop
+ reverse: rna_reverse_prop
+ wrap: rna_wrap_prop
def execute(self, context):
data_path = self.data_path
@@ -511,8 +524,8 @@ class WM_OT_context_cycle_array(Operator):
bl_label = "Context Array Cycle"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- reverse = rna_reverse_prop
+ data_path: rna_path_prop
+ reverse: rna_reverse_prop
def execute(self, context):
data_path = self.data_path
@@ -536,7 +549,8 @@ class WM_OT_context_menu_enum(Operator):
bl_idname = "wm.context_menu_enum"
bl_label = "Context Enum Menu"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
+
+ data_path: rna_path_prop
def execute(self, context):
data_path = self.data_path
@@ -562,7 +576,8 @@ class WM_OT_context_pie_enum(Operator):
bl_idname = "wm.context_pie_enum"
bl_label = "Context Enum Pie"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
+
+ data_path: rna_path_prop
def invoke(self, context, event):
wm = context.window_manager
@@ -589,12 +604,13 @@ class WM_OT_operator_pie_enum(Operator):
bl_idname = "wm.operator_pie_enum"
bl_label = "Operator Enum Pie"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = StringProperty(
+
+ data_path: StringProperty(
name="Operator",
description="Operator name (in python as string)",
maxlen=1024,
)
- prop_string = StringProperty(
+ prop_string: StringProperty(
name="Property",
description="Property name (as a string)",
maxlen=1024,
@@ -633,8 +649,8 @@ class WM_OT_context_set_id(Operator):
bl_label = "Set Library ID"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path_prop
- value = StringProperty(
+ data_path: rna_path_prop
+ value: StringProperty(
name="Value",
description="Assign value",
maxlen=1024,
@@ -684,10 +700,10 @@ class WM_OT_context_collection_boolean_set(Operator):
bl_label = "Context Collection Boolean Set"
bl_options = {'UNDO', 'REGISTER', 'INTERNAL'}
- data_path_iter = data_path_iter
- data_path_item = data_path_item
+ data_path_iter: data_path_iter
+ data_path_item: data_path_item
- type = EnumProperty(
+ type: EnumProperty(
name="Type",
items=(('TOGGLE', "Toggle", ""),
('ENABLE', "Enable", ""),
@@ -743,22 +759,22 @@ class WM_OT_context_modal_mouse(Operator):
bl_label = "Context Modal Mouse"
bl_options = {'GRAB_CURSOR', 'BLOCKING', 'UNDO', 'INTERNAL'}
- data_path_iter = data_path_iter
- data_path_item = data_path_item
- header_text = StringProperty(
+ data_path_iter: data_path_iter
+ data_path_item: data_path_item
+ header_text: StringProperty(
name="Header Text",
description="Text to display in header during scale",
)
- input_scale = FloatProperty(
+ input_scale: FloatProperty(
description="Scale the mouse movement by this value before applying the delta",
default=0.01,
)
- invert = BoolProperty(
+ invert: BoolProperty(
description="Invert the mouse input",
default=False,
)
- initial_x = IntProperty(options={'HIDDEN'})
+ initial_x: IntProperty(options={'HIDDEN'})
def _values_store(self, context):
data_path_iter = self.data_path_iter
@@ -851,7 +867,7 @@ class WM_OT_url_open(Operator):
bl_label = ""
bl_options = {'INTERNAL'}
- url = StringProperty(
+ url: StringProperty(
name="URL",
description="URL to open",
)
@@ -868,7 +884,7 @@ class WM_OT_path_open(Operator):
bl_label = ""
bl_options = {'INTERNAL'}
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
options={'SKIP_SAVE'},
)
@@ -983,7 +999,7 @@ class WM_OT_doc_view_manual(Operator):
bl_idname = "wm.doc_view_manual"
bl_label = "View Manual"
- doc_id = doc_id
+ doc_id: doc_id
@staticmethod
def _find_reference(rna_id, url_mapping, verbose=True):
@@ -1037,7 +1053,7 @@ class WM_OT_doc_view(Operator):
bl_idname = "wm.doc_view"
bl_label = "View Documentation"
- doc_id = doc_id
+ doc_id: doc_id
if bpy.app.version_cycle == "release":
_prefix = ("https://docs.blender.org/api/blender_python_api_current")
else:
@@ -1089,6 +1105,11 @@ rna_use_soft_limits = BoolProperty(
name="Use Soft Limits",
)
+rna_is_overridable_static = BoolProperty(
+ name="Is Statically Overridable",
+ default=False,
+)
+
class WM_OT_properties_edit(Operator):
bl_idname = "wm.properties_edit"
@@ -1096,15 +1117,16 @@ class WM_OT_properties_edit(Operator):
# register only because invoke_props_popup requires.
bl_options = {'REGISTER', 'INTERNAL'}
- data_path = rna_path
- property = rna_property
- value = rna_value
- min = rna_min
- max = rna_max
- use_soft_limits = rna_use_soft_limits
- soft_min = rna_min
- soft_max = rna_max
- description = StringProperty(
+ data_path: rna_path
+ property: rna_property
+ value: rna_value
+ min: rna_min
+ max: rna_max
+ use_soft_limits: rna_use_soft_limits
+ is_overridable_static: rna_is_overridable_static
+ soft_min: rna_min
+ soft_max: rna_max
+ description: StringProperty(
name="Tooltip",
)
@@ -1154,6 +1176,9 @@ class WM_OT_properties_edit(Operator):
# print(exec_str)
exec(exec_str)
+ exec_str = "item.property_overridable_static_set('[\"%s\"]', %s)" % (prop, self.is_overridable_static)
+ exec(exec_str)
+
rna_idprop_ui_prop_update(item, prop)
self._last_prop[:] = [prop]
@@ -1281,7 +1306,9 @@ class WM_OT_properties_edit(Operator):
row.prop(self, "min")
row.prop(self, "max")
- layout.prop(self, "use_soft_limits")
+ row = layout.row()
+ row.prop(self, "use_soft_limits")
+ row.prop(self, "is_overridable_static")
row = layout.row(align=True)
row.enabled = self.use_soft_limits
@@ -1295,7 +1322,7 @@ class WM_OT_properties_add(Operator):
bl_label = "Add Property"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path
+ data_path: rna_path
def execute(self, context):
from rna_prop_ui import (
@@ -1338,7 +1365,7 @@ class WM_OT_properties_context_change(Operator):
bl_label = ""
bl_options = {'INTERNAL'}
- context = StringProperty(
+ context: StringProperty(
name="Context",
maxlen=64,
)
@@ -1354,8 +1381,8 @@ class WM_OT_properties_remove(Operator):
bl_label = "Remove Property"
bl_options = {'UNDO', 'INTERNAL'}
- data_path = rna_path
- property = rna_property
+ data_path: rna_path
+ property: rna_property
def execute(self, context):
from rna_prop_ui import (
@@ -1376,7 +1403,7 @@ class WM_OT_keyconfig_activate(Operator):
bl_idname = "wm.keyconfig_activate"
bl_label = "Activate Keyconfig"
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
)
@@ -1411,7 +1438,7 @@ class WM_OT_appconfig_activate(Operator):
bl_idname = "wm.appconfig_activate"
bl_label = "Activate Application Configuration"
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
)
@@ -1436,7 +1463,7 @@ class WM_OT_sysinfo(Operator):
bl_idname = "wm.sysinfo"
bl_label = "Save System Info"
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
options={'SKIP_SAVE'},
)
@@ -1492,54 +1519,6 @@ class WM_OT_copy_prev_settings(Operator):
return {'CANCELLED'}
-class WM_OT_blenderplayer_start(Operator):
- """Launch the blender-player with the current blend-file"""
- bl_idname = "wm.blenderplayer_start"
- bl_label = "Start Game In Player"
-
- def execute(self, context):
- import os
- import sys
- import subprocess
-
- gs = context.scene.game_settings
-
- # these remain the same every execution
- blender_bin_path = bpy.app.binary_path
- blender_bin_dir = os.path.dirname(blender_bin_path)
- ext = os.path.splitext(blender_bin_path)[-1]
- player_path = os.path.join(blender_bin_dir, "blenderplayer" + ext)
- # done static vars
-
- if sys.platform == "darwin":
- player_path = os.path.join(blender_bin_dir, "../../../blenderplayer.app/Contents/MacOS/blenderplayer")
-
- if not os.path.exists(player_path):
- self.report({'ERROR'}, "Player path: %r not found" % player_path)
- return {'CANCELLED'}
-
- filepath = bpy.data.filepath + '~' if bpy.data.is_saved else os.path.join(bpy.app.tempdir, "game.blend")
- bpy.ops.wm.save_as_mainfile('EXEC_DEFAULT', filepath=filepath, copy=True)
-
- # start the command line call with the player path
- args = [player_path]
-
- # handle some UI options as command line arguments
- args.extend([
- "-g", "show_framerate", "=", "%d" % gs.show_framerate_profile,
- "-g", "show_profile", "=", "%d" % gs.show_framerate_profile,
- "-g", "show_properties", "=", "%d" % gs.show_debug_properties,
- "-g", "ignore_deprecation_warnings", "=", "%d" % (not gs.use_deprecation_warnings),
- ])
-
- # finish the call with the path to the blend file
- args.append(filepath)
-
- subprocess.call(args)
- os.remove(filepath)
- return {'FINISHED'}
-
-
class WM_OT_keyconfig_test(Operator):
"""Test key-config for conflicts"""
bl_idname = "wm.keyconfig_test"
@@ -1562,26 +1541,26 @@ class WM_OT_keyconfig_import(Operator):
bl_idname = "wm.keyconfig_import"
bl_label = "Import Key Configuration..."
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
default="keymap.py",
)
- filter_folder = BoolProperty(
+ filter_folder: BoolProperty(
name="Filter folders",
default=True,
options={'HIDDEN'},
)
- filter_text = BoolProperty(
+ filter_text: BoolProperty(
name="Filter text",
default=True,
options={'HIDDEN'},
)
- filter_python = BoolProperty(
+ filter_python: BoolProperty(
name="Filter python",
default=True,
options={'HIDDEN'},
)
- keep_original = BoolProperty(
+ keep_original: BoolProperty(
name="Keep original",
description="Keep original file after copying to configuration folder",
default=True,
@@ -1629,21 +1608,21 @@ class WM_OT_keyconfig_export(Operator):
bl_idname = "wm.keyconfig_export"
bl_label = "Export Key Configuration..."
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
default="keymap.py",
)
- filter_folder = BoolProperty(
+ filter_folder: BoolProperty(
name="Filter folders",
default=True,
options={'HIDDEN'},
)
- filter_text = BoolProperty(
+ filter_text: BoolProperty(
name="Filter text",
default=True,
options={'HIDDEN'},
)
- filter_python = BoolProperty(
+ filter_python: BoolProperty(
name="Filter python",
default=True,
options={'HIDDEN'},
@@ -1660,7 +1639,7 @@ class WM_OT_keyconfig_export(Operator):
wm = context.window_manager
- keyconfig_utils.keyconfig_export(
+ keyconfig_utils.keyconfig_export_as_data(
wm,
wm.keyconfigs.active,
self.filepath,
@@ -1679,7 +1658,7 @@ class WM_OT_keymap_restore(Operator):
bl_idname = "wm.keymap_restore"
bl_label = "Restore Key Map(s)"
- all = BoolProperty(
+ all: BoolProperty(
name="All Keymaps",
description="Restore all keymaps to default",
)
@@ -1702,7 +1681,7 @@ class WM_OT_keyitem_restore(Operator):
bl_idname = "wm.keyitem_restore"
bl_label = "Restore Key Map Item"
- item_id = IntProperty(
+ item_id: IntProperty(
name="Item Identifier",
description="Identifier of the item to remove",
)
@@ -1749,7 +1728,7 @@ class WM_OT_keyitem_remove(Operator):
bl_idname = "wm.keyitem_remove"
bl_label = "Remove Key Map Item"
- item_id = IntProperty(
+ item_id: IntProperty(
name="Item Identifier",
description="Identifier of the item to remove",
)
@@ -1817,7 +1796,7 @@ class WM_OT_addon_enable(Operator):
bl_idname = "wm.addon_enable"
bl_label = "Enable Add-on"
- module = StringProperty(
+ module: StringProperty(
name="Module",
description="Module name of the add-on to enable",
)
@@ -1863,7 +1842,7 @@ class WM_OT_addon_disable(Operator):
bl_idname = "wm.addon_disable"
bl_label = "Disable Add-on"
- module = StringProperty(
+ module: StringProperty(
name="Module",
description="Module name of the add-on to disable",
)
@@ -1887,25 +1866,56 @@ class WM_OT_addon_disable(Operator):
return {'FINISHED'}
+class WM_OT_owner_enable(Operator):
+ """Enable workspace owner ID"""
+ bl_idname = "wm.owner_enable"
+ bl_label = "Enable Add-on"
+
+ owner_id: StringProperty(
+ name="UI Tag",
+ )
+
+ def execute(self, context):
+ workspace = context.workspace
+ workspace.owner_ids.new(self.owner_id)
+ return {'FINISHED'}
+
+
+class WM_OT_owner_disable(Operator):
+ """Enable workspace owner ID"""
+ bl_idname = "wm.owner_disable"
+ bl_label = "Disable UI Tag"
+
+ owner_id: StringProperty(
+ name="UI Tag",
+ )
+
+ def execute(self, context):
+ workspace = context.workspace
+ owner_id = workspace.owner_ids[self.owner_id]
+ workspace.owner_ids.remove(owner_id)
+ return {'FINISHED'}
+
+
class WM_OT_theme_install(Operator):
"""Load and apply a Blender XML theme file"""
bl_idname = "wm.theme_install"
bl_label = "Install Theme..."
- overwrite = BoolProperty(
+ overwrite: BoolProperty(
name="Overwrite",
description="Remove existing theme file if exists",
default=True,
)
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
)
- filter_folder = BoolProperty(
+ filter_folder: BoolProperty(
name="Filter folders",
default=True,
options={'HIDDEN'},
)
- filter_glob = StringProperty(
+ filter_glob: StringProperty(
default="*.xml",
options={'HIDDEN'},
)
@@ -1969,31 +1979,31 @@ class WM_OT_addon_install(Operator):
bl_idname = "wm.addon_install"
bl_label = "Install Add-on from File..."
- overwrite = BoolProperty(
+ overwrite: BoolProperty(
name="Overwrite",
description="Remove existing add-ons with the same ID",
default=True,
)
- target = EnumProperty(
+ target: EnumProperty(
name="Target Path",
items=(('DEFAULT', "Default", ""),
('PREFS', "User Prefs", "")),
)
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
)
- filter_folder = BoolProperty(
+ filter_folder: BoolProperty(
name="Filter folders",
default=True,
options={'HIDDEN'},
)
- filter_python = BoolProperty(
+ filter_python: BoolProperty(
name="Filter python",
default=True,
options={'HIDDEN'},
)
- filter_glob = StringProperty(
+ filter_glob: StringProperty(
default="*.py;*.zip",
options={'HIDDEN'},
)
@@ -2123,7 +2133,7 @@ class WM_OT_addon_remove(Operator):
bl_idname = "wm.addon_remove"
bl_label = "Remove Add-on"
- module = StringProperty(
+ module: StringProperty(
name="Module",
description="Module name of the add-on to remove",
)
@@ -2183,7 +2193,7 @@ class WM_OT_addon_expand(Operator):
bl_label = ""
bl_options = {'INTERNAL'}
- module = StringProperty(
+ module: StringProperty(
name="Module",
description="Module name of the add-on to expand",
)
@@ -2207,7 +2217,7 @@ class WM_OT_addon_userpref_show(Operator):
bl_label = ""
bl_options = {'INTERNAL'}
- module = StringProperty(
+ module: StringProperty(
name="Module",
description="Module name of the add-on to expand",
)
@@ -2238,21 +2248,21 @@ class WM_OT_app_template_install(Operator):
bl_idname = "wm.app_template_install"
bl_label = "Install Template from File..."
- overwrite = BoolProperty(
+ overwrite: BoolProperty(
name="Overwrite",
description="Remove existing template with the same ID",
default=True,
)
- filepath = StringProperty(
+ filepath: StringProperty(
subtype='FILE_PATH',
)
- filter_folder = BoolProperty(
+ filter_folder: BoolProperty(
name="Filter folders",
default=True,
options={'HIDDEN'},
)
- filter_glob = StringProperty(
+ filter_glob: StringProperty(
default="*.zip",
options={'HIDDEN'},
)
@@ -2332,6 +2342,177 @@ class WM_OT_app_template_install(Operator):
return {'RUNNING_MODAL'}
+class WM_OT_tool_set_by_name(Operator):
+ """Set the tool by name (for keymaps)"""
+ bl_idname = "wm.tool_set_by_name"
+ bl_label = "Set Tool By Name"
+
+ name: StringProperty(
+ name="Text",
+ description="Display name of the tool",
+ )
+ cycle: BoolProperty(
+ name="Cycle",
+ description="Cycle through tools in this group",
+ default=False,
+ options={'SKIP_SAVE'},
+ )
+
+ space_type: rna_space_type_prop
+
+ def execute(self, context):
+ from bl_ui.space_toolsystem_common import (
+ activate_by_name,
+ activate_by_name_or_cycle,
+ )
+
+ if self.properties.is_property_set("space_type"):
+ space_type = self.space_type
+ else:
+ space_type = context.space_data.type
+
+ fn = activate_by_name_or_cycle if self.cycle else activate_by_name
+ if fn(context, space_type, self.name):
+ return {'FINISHED'}
+ else:
+ self.report({'WARNING'}, f"Tool {self.name!r} not found.")
+ return {'CANCELLED'}
+
+
+class WM_OT_toolbar(Operator):
+ bl_idname = "wm.toolbar"
+ bl_label = "Toolbar"
+
+ def execute(self, context):
+ from bl_ui.space_toolsystem_common import (
+ ToolSelectPanelHelper,
+ keymap_from_context,
+ )
+ space_type = context.space_data.type
+
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is None:
+ self.report({'WARNING'}, f"Toolbar not found for {space_type!r}")
+ return {'CANCELLED'}
+
+ wm = context.window_manager
+ keymap = keymap_from_context(context, space_type)
+
+ def draw_menu(popover, context):
+ layout = popover.layout
+
+ layout.operator_context = 'INVOKE_DEFAULT'
+ layout.operator("wm.search_menu", text="Search Commands...", icon='VIEWZOOM')
+
+ cls.draw_cls(layout, context, detect_layout=False, scale_y=1.0)
+
+ wm.popover(draw_menu, ui_units_x=8, keymap=keymap)
+ return {'FINISHED'}
+
+
+# Studio Light operations
+class WM_OT_studiolight_install(Operator):
+ """Install a user defined studio light"""
+ bl_idname = "wm.studiolight_install"
+ bl_label = "Install Custom Studio Light"
+
+ files: CollectionProperty(
+ name="File Path",
+ type=OperatorFileListElement,
+ )
+ directory: StringProperty(
+ subtype='DIR_PATH',
+ )
+ filter_folder: BoolProperty(
+ name="Filter folders",
+ default=True,
+ options={'HIDDEN'},
+ )
+ filter_glob: StringProperty(
+ default="*.png;*.jpg;*.hdr;*.exr",
+ options={'HIDDEN'},
+ )
+ orientation: EnumProperty(
+ items=(
+ ("MATCAP", "MatCap", ""),
+ ("WORLD", "World", ""),
+ ("CAMERA", "Camera", ""),
+ )
+ )
+
+ def execute(self, context):
+ import traceback
+ import shutil
+ import pathlib
+ userpref = context.user_preferences
+
+ filepaths = [pathlib.Path(self.directory, e.name) for e in self.files]
+ path_studiolights = bpy.utils.user_resource('DATAFILES')
+
+ if not path_studiolights:
+ self.report({'ERROR'}, "Failed to get Studio Light path")
+ return {'CANCELLED'}
+
+ path_studiolights = pathlib.Path(path_studiolights, "studiolights", self.orientation.lower())
+ if not path_studiolights.exists():
+ try:
+ path_studiolights.mkdir(parents=True, exist_ok=True)
+ except:
+ traceback.print_exc()
+
+ for filepath in filepaths:
+ shutil.copy(str(filepath), str(path_studiolights))
+ userpref.studio_lights.new(str(path_studiolights.joinpath(filepath.name)), self.orientation)
+
+ # print message
+ msg = (
+ tip_("StudioLight Installed %r into %r") %
+ (", ".join(str(x.name) for x in self.files), str(path_studiolights))
+ )
+ print(msg)
+ self.report({'INFO'}, msg)
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ wm.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+
+class WM_OT_studiolight_uninstall(Operator):
+ bl_idname = 'wm.studiolight_uninstall'
+ bl_label = "Uninstall Studio Light"
+ index: bpy.props.IntProperty()
+
+ def _remove_path(self, path):
+ if path.exists():
+ path.unlink()
+
+ def execute(self, context):
+ import pathlib
+ userpref = context.user_preferences
+ for studio_light in userpref.studio_lights:
+ if studio_light.index == self.index:
+ self._remove_path(pathlib.Path(studio_light.path))
+ self._remove_path(pathlib.Path(studio_light.path_irr_cache))
+ self._remove_path(pathlib.Path(studio_light.path_sh_cache))
+ userpref.studio_lights.remove(studio_light)
+ return {'FINISHED'}
+ return {'CANCELLED'}
+
+
+class WM_OT_studiolight_userpref_show(Operator):
+ """Show light user preferences"""
+ bl_idname = "wm.studiolight_userpref_show"
+ bl_label = ""
+ bl_options = {'INTERNAL'}
+
+ def execute(self, context):
+ context.user_preferences.active_section = 'LIGHTS'
+ bpy.ops.screen.userpref_show('INVOKE_DEFAULT')
+ return {'FINISHED'}
+
+
classes = (
BRUSH_OT_active_index_set,
WM_OT_addon_disable,
@@ -2344,7 +2525,6 @@ classes = (
WM_OT_app_template_install,
WM_OT_appconfig_activate,
WM_OT_appconfig_default,
- WM_OT_blenderplayer_start,
WM_OT_context_collection_boolean_set,
WM_OT_context_cycle_array,
WM_OT_context_cycle_enum,
@@ -2384,5 +2564,12 @@ classes = (
WM_OT_properties_remove,
WM_OT_sysinfo,
WM_OT_theme_install,
+ WM_OT_owner_disable,
+ WM_OT_owner_enable,
WM_OT_url_open,
+ WM_OT_studiolight_install,
+ WM_OT_studiolight_uninstall,
+ WM_OT_studiolight_userpref_show,
+ WM_OT_tool_set_by_name,
+ WM_OT_toolbar,
)
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index f98074cdf0b..51ba45cdcd7 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -34,13 +34,14 @@ _modules = [
"properties_data_camera",
"properties_data_curve",
"properties_data_empty",
- "properties_data_lamp",
+ "properties_data_light",
"properties_data_lattice",
"properties_data_mesh",
"properties_data_metaball",
"properties_data_modifier",
+ "properties_data_lightprobe",
"properties_data_speaker",
- "properties_game",
+ "properties_data_workspace",
"properties_mask_common",
"properties_material",
"properties_object",
@@ -57,10 +58,17 @@ _modules = [
"properties_physics_smoke",
"properties_physics_softbody",
"properties_render",
- "properties_render_layer",
+ "properties_view_layer",
"properties_scene",
"properties_texture",
"properties_world",
+
+ # Generic Space Modules
+ #
+ # Depends on DNA_WORKSPACE_TOOL (C define).
+ "space_toolsystem_common",
+ "space_toolsystem_toolbar",
+
"space_clip",
"space_console",
"space_dopesheet",
@@ -68,14 +76,15 @@ _modules = [
"space_graph",
"space_image",
"space_info",
- "space_logic",
"space_nla",
"space_node",
"space_outliner",
"space_properties",
"space_sequencer",
+ "space_statusbar",
"space_text",
"space_time",
+ "space_topbar",
"space_userpref",
"space_view3d",
"space_view3d_toolbar",
diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index 9782d5a072c..901e15c181a 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -37,27 +37,26 @@ class MotionPathButtonsPanel:
mps = avs.motion_path
# Display Range
- layout.row().prop(mps, "type", expand=True)
+ layout.use_property_split = True
+ layout.row().prop(mps, "type")
- split = layout.split()
+ col = layout.column()
- col = split.column()
- col.label(text="Display Range:")
sub = col.column(align=True)
if mps.type == 'CURRENT_FRAME':
- sub.prop(mps, "frame_before", text="Before")
+ sub.prop(mps, "frame_before", text="Frame Range Before")
sub.prop(mps, "frame_after", text="After")
elif mps.type == 'RANGE':
- sub.prop(mps, "frame_start", text="Start")
+ sub.prop(mps, "frame_start", text="Frame Range Start")
sub.prop(mps, "frame_end", text="End")
sub.prop(mps, "frame_step", text="Step")
- col = split.column()
+ col = layout.column(align=True)
if bones:
col.label(text="Cache for Bone:")
else:
- col.label(text="Cache:")
+ col.label(text="Cache")
if mpath:
sub = col.column(align=True)
@@ -81,17 +80,15 @@ class MotionPathButtonsPanel:
sub.operator("object.paths_calculate", text="Calculate...", icon='OBJECT_DATA')
# Display Settings
- split = layout.split()
- col = split.column()
- col.label(text="Show:")
+ layout.label(text="Display")
+
+ col = layout.column()
col.prop(mps, "show_frame_numbers", text="Frame Numbers")
if mpath is not None:
col.prop(mpath, "lines", text="Lines")
col.prop(mpath, "line_thickness", text="Thickness")
- col = split.column()
- col.label("")
col.prop(mps, "show_keyframe_highlight", text="Keyframes")
sub = col.column()
sub.enabled = mps.show_keyframe_highlight
@@ -101,11 +98,11 @@ class MotionPathButtonsPanel:
# Customize path
if mpath is not None:
- row = layout.row(align=True)
- row.prop(mpath, "use_custom_color", text="", toggle=True, icon='COLOR')
- sub = row.row(align=True)
+
+ col.prop(mpath, "use_custom_color", text="Custom Color")
+ sub = col.column()
sub.enabled = mpath.use_custom_color
- sub.prop(mpath, "color", text="")
+ sub.prop(mpath, "color")
# FIXME: this panel still needs to be ported so that it will work correctly with animviz
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index c0fa82946e1..6cfc4b6ea3f 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -65,11 +65,6 @@ class DATA_PT_skeleton(ArmatureButtonsPanel, Panel):
col.label(text="Protected Layers:")
col.prop(arm, "layers_protected", text="")
- if context.scene.render.engine == 'BLENDER_GAME':
- col = layout.column()
- col.label(text="Deform:")
- col.prop(arm, "deform_method", expand=True)
-
class DATA_PT_display(ArmatureButtonsPanel, Panel):
bl_label = "Display"
@@ -82,15 +77,13 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel):
layout.row().prop(arm, "draw_type", expand=True)
- split = layout.split()
+ layout.use_property_split = True
- col = split.column()
+ col = layout.column()
col.prop(arm, "show_names", text="Names")
col.prop(arm, "show_axes", text="Axes")
col.prop(arm, "show_bone_custom_shapes", text="Shapes")
-
- col = split.column()
- col.prop(arm, "show_group_colors", text="Colors")
+ col.prop(arm, "show_group_colors", text="Group Colors")
if ob:
col.prop(ob, "show_x_ray", text="X-Ray")
col.prop(arm, "use_deform_delay", text="Delay Refresh")
@@ -154,7 +147,8 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
sub = row.row(align=True)
sub.operator("pose.group_assign", text="Assign")
- sub.operator("pose.group_unassign", text="Remove") # row.operator("pose.bone_group_remove_from", text="Remove")
+ # row.operator("pose.bone_group_remove_from", text="Remove")
+ sub.operator("pose.group_unassign", text="Remove")
sub = row.row(align=True)
sub.operator("pose.group_select", text="Select")
@@ -201,7 +195,11 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
if pose_marker_active is not None:
col.operator("poselib.pose_remove", icon='ZOOMOUT', text="")
- col.operator("poselib.apply_pose", icon='ZOOM_SELECTED', text="").pose_index = poselib.pose_markers.active_index
+ col.operator(
+ "poselib.apply_pose",
+ icon='ZOOM_SELECTED',
+ text="",
+ ).pose_index = poselib.pose_markers.active_index
col.operator("poselib.action_sanitize", icon='HELP', text="") # XXX: put in menu?
@@ -221,21 +219,19 @@ class DATA_PT_ghost(ArmatureButtonsPanel, Panel):
layout.row().prop(arm, "ghost_type", expand=True)
- split = layout.split()
+ layout.use_property_split = True
- col = split.column(align=True)
+ col = layout.column(align=True)
if arm.ghost_type == 'RANGE':
- col.prop(arm, "ghost_frame_start", text="Start")
+ col.prop(arm, "ghost_frame_start", text="Frame Start")
col.prop(arm, "ghost_frame_end", text="End")
col.prop(arm, "ghost_size", text="Step")
elif arm.ghost_type == 'CURRENT_FRAME':
- col.prop(arm, "ghost_step", text="Range")
+ col.prop(arm, "ghost_step", text="Frame Range")
col.prop(arm, "ghost_size", text="Step")
- col = split.column()
- col.label(text="Display:")
- col.prop(arm, "show_only_ghost_selected", text="Selected Only")
+ col.prop(arm, "show_only_ghost_selected", text="Display Selected Only")
class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
@@ -249,6 +245,7 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
itasc = ob.pose.ik_param
@@ -256,34 +253,36 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
layout.prop(ob.pose, "ik_solver")
if itasc:
+ layout.use_property_split = False
layout.row().prop(itasc, "mode", expand=True)
+ layout.use_property_split = True
simulation = (itasc.mode == 'SIMULATION')
if simulation:
- layout.label(text="Reiteration:")
- layout.row().prop(itasc, "reiteration_method", expand=True)
+ layout.prop(itasc, "reiteration_method", expand=False)
- row = layout.row()
- row.active = not simulation or itasc.reiteration_method != 'NEVER'
- row.prop(itasc, "precision")
- row.prop(itasc, "iterations")
+ col = layout.column()
+ col.active = not simulation or itasc.reiteration_method != 'NEVER'
+ col.prop(itasc, "precision")
+ col.prop(itasc, "iterations")
if simulation:
layout.prop(itasc, "use_auto_step")
- row = layout.row()
+ col = layout.column(align=True)
if itasc.use_auto_step:
- row.prop(itasc, "step_min", text="Min")
- row.prop(itasc, "step_max", text="Max")
+ col.prop(itasc, "step_min", text="Steps Min")
+ col.prop(itasc, "step_max", text="Max")
else:
- row.prop(itasc, "step_count")
+ col.prop(itasc, "step_count", text="Steps")
layout.prop(itasc, "solver")
if simulation:
layout.prop(itasc, "feedback")
layout.prop(itasc, "velocity_max")
if itasc.solver == 'DLS':
- row = layout.row()
- row.prop(itasc, "damping_max", text="Damp", slider=True)
- row.prop(itasc, "damping_epsilon", text="Eps", slider=True)
+ col = layout.column()
+ col.separator()
+ col.prop(itasc, "damping_max", text="Damping Max", slider=True)
+ col.prop(itasc, "damping_epsilon", text="Damping Epsilon", slider=True)
from .properties_animviz import (
@@ -329,7 +328,7 @@ class DATA_PT_onion_skinning(OnionSkinButtonsPanel): # , Panel): # inherit from
class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "object.data"
_property_type = bpy.types.Armature
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index 63b5d4f96fc..cc593fbb0a2 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -62,88 +62,63 @@ class BONE_PT_transform(BoneButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
bone = context.bone
+ col = layout.column()
+
if bone and ob:
pchan = ob.pose.bones[bone.name]
-
- row = layout.row()
- col = row.column()
- col.prop(pchan, "location")
col.active = not (bone.parent and bone.use_connect)
- col = row.column()
+ sub = col.row(align=True)
+ sub.prop(pchan, "location")
+ sub.prop(pchan, "lock_location", text="")
+
+ col = layout.column()
if pchan.rotation_mode == 'QUATERNION':
- col.prop(pchan, "rotation_quaternion", text="Rotation")
+ sub = col.row(align=True)
+ sub.prop(pchan, "rotation_quaternion", text="Rotation")
+ subsub = sub.column(align=True)
+ subsub.prop(pchan, "lock_rotation_w", text="")
+ subsub.prop(pchan, "lock_rotation", text="")
elif pchan.rotation_mode == 'AXIS_ANGLE':
# col.label(text="Rotation")
#col.prop(pchan, "rotation_angle", text="Angle")
#col.prop(pchan, "rotation_axis", text="Axis")
- col.prop(pchan, "rotation_axis_angle", text="Rotation")
+ sub = col.row(align=True)
+ sub.prop(pchan, "rotation_axis_angle", text="Rotation")
+ subsub = sub.column(align=True)
+ subsub.prop(pchan, "lock_rotation_w", text="")
+ subsub.prop(pchan, "lock_rotation", text="")
else:
- col.prop(pchan, "rotation_euler", text="Rotation")
+ sub = col.row(align=True)
+ sub.prop(pchan, "rotation_euler", text="Rotation")
+ sub.prop(pchan, "lock_rotation", text="")
- row.column().prop(pchan, "scale")
+ col = layout.column()
+ sub = col.row(align=True)
+ sub.prop(pchan, "scale")
+ sub.prop(pchan, "lock_scale", text="")
- layout.prop(pchan, "rotation_mode")
+ col = layout.column()
+ col.prop(pchan, "rotation_mode")
elif context.edit_bone:
bone = context.edit_bone
- row = layout.row()
- row.column().prop(bone, "head")
- row.column().prop(bone, "tail")
-
- col = row.column()
- sub = col.column(align=True)
- sub.label(text="Roll:")
- sub.prop(bone, "roll", text="")
- sub.label()
- sub.prop(bone, "lock")
-
-
-class BONE_PT_transform_locks(BoneButtonsPanel, Panel):
- bl_label = "Transform Locks"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- ob = context.object
- return ob and ob.mode == 'POSE' and context.bone
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
- bone = context.bone
- pchan = ob.pose.bones[bone.name]
-
- split = layout.split(percentage=0.1)
-
- col = split.column(align=True)
- col.label(text="")
- col.label(text="X:")
- col.label(text="Y:")
- col.label(text="Z:")
-
- col = split.column()
- col.active = not (bone.parent and bone.use_connect)
- col.prop(pchan, "lock_location", text="Location")
-
- col = split.column()
- col.prop(pchan, "lock_rotation", text="Rotation")
-
- col = split.column()
- col.prop(pchan, "lock_scale", text="Scale")
+ col = layout.column()
+ col.prop(bone, "head")
+ col.prop(bone, "tail")
- if pchan.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}:
- row = layout.row()
- row.prop(pchan, "lock_rotations_4d", text="Lock Rotation")
+ col = layout.column()
+ col.prop(bone, "roll")
+ col.prop(bone, "lock")
- sub = row.row()
- sub.active = pchan.lock_rotations_4d
- sub.prop(pchan, "lock_rotation_w", text="W")
+ col = layout.column()
+ col.prop(bone, "tail_radius")
+ col.prop(bone, "envelope_distance")
class BONE_PT_curved(BoneButtonsPanel, Panel):
@@ -166,54 +141,52 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
bbone = bone
layout = self.layout
+ layout.use_property_split = True
+
layout.prop(bone, "bbone_segments", text="Segments")
col = layout.column()
col.active = bone.bbone_segments > 1
- row = col.row()
- sub = row.column(align=True)
- sub.label(text="Curve XY Offsets:")
- sub.prop(bbone, "bbone_curveinx", text="In X")
- sub.prop(bbone, "bbone_curveoutx", text="Out X")
- sub.prop(bbone, "bbone_curveiny", text="In Y")
- sub.prop(bbone, "bbone_curveouty", text="Out Y")
-
- sub = row.column(align=True)
- sub.label("Roll:")
- sub.prop(bbone, "bbone_rollin", text="In")
- sub.prop(bbone, "bbone_rollout", text="Out")
- sub.prop(bone, "use_endroll_as_inroll")
-
- row = col.row()
- sub = row.column(align=True)
- sub.label(text="Scale:")
- sub.prop(bbone, "bbone_scalein", text="In")
- sub.prop(bbone, "bbone_scaleout", text="Out")
-
- sub = row.column(align=True)
- sub.label("Easing:")
- sub.prop(bbone, "bbone_easein", text="In")
- sub.prop(bbone, "bbone_easeout", text="Out")
+ col = layout.column(align=True)
+ col.prop(bbone, "bbone_curveinx", text="Curve In X")
+ col.prop(bbone, "bbone_curveiny", text="In Y")
+
+ col = layout.column(align=True)
+ col.prop(bbone, "bbone_curveoutx", text="Curve Out X")
+ col.prop(bbone, "bbone_curveouty", text="Out Y")
+
+ col = layout.column(align=True)
+ col.prop(bbone, "bbone_rollin", text="Roll In")
+ col.prop(bbone, "bbone_rollout", text="Out")
+ col.prop(bone, "use_endroll_as_inroll")
+
+ col = layout.column(align=True)
+ col.prop(bbone, "bbone_scalein", text="Scale In")
+ col.prop(bbone, "bbone_scaleout", text="Out")
+
+ col = layout.column(align=True)
+ col.prop(bbone, "bbone_easein", text="Ease In")
+ col.prop(bbone, "bbone_easeout", text="Out")
if pchan:
layout.separator()
col = layout.column()
+ col.use_property_split = False
col.prop(pchan, "use_bbone_custom_handles")
- row = col.row()
- row.active = pchan.use_bbone_custom_handles
+ col = layout.column(align=True)
+ col.active = pchan.use_bbone_custom_handles
+ col.use_property_split = True
- sub = row.column(align=True)
- sub.label(text="In:")
- sub.prop_search(pchan, "bbone_custom_handle_start", ob.pose, "bones", text="")
- sub.prop(pchan, "use_bbone_relative_start_handle", text="Relative")
+ sub = col.column()
+ sub.prop_search(pchan, "bbone_custom_handle_start", ob.pose, "bones", text="Custom Handle Start")
+ sub.prop_search(pchan, "bbone_custom_handle_end", ob.pose, "bones", text="End")
- sub = row.column(align=True)
- sub.label(text="Out:")
- sub.prop_search(pchan, "bbone_custom_handle_end", ob.pose, "bones", text="")
- sub.prop(pchan, "use_bbone_relative_end_handle", text="Relative")
+ sub = col.column(align=True)
+ sub.prop(pchan, "use_bbone_relative_start_handle", text="Relative Handle Start")
+ sub.prop(pchan, "use_bbone_relative_end_handle", text="End")
class BONE_PT_relations(BoneButtonsPanel, Panel):
@@ -221,6 +194,7 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
bone = context.bone
@@ -232,26 +206,22 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
elif bone is None:
bone = context.edit_bone
- split = layout.split()
-
- col = split.column()
- col.label(text="Layers:")
+ col = layout.column()
+ col.use_property_split = False
col.prop(bone, "layers", text="")
+ col.use_property_split = True
+ col = layout.column()
col.separator()
- if ob and pchan:
- col.label(text="Bone Group:")
- col.prop_search(pchan, "bone_group", ob.pose, "bone_groups", text="")
- col.label(text="Object Children:")
- col.prop(bone, "use_relative_parent")
-
- col = split.column()
- col.label(text="Parent:")
if context.bone:
- col.prop(bone, "parent", text="")
+ col.prop(bone, "parent")
else:
- col.prop_search(bone, "parent", arm, "edit_bones", text="")
+ col.prop_search(bone, "parent", arm, "edit_bones")
+
+ if ob and pchan:
+ col.prop(bone, "use_relative_parent")
+ col.prop_search(pchan, "bone_group", ob.pose, "bone_groups", text="Bone Group")
sub = col.column()
sub.active = (bone.parent is not None)
@@ -274,6 +244,7 @@ class BONE_PT_display(BoneButtonsPanel, Panel):
# note. this works ok in edit-mode but isn't
# all that useful so disabling for now.
layout = self.layout
+ layout.use_property_split = True
ob = context.object
bone = context.bone
@@ -285,23 +256,20 @@ class BONE_PT_display(BoneButtonsPanel, Panel):
bone = context.edit_bone
if bone:
- split = layout.split()
- col = split.column()
+ col = layout.column()
col.prop(bone, "hide", text="Hide")
sub = col.column()
sub.active = bool(pchan and pchan.custom_shape)
sub.prop(bone, "show_wire", text="Wireframe")
if pchan:
- col = split.column()
-
- col.label(text="Custom Shape:")
- col.prop(pchan, "custom_shape", text="")
+ col = layout.column()
+ col.prop(pchan, "custom_shape")
if pchan.custom_shape:
col.prop(pchan, "use_custom_shape_bone_size", text="Bone Size")
col.prop(pchan, "custom_shape_scale", text="Scale")
- col.prop_search(pchan, "custom_shape_transform", ob.pose, "bones", text="At")
+ col.prop_search(pchan, "custom_shape_transform", ob.pose, "bones")
class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
@@ -315,80 +283,82 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
bone = context.bone
pchan = ob.pose.bones[bone.name]
- row = layout.row()
-
active = pchan.is_in_ik_chain
- split = layout.split(percentage=0.25)
- split.prop(pchan, "lock_ik_x", text="X")
- split.active = active
- row = split.row()
- row.prop(pchan, "ik_stiffness_x", text="Stiffness", slider=True)
- row.active = pchan.lock_ik_x is False and active
+ col = layout.column()
+ col.prop(pchan, "ik_stretch", slider=True)
+ col.active = active
+
+ layout.separator()
+
+ col = layout.column(align=True)
- split = layout.split(percentage=0.25)
- sub = split.row()
+ col.prop(pchan, "lock_ik_x", text="Lock IK X")
+ col.prop(pchan, "lock_ik_y", text="Y")
+ col.prop(pchan, "lock_ik_z", text="Z")
- sub.prop(pchan, "use_ik_limit_x", text="Limit")
+ col = layout.column(align=True)
+
+ sub = col.column(align=True)
sub.active = pchan.lock_ik_x is False and active
- sub = split.row(align=True)
- sub.prop(pchan, "ik_min_x", text="")
- sub.prop(pchan, "ik_max_x", text="")
- sub.active = pchan.lock_ik_x is False and pchan.use_ik_limit_x and active
+ sub.prop(pchan, "ik_stiffness_x", text="Stiffness X", slider=True)
+ sub = col.column(align=True)
+ sub.active = pchan.lock_ik_y is False and active
+ sub.prop(pchan, "ik_stiffness_y", text="Y", slider=True)
+ sub = col.column(align=True)
+ sub.active = pchan.lock_ik_z is False and active
+ sub.prop(pchan, "ik_stiffness_z", text="Z", slider=True)
+
+ col = layout.column(align=True)
- split = layout.split(percentage=0.25)
- split.prop(pchan, "lock_ik_y", text="Y")
- split.active = active
- row = split.row()
- row.prop(pchan, "ik_stiffness_y", text="Stiffness", slider=True)
- row.active = pchan.lock_ik_y is False and active
+ sub = col.column()
+ sub.active = pchan.lock_ik_x is False and active
+ sub.prop(pchan, "use_ik_limit_x", text="Limit X")
- split = layout.split(percentage=0.25)
- sub = split.row()
+ sub = col.column(align=True)
+ sub.active = pchan.lock_ik_x is False and pchan.use_ik_limit_x and active
+ sub.prop(pchan, "ik_min_x", text="Min")
+ sub.prop(pchan, "ik_max_x", text="Max")
+
+ col.separator()
- sub.prop(pchan, "use_ik_limit_y", text="Limit")
+ sub = col.column()
sub.active = pchan.lock_ik_y is False and active
+ sub.prop(pchan, "use_ik_limit_y", text="Limit Y")
- sub = split.row(align=True)
- sub.prop(pchan, "ik_min_y", text="")
- sub.prop(pchan, "ik_max_y", text="")
+ sub = col.column(align=True)
sub.active = pchan.lock_ik_y is False and pchan.use_ik_limit_y and active
+ sub.prop(pchan, "ik_min_y", text="Min")
+ sub.prop(pchan, "ik_max_y", text="Max")
- split = layout.split(percentage=0.25)
- split.prop(pchan, "lock_ik_z", text="Z")
- split.active = active
- sub = split.row()
- sub.prop(pchan, "ik_stiffness_z", text="Stiffness", slider=True)
- sub.active = pchan.lock_ik_z is False and active
-
- split = layout.split(percentage=0.25)
- sub = split.row()
+ col.separator()
- sub.prop(pchan, "use_ik_limit_z", text="Limit")
+ sub = col.column()
sub.active = pchan.lock_ik_z is False and active
- sub = split.row(align=True)
- sub.prop(pchan, "ik_min_z", text="")
- sub.prop(pchan, "ik_max_z", text="")
+ sub.prop(pchan, "use_ik_limit_z", text="Limit Z")
+
+ sub = col.column(align=True)
sub.active = pchan.lock_ik_z is False and pchan.use_ik_limit_z and active
+ sub.prop(pchan, "ik_min_z", text="Min")
+ sub.prop(pchan, "ik_max_z", text="Max")
- split = layout.split(percentage=0.25)
- split.label(text="Stretch:")
- sub = split.row()
- sub.prop(pchan, "ik_stretch", text="", slider=True)
- sub.active = active
+ col.separator()
if ob.pose.ik_solver == 'ITASC':
- split = layout.split()
- col = split.column()
+
+ col = layout.column()
col.prop(pchan, "use_ik_rotation_control", text="Control Rotation")
col.active = active
- col = split.column()
- col.prop(pchan, "ik_rotation_weight", text="Weight", slider=True)
+
+ col = layout.column()
+
+ col.prop(pchan, "ik_rotation_weight", text="IK Rotation Weight", slider=True)
col.active = active
# not supported yet
#row = layout.row()
@@ -410,6 +380,7 @@ class BONE_PT_deform(BoneButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
bone = context.bone
@@ -418,22 +389,20 @@ class BONE_PT_deform(BoneButtonsPanel, Panel):
layout.active = bone.use_deform
- row = layout.row()
+ col = layout.column()
+ col.prop(bone, "envelope_distance", text="Envelope Distance")
+ col.prop(bone, "envelope_weight", text="Envelope Weight")
+ col.prop(bone, "use_envelope_multiply", text="Envelope Multiply")
- col = row.column(align=True)
- col.label(text="Envelope:")
- col.prop(bone, "envelope_distance", text="Distance")
- col.prop(bone, "envelope_weight", text="Weight")
- col.prop(bone, "use_envelope_multiply", text="Multiply")
+ col.separator()
- col = row.column(align=True)
- col.label(text="Envelope Radius:")
- col.prop(bone, "head_radius", text="Head")
+ col = layout.column(align=True)
+ col.prop(bone, "head_radius", text="Radius Head")
col.prop(bone, "tail_radius", text="Tail")
class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_property_type = bpy.types.Bone, bpy.types.EditBone, bpy.types.PoseBone
@property
@@ -448,7 +417,6 @@ class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, Panel):
classes = (
BONE_PT_context_bone,
BONE_PT_transform,
- BONE_PT_transform_locks,
BONE_PT_curved,
BONE_PT_relations,
BONE_PT_display,
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 14286045704..3b5f21d616e 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -20,6 +20,7 @@
import bpy
from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
+from bl_operators.presets import PresetMenu
class CameraButtonsPanel:
@@ -29,30 +30,30 @@ class CameraButtonsPanel:
@classmethod
def poll(cls, context):
- engine = context.scene.render.engine
+ engine = context.engine
return context.camera and (engine in cls.COMPAT_ENGINES)
-class CAMERA_MT_presets(Menu):
+class CAMERA_PT_presets(PresetMenu):
bl_label = "Camera Presets"
preset_subdir = "camera"
preset_operator = "script.execute_preset"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- draw = Menu.draw_preset
+ preset_add_operator = "camera.preset_add"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
-class SAFE_AREAS_MT_presets(Menu):
+class SAFE_AREAS_PT_presets(PresetMenu):
bl_label = "Camera Presets"
preset_subdir = "safe_areas"
preset_operator = "script.execute_preset"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- draw = Menu.draw_preset
+ preset_add_operator = "safe_areas.preset_add"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -72,72 +73,70 @@ class DATA_PT_context_camera(CameraButtonsPanel, Panel):
class DATA_PT_lens(CameraButtonsPanel, Panel):
bl_label = "Lens"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
cam = context.camera
- layout.row().prop(cam, "type", expand=True)
+ layout.prop(cam, "type")
- split = layout.split()
+ col = layout.column()
+ col.separator()
- col = split.column()
if cam.type == 'PERSP':
- row = col.row()
+ col = layout.column()
if cam.lens_unit == 'MILLIMETERS':
- row.prop(cam, "lens")
+ col.prop(cam, "lens")
elif cam.lens_unit == 'FOV':
row.prop(cam, "angle")
- row.prop(cam, "lens_unit", text="")
+ col.prop(cam, "lens_unit")
elif cam.type == 'ORTHO':
col.prop(cam, "ortho_scale")
elif cam.type == 'PANO':
- engine = context.scene.render.engine
+ engine = context.engine
if engine == 'CYCLES':
ccam = cam.cycles
- col.prop(ccam, "panorama_type", text="Type")
+ col.prop(ccam, "panorama_type")
if ccam.panorama_type == 'FISHEYE_EQUIDISTANT':
col.prop(ccam, "fisheye_fov")
elif ccam.panorama_type == 'FISHEYE_EQUISOLID':
- row = layout.row()
- row.prop(ccam, "fisheye_lens", text="Lens")
- row.prop(ccam, "fisheye_fov")
+ col.prop(ccam, "fisheye_lens", text="Lens")
+ col.prop(ccam, "fisheye_fov")
elif ccam.panorama_type == 'EQUIRECTANGULAR':
- row = layout.row()
- sub = row.column(align=True)
- sub.prop(ccam, "latitude_min")
- sub.prop(ccam, "latitude_max")
- sub = row.column(align=True)
- sub.prop(ccam, "longitude_min")
- sub.prop(ccam, "longitude_max")
- elif engine == 'BLENDER_RENDER':
- row = col.row()
+ sub = col.column(align=True)
+ sub.prop(ccam, "latitude_min", text="Latitute Min")
+ sub.prop(ccam, "latitude_max", text="Max")
+ sub = col.column(align=True)
+ sub.prop(ccam, "longitude_min", text="Longiture Min")
+ sub.prop(ccam, "longitude_max", text="Max")
+ elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE'}:
if cam.lens_unit == 'MILLIMETERS':
- row.prop(cam, "lens")
+ col.prop(cam, "lens")
elif cam.lens_unit == 'FOV':
- row.prop(cam, "angle")
- row.prop(cam, "lens_unit", text="")
+ col.prop(cam, "angle")
+ col.prop(cam, "lens_unit")
- split = layout.split()
+ col = layout.column()
+ col.separator()
- col = split.column(align=True)
- col.label(text="Shift:")
- col.prop(cam, "shift_x", text="X")
- col.prop(cam, "shift_y", text="Y")
+ sub = col.column(align=True)
+ sub.prop(cam, "shift_x", text="Shift X")
+ sub.prop(cam, "shift_y", text="Y")
- col = split.column(align=True)
- col.label(text="Clipping:")
- col.prop(cam, "clip_start", text="Start")
- col.prop(cam, "clip_end", text="End")
+ col.separator()
+ sub = col.column(align=True)
+ sub.prop(cam, "clip_start", text="Clip Start")
+ sub.prop(cam, "clip_end", text="End")
class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
bl_label = "Stereoscopy"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -147,6 +146,8 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
render = context.scene.render
st = context.camera.stereo
cam = context.camera
@@ -154,9 +155,9 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
is_spherical_stereo = cam.type != 'ORTHO' and render.use_spherical_stereo
use_spherical_stereo = is_spherical_stereo and st.use_spherical_stereo
- col = layout.column()
- col.row().prop(st, "convergence_mode", expand=True)
+ layout.prop(st, "convergence_mode")
+ col = layout.column()
sub = col.column()
sub.active = st.convergence_mode != 'PARALLEL'
sub.prop(st, "convergence_distance")
@@ -165,106 +166,222 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
if is_spherical_stereo:
col.separator()
- row = col.row()
- row.prop(st, "use_spherical_stereo")
- sub = row.row()
+ col.prop(st, "use_spherical_stereo")
+ sub = col.column()
sub.active = st.use_spherical_stereo
sub.prop(st, "use_pole_merge")
- row = col.row(align=True)
- row.active = st.use_pole_merge
- row.prop(st, "pole_merge_angle_from")
- row.prop(st, "pole_merge_angle_to")
- col.label(text="Pivot:")
- row = col.row()
- row.active = not use_spherical_stereo
- row.prop(st, "pivot", expand=True)
+ sub = col.column(align=True)
+ sub.active = st.use_pole_merge
+ sub.prop(st, "pole_merge_angle_from", text="Pole Merge Angle Start")
+ sub.prop(st, "pole_merge_angle_to", text="End")
+
+ col = layout.column()
+ col.active = not use_spherical_stereo
+ col.separator()
+ col.prop(st, "pivot")
class DATA_PT_camera(CameraButtonsPanel, Panel):
bl_label = "Camera"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw_header_preset(self, context):
+ CAMERA_PT_presets.draw_panel_header(self.layout)
def draw(self, context):
layout = self.layout
cam = context.camera
- row = layout.row(align=True)
-
- row.menu("CAMERA_MT_presets", text=bpy.types.CAMERA_MT_presets.bl_label)
- row.operator("camera.preset_add", text="", icon='ZOOMIN')
- row.operator("camera.preset_add", text="", icon='ZOOMOUT').remove_active = True
+ layout.use_property_split = True
- layout.label(text="Sensor:")
-
- split = layout.split()
+ col = layout.column()
+ col.prop(cam, "sensor_fit")
- col = split.column(align=True)
if cam.sensor_fit == 'AUTO':
- col.prop(cam, "sensor_width", text="Size")
+ col.prop(cam, "sensor_width")
else:
sub = col.column(align=True)
sub.active = cam.sensor_fit == 'HORIZONTAL'
sub.prop(cam, "sensor_width", text="Width")
+
sub = col.column(align=True)
sub.active = cam.sensor_fit == 'VERTICAL'
sub.prop(cam, "sensor_height", text="Height")
- col = split.column(align=True)
- col.prop(cam, "sensor_fit", text="")
-
class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
bl_label = "Depth of Field"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
cam = context.camera
dof_options = cam.gpu_dof
- split = layout.split()
-
- col = split.column()
- col.label(text="Focus:")
- col.prop(cam, "dof_object", text="")
+ col = layout.column()
+ col.prop(cam, "dof_object", text="Focus on Object")
sub = col.column()
sub.active = (cam.dof_object is None)
- sub.prop(cam, "dof_distance", text="Distance")
+ sub.prop(cam, "dof_distance", text="Focus Distance")
- hq_support = dof_options.is_hq_supported
- col = split.column(align=True)
- col.label("Viewport:")
- sub = col.column()
- sub.active = hq_support
- sub.prop(dof_options, "use_high_quality")
- col.prop(dof_options, "fstop")
- if dof_options.use_high_quality and hq_support:
+
+class DATA_PT_camera_dof_aperture(CameraButtonsPanel, Panel):
+ bl_label = "Aperture"
+ bl_parent_id = "DATA_PT_camera_dof"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ cam = context.camera
+ dof_options = cam.gpu_dof
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ if context.engine == 'BLENDER_EEVEE':
+ col = flow.column()
+ col.prop(dof_options, "fstop")
col.prop(dof_options, "blades")
+ col = flow.column()
+ col.prop(dof_options, "rotation")
+ col.prop(dof_options, "ratio")
+ else:
+ hq_support = dof_options.is_hq_supported
+ col = flow.column()
+ col.label("Viewport")
+ sub = col.column()
+ sub.active = hq_support
+ sub.prop(dof_options, "use_high_quality")
+ col.prop(dof_options, "fstop")
+ if dof_options.use_high_quality and hq_support:
+ col.prop(dof_options, "blades")
+
+
+class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
+ bl_label = "Background Images"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw_header(self, context):
+ cam = context.camera
+
+ self.layout.prop(cam, "show_background_images", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ cam = context.camera
+ use_multiview = context.scene.render.use_multiview
+
+ col = layout.column()
+ col.operator("view3d.background_image_add", text="Add Image")
+
+ for i, bg in enumerate(cam.background_images):
+ layout.active = cam.show_background_images
+ box = layout.box()
+ row = box.row(align=True)
+ row.prop(bg, "show_expanded", text="", emboss=False)
+ if bg.source == 'IMAGE' and bg.image:
+ row.prop(bg.image, "name", text="", emboss=False)
+ elif bg.source == 'MOVIE_CLIP' and bg.clip:
+ row.prop(bg.clip, "name", text="", emboss=False)
+ else:
+ row.label(text="Not Set")
+
+ if bg.show_background_image:
+ row.prop(bg, "show_background_image", text="", emboss=False, icon='RESTRICT_VIEW_OFF')
+ else:
+ row.prop(bg, "show_background_image", text="", emboss=False, icon='RESTRICT_VIEW_ON')
+
+ row.operator("view3d.background_image_remove", text="", emboss=False, icon='X').index = i
+
+ if bg.show_expanded:
+ row = box.row()
+ row.prop(bg, "source", expand=True)
+
+ has_bg = False
+ if bg.source == 'IMAGE':
+ row = box.row()
+ row.template_ID(bg, "image", open="image.open")
+ if bg.image is not None:
+ box.template_image(bg, "image", bg.image_user, compact=True)
+ has_bg = True
+
+ if use_multiview and bg.view_axis in {'CAMERA', 'ALL'}:
+ box.prop(bg.image, "use_multiview")
+
+ column = box.column()
+ column.active = bg.image.use_multiview
+
+ column.label(text="Views Format:")
+ column.row().prop(bg.image, "views_format", expand=True)
+
+ sub = column.box()
+ sub.active = bg.image.views_format == 'STEREO_3D'
+ sub.template_image_stereo_3d(bg.image.stereo_3d_format)
+
+ elif bg.source == 'MOVIE_CLIP':
+ box.prop(bg, "use_camera_clip")
+
+ column = box.column()
+ column.active = not bg.use_camera_clip
+ column.template_ID(bg, "clip", open="clip.open")
+
+ if bg.clip:
+ column.template_movieclip(bg, "clip", compact=True)
+
+ if bg.use_camera_clip or bg.clip:
+ has_bg = True
+
+ column = box.column()
+ column.active = has_bg
+ column.prop(bg.clip_user, "proxy_render_size", text="")
+ column.prop(bg.clip_user, "use_render_undistorted")
+
+ if has_bg:
+ col = box.column()
+ col.prop(bg, "alpha", slider=True)
+ col.row().prop(bg, "draw_depth", expand=True)
+
+ col.row().prop(bg, "frame_method", expand=True)
+
+ box = col.box()
+ row = box.row()
+ row.prop(bg, "offset")
+
+ row = box.row()
+ row.prop(bg, "use_flip_x")
+ row.prop(bg, "use_flip_y")
+
+ row = box.row()
+ row.prop(bg, "rotation")
+ row.prop(bg, "scale")
+
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
bl_label = "Display"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
cam = context.camera
split = layout.split()
+ split.label()
+ split.prop_menu_enum(cam, "show_guide")
- col = split.column()
- col.prop(cam, "show_limits", text="Limits")
- col.prop(cam, "show_mist", text="Mist")
+ col = layout.column(align=True)
- col.prop(cam, "show_sensor", text="Sensor")
- col.prop(cam, "show_name", text="Name")
-
- col = split.column()
- col.prop_menu_enum(cam, "show_guide")
col.separator()
col.prop(cam, "draw_size", text="Size")
col.separator()
@@ -273,17 +390,27 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel):
sub.active = cam.show_passepartout
sub.prop(cam, "passepartout_alpha", text="Alpha", slider=True)
+ col.separator()
+
+ col.prop(cam, "show_limits", text="Limits")
+ col.prop(cam, "show_mist", text="Mist")
+ col.prop(cam, "show_sensor", text="Sensor")
+ col.prop(cam, "show_name", text="Name")
+
class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
bl_label = "Safe Areas"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
cam = context.camera
self.layout.prop(cam, "show_safe_areas", text="")
+ def draw_header_preset(self, context):
+ SAFE_AREAS_PT_presets.draw_panel_header(self.layout)
+
def draw(self, context):
layout = self.layout
safe_data = context.scene.safe_areas
@@ -293,7 +420,7 @@ class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "object.data"
_property_type = bpy.types.Camera
@@ -302,39 +429,37 @@ def draw_display_safe_settings(layout, safe_data, settings):
show_safe_areas = settings.show_safe_areas
show_safe_center = settings.show_safe_center
- split = layout.split()
+ layout.use_property_split = True
- col = split.column()
- row = col.row(align=True)
- row.menu("SAFE_AREAS_MT_presets", text=bpy.types.SAFE_AREAS_MT_presets.bl_label)
- row.operator("safe_areas.preset_add", text="", icon='ZOOMIN')
- row.operator("safe_areas.preset_add", text="", icon='ZOOMOUT').remove_active = True
+ col = layout.column()
+ col.active = show_safe_areas
- col = split.column()
- col.prop(settings, "show_safe_center", text="Center-Cut Safe Areas")
+ sub = col.column()
+ sub.prop(safe_data, "title", slider=True)
+ sub.prop(safe_data, "action", slider=True)
- split = layout.split()
- col = split.column()
- col.active = show_safe_areas
- col.prop(safe_data, "title", slider=True)
- col.prop(safe_data, "action", slider=True)
+ col.separator()
+
+ col.prop(settings, "show_safe_center", text="Center-Cut Safe Areas")
- col = split.column()
- col.active = show_safe_areas and show_safe_center
- col.prop(safe_data, "title_center", slider=True)
- col.prop(safe_data, "action_center", slider=True)
+ sub = col.column()
+ sub.active = show_safe_areas and show_safe_center
+ sub.prop(safe_data, "title_center", slider=True)
+ sub.prop(safe_data, "action_center", slider=True)
classes = (
- CAMERA_MT_presets,
- SAFE_AREAS_MT_presets,
+ CAMERA_PT_presets,
+ SAFE_AREAS_PT_presets,
DATA_PT_context_camera,
DATA_PT_lens,
DATA_PT_camera,
DATA_PT_camera_stereoscopy,
DATA_PT_camera_dof,
+ DATA_PT_camera_dof_aperture,
DATA_PT_camera_display,
DATA_PT_camera_safe_areas,
+ DATA_PT_camera_background_image,
DATA_PT_custom_props_camera,
)
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index f57156c1bae..c0ab9da949f 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -93,63 +93,63 @@ class DATA_PT_shape_curve(CurveButtonsPanel, Panel):
row = layout.row()
row.prop(curve, "dimensions", expand=True)
- split = layout.split()
+ layout.use_property_split = True
+
+ col = layout.column()
+ sub = col.column(align=True)
+ sub.prop(curve, "resolution_u", text="Resolution Preview U")
+ if is_surf:
+ sub.prop(curve, "resolution_v", text="V")
- col = split.column()
- col.label(text="Resolution:")
sub = col.column(align=True)
- sub.prop(curve, "resolution_u", text="Preview U")
sub.prop(curve, "render_resolution_u", text="Render U")
+ if is_surf:
+ sub.prop(curve, "render_resolution_v", text="V")
+ col.separator()
+
if is_curve:
- col.label(text="Twisting:")
- col.prop(curve, "twist_mode", text="")
+ col.prop(curve, "twist_mode")
col.prop(curve, "twist_smooth", text="Smooth")
elif is_text:
- col.label(text="Display:")
col.prop(curve, "use_fast_edit", text="Fast Editing")
- col = split.column()
-
- if is_surf:
- sub = col.column()
- sub.label(text="")
- sub = col.column(align=True)
- sub.prop(curve, "resolution_v", text="Preview V")
- sub.prop(curve, "render_resolution_v", text="Render V")
-
if is_curve or is_text:
- col.label(text="Fill:")
+ col = layout.column()
+ col.separator()
+
sub = col.column()
sub.active = (curve.dimensions == '2D' or (curve.bevel_object is None and curve.dimensions == '3D'))
- sub.prop(curve, "fill_mode", text="")
+ sub.prop(curve, "fill_mode")
col.prop(curve, "use_fill_deform")
if is_curve:
- col.label(text="Path/Curve-Deform:")
+ col = layout.column()
+ col.separator()
+
sub = col.column()
- subsub = sub.row()
- subsub.prop(curve, "use_radius")
- subsub.prop(curve, "use_stretch")
+ sub.prop(curve, "use_radius")
+ sub.prop(curve, "use_stretch")
sub.prop(curve, "use_deform_bounds")
class DATA_PT_curve_texture_space(CurveButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
curve = context.curve
- row = layout.row()
- row.prop(curve, "use_auto_texspace")
- row.prop(curve, "use_uv_as_generated")
+ col = layout.column()
+ col.prop(curve, "use_uv_as_generated")
+ col.prop(curve, "use_auto_texspace")
- row = layout.row()
- row.column().prop(curve, "texspace_location", text="Location")
- row.column().prop(curve, "texspace_size", text="Size")
+ col = layout.column()
+ col.prop(curve, "texspace_location")
+ col.prop(curve, "texspace_size")
layout.operator("curve.match_texture_space")
@@ -163,29 +163,51 @@ class DATA_PT_geometry_curve(CurveButtonsPanelCurve, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
curve = context.curve
- split = layout.split()
-
- col = split.column()
- col.label(text="Modification:")
+ col = layout.column()
col.prop(curve, "offset")
- col.prop(curve, "extrude")
- col.label(text="Taper Object:")
- col.prop(curve, "taper_object", text="")
- col = split.column()
- col.label(text="Bevel:")
- col.prop(curve, "bevel_depth", text="Depth")
- col.prop(curve, "bevel_resolution", text="Resolution")
- col.label(text="Bevel Object:")
- col.prop(curve, "bevel_object", text="")
+ sub = col.column()
+ sub.active = (curve.bevel_object is None)
+ sub.prop(curve, "extrude")
+
+ col.prop(curve, "taper_object")
+
+ sub = col.column()
+ sub.active = curve.taper_object is not None
+ sub.prop(curve, "use_map_taper")
+
+
+class DATA_PT_geometry_curve_bevel(CurveButtonsPanelCurve, Panel):
+ bl_label = "Bevel"
+ bl_parent_id = "DATA_PT_geometry_curve"
+
+ @classmethod
+ def poll(cls, context):
+ return (type(context.curve) in {Curve, TextCurve})
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ curve = context.curve
+
+ col = layout.column()
+ sub = col.column()
+ sub.active = (curve.bevel_object is None)
+ sub.prop(curve, "bevel_depth", text="Depth")
+ sub.prop(curve, "bevel_resolution", text="Resolution")
+
+ col.prop(curve, "bevel_object", text="Object")
+
+ sub = col.column()
+ sub.active = curve.bevel_object is not None
+ sub.prop(curve, "use_fill_caps")
if type(curve) is not TextCurve:
- col = layout.column(align=True)
- row = col.row()
- row.label(text="Bevel Factor:")
col = layout.column()
col.active = (
@@ -193,20 +215,13 @@ class DATA_PT_geometry_curve(CurveButtonsPanelCurve, Panel):
(curve.extrude > 0.0) or
(curve.bevel_object is not None)
)
- row = col.row(align=True)
- row.prop(curve, "bevel_factor_mapping_start", text="")
- row.prop(curve, "bevel_factor_start", text="Start")
- row = col.row(align=True)
- row.prop(curve, "bevel_factor_mapping_end", text="")
- row.prop(curve, "bevel_factor_end", text="End")
+ sub = col.column(align=True)
+ sub.prop(curve, "bevel_factor_start", text="Bevel Start")
+ sub.prop(curve, "bevel_factor_end", text="End")
- row = layout.row()
- sub = row.row()
- sub.active = curve.taper_object is not None
- sub.prop(curve, "use_map_taper")
- sub = row.row()
- sub.active = curve.bevel_object is not None
- sub.prop(curve, "use_fill_caps")
+ sub = col.column(align=True)
+ sub.prop(curve, "bevel_factor_mapping_start", text="Bevel Mapping Start")
+ sub.prop(curve, "bevel_factor_mapping_end", text="End")
class DATA_PT_pathanim(CurveButtonsPanelCurve, Panel):
@@ -219,6 +234,7 @@ class DATA_PT_pathanim(CurveButtonsPanelCurve, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
curve = context.curve
@@ -229,8 +245,9 @@ class DATA_PT_pathanim(CurveButtonsPanelCurve, Panel):
col.prop(curve, "eval_time")
# these are for paths only
- row = layout.row()
- row.prop(curve, "use_path_follow")
+ col.separator()
+
+ col.prop(curve, "use_path_follow")
class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
@@ -238,65 +255,64 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
curve = context.curve
act_spline = curve.splines.active
is_surf = type(curve) is SurfaceCurve
is_poly = (act_spline.type == 'POLY')
- split = layout.split()
+ col = layout.column()
if is_poly:
# These settings are below but its easier to have
# polys set aside since they use so few settings
- row = layout.row()
- row.label(text="Cyclic:")
- row.prop(act_spline, "use_cyclic_u", text="U")
- layout.prop(act_spline, "use_smooth")
+ col.prop(act_spline, "use_cyclic_u")
+ col.prop(act_spline, "use_smooth")
else:
- col = split.column()
- col.label(text="Cyclic:")
- if act_spline.type == 'NURBS':
- col.label(text="Bezier:")
- col.label(text="Endpoint:")
- col.label(text="Order:")
- col.label(text="Resolution:")
-
- col = split.column()
- col.prop(act_spline, "use_cyclic_u", text="U")
+ sub = col.column(align=True)
+ sub.prop(act_spline, "use_cyclic_u")
+ if is_surf:
+ sub.prop(act_spline, "use_cyclic_v", text="V")
if act_spline.type == 'NURBS':
- sub = col.column()
+ sub = col.column(align=True)
# sub.active = (not act_spline.use_cyclic_u)
- sub.prop(act_spline, "use_bezier_u", text="U")
- sub.prop(act_spline, "use_endpoint_u", text="U")
+ sub.prop(act_spline, "use_bezier_u", text="Bezier U")
- sub = col.column()
- sub.prop(act_spline, "order_u", text="U")
- col.prop(act_spline, "resolution_u", text="U")
+ if is_surf:
+ subsub = sub.column()
+ subsub.active = (not act_spline.use_cyclic_v)
+ subsub.prop(act_spline, "use_bezier_v", text="V")
- if is_surf:
- col = split.column()
- col.prop(act_spline, "use_cyclic_v", text="V")
+ sub = col.column(align=True)
+ sub.prop(act_spline, "use_endpoint_u", text="Endpoint U")
- # its a surface, assume its a nurbs
- sub = col.column()
- sub.active = (not act_spline.use_cyclic_v)
- sub.prop(act_spline, "use_bezier_v", text="V")
- sub.prop(act_spline, "use_endpoint_v", text="V")
- sub = col.column()
- sub.prop(act_spline, "order_v", text="V")
+ if is_surf:
+ subsub = sub.column()
+ subsub.active = (not act_spline.use_cyclic_v)
+ subsub.prop(act_spline, "use_endpoint_v", text="V")
+
+ sub = col.column(align=True)
+ sub.prop(act_spline, "order_u", text="Order U")
+
+ if is_surf:
+ sub.prop(act_spline, "order_v", text="V")
+
+ sub = col.column(align=True)
+ sub.prop(act_spline, "resolution_u", text="Resolution U")
+ if is_surf:
sub.prop(act_spline, "resolution_v", text="V")
if act_spline.type == 'BEZIER':
- col = layout.column()
- col.label(text="Interpolation:")
+
+ col.separator()
sub = col.column()
sub.active = (curve.dimensions == '3D')
- sub.prop(act_spline, "tilt_interpolation", text="Tilt")
+ sub.prop(act_spline, "tilt_interpolation", text="Interpolation Tilt")
col.prop(act_spline, "radius_interpolation", text="Radius")
@@ -325,42 +341,46 @@ class DATA_PT_font(CurveButtonsPanelText, Panel):
row.label(text="Bold & Italic")
row.template_ID(text, "font_bold_italic", open="font.open", unlink="font.unlink")
- # layout.prop(text, "font")
+ layout.separator()
- split = layout.split()
+ row = layout.row(align=True)
+ row.prop(char, "use_bold", toggle=True)
+ row.prop(char, "use_italic", toggle=True)
+ row.prop(char, "use_underline", toggle=True)
+ row.prop(char, "use_small_caps", toggle=True)
+
+
+class DATA_PT_font_transform(CurveButtonsPanelText, Panel):
+ bl_label = "Transform"
+ bl_parent_id = "DATA_PT_font"
+
+ def draw(self, context):
+ layout = self.layout
+
+ text = context.curve
+ char = context.curve.edit_format
+
+ layout.use_property_split = True
+
+ col = layout.column()
+
+ col.separator()
- col = split.column()
col.prop(text, "size", text="Size")
- col = split.column()
col.prop(text, "shear")
- split = layout.split()
-
- col = split.column()
- col.label(text="Object Font:")
- col.prop(text, "family", text="")
+ col.separator()
- col = split.column()
- col.label(text="Text on Curve:")
- col.prop(text, "follow_curve", text="")
+ col.prop(text, "family")
+ col.prop(text, "follow_curve")
- split = layout.split()
+ col.separator()
- col = split.column()
sub = col.column(align=True)
- sub.label(text="Underline:")
- sub.prop(text, "underline_position", text="Position")
- sub.prop(text, "underline_height", text="Thickness")
-
- col = split.column()
- col.label(text="Character:")
- col.prop(char, "use_bold")
- col.prop(char, "use_italic")
- col.prop(char, "use_underline")
+ sub.prop(text, "underline_position", text="Underline Position")
+ sub.prop(text, "underline_height", text="Underline Thickness")
- row = layout.row()
- row.prop(text, "small_caps_scale", text="Small Caps")
- row.prop(char, "use_small_caps")
+ col.prop(text, "small_caps_scale", text="Small Caps Scale")
class DATA_PT_paragraph(CurveButtonsPanelText, Panel):
@@ -371,23 +391,40 @@ class DATA_PT_paragraph(CurveButtonsPanelText, Panel):
text = context.curve
- layout.label(text="Horizontal Alignment:")
- layout.row().prop(text, "align_x", expand=True)
- layout.label(text="Vertical Alignment:")
+class DATA_PT_paragraph_alignment(CurveButtonsPanelText, Panel):
+ bl_parent_id = "DATA_PT_paragraph"
+ bl_label = "Alignment"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = False
+
+ text = context.curve
+
+ layout.row().prop(text, "align_x", expand=True)
layout.row().prop(text, "align_y", expand=True)
- split = layout.split()
- col = split.column(align=True)
- col.label(text="Spacing:")
- col.prop(text, "space_character", text="Letter")
- col.prop(text, "space_word", text="Word")
- col.prop(text, "space_line", text="Line")
+class DATA_PT_paragraph_spacing(CurveButtonsPanelText, Panel):
+ bl_parent_id = "DATA_PT_paragraph"
+ bl_label = "Spacing"
- col = split.column(align=True)
- col.label(text="Offset:")
- col.prop(text, "offset_x", text="X")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ text = context.curve
+
+ col = layout.column(align=True)
+ col.prop(text, "space_character", text="Character Spacing")
+ col.prop(text, "space_word", text="Word Spacing")
+ col.prop(text, "space_line", text="Line Spacing")
+
+ layout.separator()
+
+ col = layout.column(align=True)
+ col.prop(text, "offset_x", text="Offset X")
col.prop(text, "offset_y", text="Y")
@@ -399,10 +436,7 @@ class DATA_PT_text_boxes(CurveButtonsPanelText, Panel):
text = context.curve
- split = layout.split()
- col = split.column()
- col.operator("font.textbox_add", icon='ZOOMIN')
- col = split.column()
+ layout.operator("font.textbox_add", icon='ZOOMIN')
for i, box in enumerate(text.text_boxes):
@@ -410,25 +444,22 @@ class DATA_PT_text_boxes(CurveButtonsPanelText, Panel):
row = boxy.row()
- split = row.split()
-
- col = split.column(align=True)
-
- col.label(text="Dimensions:")
- col.prop(box, "width", text="Width")
- col.prop(box, "height", text="Height")
+ col = row.column()
+ col.use_property_split = True
- col = split.column(align=True)
+ sub = col.column(align=True)
+ sub.prop(box, "width", text="Size X")
+ sub.prop(box, "height", text="Y")
- col.label(text="Offset:")
- col.prop(box, "x", text="X")
- col.prop(box, "y", text="Y")
+ sub = col.column(align=True)
+ sub.prop(box, "x", text="Offset X")
+ sub.prop(box, "y", text="Y")
row.operator("font.textbox_remove", text="", icon='X', emboss=False).index = i
class DATA_PT_custom_props_curve(CurveButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "object.data"
_property_type = bpy.types.Curve
@@ -438,10 +469,14 @@ classes = (
DATA_PT_shape_curve,
DATA_PT_curve_texture_space,
DATA_PT_geometry_curve,
+ DATA_PT_geometry_curve_bevel,
DATA_PT_pathanim,
DATA_PT_active_spline,
DATA_PT_font,
+ DATA_PT_font_transform,
DATA_PT_paragraph,
+ DATA_PT_paragraph_alignment,
+ DATA_PT_paragraph_spacing,
DATA_PT_text_boxes,
DATA_PT_custom_props_curve,
)
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index c66ff87ecbd..ab12d0f5c5f 100644
--- a/release/scripts/startup/bl_ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -36,10 +36,11 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
- layout.prop(ob, "empty_draw_type", text="Display")
+ layout.prop(ob, "empty_draw_type", text="Display As")
if ob.empty_draw_type == 'IMAGE':
layout.template_ID(ob, "data", open="image.open", unlink="object.unlink_data")
@@ -49,9 +50,11 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
row = layout.row(align=True)
layout.prop(ob, "color", text="Transparency", index=3, slider=True)
- row = layout.row(align=True)
- row.prop(ob, "empty_image_offset", text="Offset X", index=0)
- row.prop(ob, "empty_image_offset", text="Offset Y", index=1)
+ col = layout.column(align=True)
+ col.prop(ob, "empty_image_offset", text="Offset X", index=0)
+ col.prop(ob, "empty_image_offset", text="Y", index=1)
+
+ layout.separator()
layout.prop(ob, "empty_draw_size", text="Size")
diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py
deleted file mode 100644
index f9394139b42..00000000000
--- a/release/scripts/startup/bl_ui/properties_data_lamp.py
+++ /dev/null
@@ -1,414 +0,0 @@
-# ##### 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.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-import bpy
-from bpy.types import Menu, Panel
-from rna_prop_ui import PropertyPanel
-
-
-class LAMP_MT_sunsky_presets(Menu):
- bl_label = "Sun & Sky Presets"
- preset_subdir = "sunsky"
- preset_operator = "script.execute_preset"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- draw = Menu.draw_preset
-
-
-class DataButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "data"
-
- @classmethod
- def poll(cls, context):
- engine = context.scene.render.engine
- return context.lamp and (engine in cls.COMPAT_ENGINES)
-
-
-class DATA_PT_context_lamp(DataButtonsPanel, Panel):
- bl_label = ""
- bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
- lamp = context.lamp
- space = context.space_data
-
- split = layout.split(percentage=0.65)
-
- texture_count = len(lamp.texture_slots.keys())
-
- if ob:
- split.template_ID(ob, "data")
- elif lamp:
- split.template_ID(space, "pin_id")
-
- if texture_count != 0:
- split.label(text=str(texture_count), icon='TEXTURE')
-
-
-class DATA_PT_preview(DataButtonsPanel, Panel):
- bl_label = "Preview"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- self.layout.template_preview(context.lamp)
-
-
-class DATA_PT_lamp(DataButtonsPanel, Panel):
- bl_label = "Lamp"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- lamp = context.lamp
-
- layout.row().prop(lamp, "type", expand=True)
-
- split = layout.split()
-
- col = split.column()
- sub = col.column()
- sub.prop(lamp, "color", text="")
- sub.prop(lamp, "energy")
-
- if lamp.type in {'POINT', 'SPOT'}:
- sub.label(text="Falloff:")
- sub.prop(lamp, "falloff_type", text="")
- sub.prop(lamp, "distance")
-
- if lamp.falloff_type == 'LINEAR_QUADRATIC_WEIGHTED':
- col.label(text="Attenuation Factors:")
- sub = col.column(align=True)
- sub.prop(lamp, "linear_attenuation", slider=True, text="Linear")
- sub.prop(lamp, "quadratic_attenuation", slider=True, text="Quadratic")
-
- elif lamp.falloff_type == 'INVERSE_COEFFICIENTS':
- col.label(text="Inverse Coefficients:")
- sub = col.column(align=True)
- sub.prop(lamp, "constant_coefficient", text="Constant")
- sub.prop(lamp, "linear_coefficient", text="Linear")
- sub.prop(lamp, "quadratic_coefficient", text="Quadratic")
-
- col.prop(lamp, "use_sphere")
-
- if lamp.type == 'AREA':
- col.prop(lamp, "distance")
- col.prop(lamp, "gamma")
-
- col = split.column()
- col.prop(lamp, "use_negative")
- col.prop(lamp, "use_own_layer", text="This Layer Only")
- col.prop(lamp, "use_specular")
- col.prop(lamp, "use_diffuse")
-
-
-class DATA_PT_sunsky(DataButtonsPanel, Panel):
- bl_label = "Sky & Atmosphere"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- lamp = context.lamp
- engine = context.scene.render.engine
- return (lamp and lamp.type == 'SUN') and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- lamp = context.lamp.sky
-
- row = layout.row(align=True)
- row.prop(lamp, "use_sky")
- row.menu("LAMP_MT_sunsky_presets", text=bpy.types.LAMP_MT_sunsky_presets.bl_label)
- row.operator("lamp.sunsky_preset_add", text="", icon='ZOOMIN')
- row.operator("lamp.sunsky_preset_add", text="", icon='ZOOMOUT').remove_active = True
-
- row = layout.row()
- row.active = lamp.use_sky or lamp.use_atmosphere
- row.prop(lamp, "atmosphere_turbidity", text="Turbidity")
-
- split = layout.split()
-
- col = split.column()
- col.active = lamp.use_sky
- col.label(text="Blending:")
- sub = col.column()
- sub.prop(lamp, "sky_blend_type", text="")
- sub.prop(lamp, "sky_blend", text="Factor")
-
- col.label(text="Color Space:")
- sub = col.column()
- sub.row().prop(lamp, "sky_color_space", expand=True)
- sub.prop(lamp, "sky_exposure", text="Exposure")
-
- col = split.column()
- col.active = lamp.use_sky
- col.label(text="Horizon:")
- sub = col.column()
- sub.prop(lamp, "horizon_brightness", text="Brightness")
- sub.prop(lamp, "spread", text="Spread")
-
- col.label(text="Sun:")
- sub = col.column()
- sub.prop(lamp, "sun_brightness", text="Brightness")
- sub.prop(lamp, "sun_size", text="Size")
- sub.prop(lamp, "backscattered_light", slider=True, text="Back Light")
-
- layout.separator()
-
- layout.prop(lamp, "use_atmosphere")
-
- split = layout.split()
-
- col = split.column()
- col.active = lamp.use_atmosphere
- col.label(text="Intensity:")
- col.prop(lamp, "sun_intensity", text="Sun")
- col.prop(lamp, "atmosphere_distance_factor", text="Distance")
-
- col = split.column()
- col.active = lamp.use_atmosphere
- col.label(text="Scattering:")
- sub = col.column(align=True)
- sub.prop(lamp, "atmosphere_inscattering", slider=True, text="Inscattering")
- sub.prop(lamp, "atmosphere_extinction", slider=True, text="Extinction")
-
-
-class DATA_PT_shadow(DataButtonsPanel, Panel):
- bl_label = "Shadow"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- lamp = context.lamp
- engine = context.scene.render.engine
- return (lamp and lamp.type in {'POINT', 'SUN', 'SPOT', 'AREA'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- lamp = context.lamp
-
- layout.row().prop(lamp, "shadow_method", expand=True)
-
- if lamp.shadow_method == 'NOSHADOW' and lamp.type == 'AREA':
- split = layout.split()
-
- col = split.column()
- col.label(text="Form Factor Sampling:")
-
- sub = col.row(align=True)
-
- if lamp.shape == 'SQUARE':
- sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
- elif lamp.shape == 'RECTANGLE':
- sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
- sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
-
- if lamp.shadow_method != 'NOSHADOW':
- split = layout.split()
-
- col = split.column()
- col.prop(lamp, "shadow_color", text="")
-
- col = split.column()
- col.prop(lamp, "use_shadow_layer", text="This Layer Only")
- col.prop(lamp, "use_only_shadow")
-
- if lamp.shadow_method == 'RAY_SHADOW':
- split = layout.split()
-
- col = split.column()
- col.label(text="Sampling:")
-
- if lamp.type in {'POINT', 'SUN', 'SPOT'}:
- sub = col.row()
-
- sub.prop(lamp, "shadow_ray_samples", text="Samples")
- sub.prop(lamp, "shadow_soft_size", text="Soft Size")
-
- elif lamp.type == 'AREA':
- sub = col.row(align=True)
-
- if lamp.shape == 'SQUARE':
- sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
- elif lamp.shape == 'RECTANGLE':
- sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
- sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
-
- col.row().prop(lamp, "shadow_ray_sample_method", expand=True)
-
- if lamp.shadow_ray_sample_method == 'ADAPTIVE_QMC':
- layout.prop(lamp, "shadow_adaptive_threshold", text="Threshold")
-
- if lamp.type == 'AREA' and lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
- row = layout.row()
- row.prop(lamp, "use_umbra")
- row.prop(lamp, "use_dither")
- row.prop(lamp, "use_jitter")
-
- elif lamp.shadow_method == 'BUFFER_SHADOW':
- col = layout.column()
- col.label(text="Buffer Type:")
- col.row().prop(lamp, "shadow_buffer_type", expand=True)
-
- if lamp.shadow_buffer_type in {'REGULAR', 'HALFWAY', 'DEEP'}:
- split = layout.split()
-
- col = split.column()
- col.label(text="Filter Type:")
- col.prop(lamp, "shadow_filter_type", text="")
- sub = col.column(align=True)
- sub.prop(lamp, "shadow_buffer_soft", text="Soft")
- sub.prop(lamp, "shadow_buffer_bias", text="Bias")
-
- col = split.column()
- col.label(text="Sample Buffers:")
- col.prop(lamp, "shadow_sample_buffers", text="")
- sub = col.column(align=True)
- sub.prop(lamp, "shadow_buffer_size", text="Size")
- sub.prop(lamp, "shadow_buffer_samples", text="Samples")
- if lamp.shadow_buffer_type == 'DEEP':
- col.prop(lamp, "compression_threshold")
-
- elif lamp.shadow_buffer_type == 'IRREGULAR':
- layout.prop(lamp, "shadow_buffer_bias", text="Bias")
-
- split = layout.split()
-
- col = split.column()
- col.prop(lamp, "use_auto_clip_start", text="Autoclip Start")
- sub = col.column()
- sub.active = not lamp.use_auto_clip_start
- sub.prop(lamp, "shadow_buffer_clip_start", text="Clip Start")
-
- col = split.column()
- col.prop(lamp, "use_auto_clip_end", text="Autoclip End")
- sub = col.column()
- sub.active = not lamp.use_auto_clip_end
- sub.prop(lamp, "shadow_buffer_clip_end", text=" Clip End")
-
-
-class DATA_PT_area(DataButtonsPanel, Panel):
- bl_label = "Area Shape"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- lamp = context.lamp
- engine = context.scene.render.engine
- return (lamp and lamp.type == 'AREA') and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- lamp = context.lamp
-
- col = layout.column()
- col.row().prop(lamp, "shape", expand=True)
- sub = col.row(align=True)
-
- if lamp.shape == 'SQUARE':
- sub.prop(lamp, "size")
- elif lamp.shape == 'RECTANGLE':
- sub.prop(lamp, "size", text="Size X")
- sub.prop(lamp, "size_y", text="Size Y")
-
-
-class DATA_PT_spot(DataButtonsPanel, Panel):
- bl_label = "Spot Shape"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- lamp = context.lamp
- engine = context.scene.render.engine
- return (lamp and lamp.type == 'SPOT') and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- lamp = context.lamp
-
- split = layout.split()
-
- col = split.column()
- sub = col.column()
- sub.prop(lamp, "spot_size", text="Size")
- sub.prop(lamp, "spot_blend", text="Blend", slider=True)
- col.prop(lamp, "use_square")
- col.prop(lamp, "show_cone")
-
- col = split.column()
-
- col.active = (lamp.shadow_method != 'BUFFER_SHADOW' or lamp.shadow_buffer_type != 'DEEP')
- col.prop(lamp, "use_halo")
- sub = col.column(align=True)
- sub.active = lamp.use_halo
- sub.prop(lamp, "halo_intensity", text="Intensity")
- if lamp.shadow_method == 'BUFFER_SHADOW':
- sub.prop(lamp, "halo_step", text="Step")
-
-
-class DATA_PT_falloff_curve(DataButtonsPanel, Panel):
- bl_label = "Falloff Curve"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- lamp = context.lamp
- engine = context.scene.render.engine
-
- return (lamp and lamp.type in {'POINT', 'SPOT'} and lamp.falloff_type == 'CUSTOM_CURVE') and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- lamp = context.lamp
-
- self.layout.template_curve_mapping(lamp, "falloff_curve", use_negative_slope=True)
-
-
-class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- _context_path = "object.data"
- _property_type = bpy.types.Lamp
-
-
-classes = (
- LAMP_MT_sunsky_presets,
- DATA_PT_context_lamp,
- DATA_PT_preview,
- DATA_PT_lamp,
- DATA_PT_sunsky,
- DATA_PT_shadow,
- DATA_PT_area,
- DATA_PT_spot,
- DATA_PT_falloff_curve,
- DATA_PT_custom_props_lamp,
-)
-
-if __name__ == "__main__": # only for live edit.
- from bpy.utils import register_class
- for cls in classes:
- register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_lattice.py b/release/scripts/startup/bl_ui/properties_data_lattice.py
index 4b3fd48c195..40e82bc0a52 100644
--- a/release/scripts/startup/bl_ui/properties_data_lattice.py
+++ b/release/scripts/startup/bl_ui/properties_data_lattice.py
@@ -57,28 +57,35 @@ class DATA_PT_lattice(DataButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
lat = context.lattice
- row = layout.row()
- row.prop(lat, "points_u")
- row.prop(lat, "interpolation_type_u", text="")
+ col = layout.column()
- row = layout.row()
- row.prop(lat, "points_v")
- row.prop(lat, "interpolation_type_v", text="")
+ sub = col.column(align=True)
+ sub.prop(lat, "points_u", text="Resolution U")
+ sub.prop(lat, "points_v", text="V")
+ sub.prop(lat, "points_w", text="W")
- row = layout.row()
- row.prop(lat, "points_w")
- row.prop(lat, "interpolation_type_w", text="")
+ col.separator()
- row = layout.row()
- row.prop(lat, "use_outside")
- row.prop_search(lat, "vertex_group", context.object, "vertex_groups", text="")
+ sub = col.column(align=True)
+ sub.prop(lat, "interpolation_type_u", text="Interpolation U")
+ sub.prop(lat, "interpolation_type_v", text="V")
+ sub.prop(lat, "interpolation_type_w", text="W")
+
+ col.separator()
+
+ col.prop(lat, "use_outside")
+
+ col.separator()
+
+ col.prop_search(lat, "vertex_group", context.object, "vertex_groups")
class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "object.data"
_property_type = bpy.types.Lattice
diff --git a/release/scripts/startup/bl_ui/properties_data_light.py b/release/scripts/startup/bl_ui/properties_data_light.py
new file mode 100644
index 00000000000..057f7dffce0
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_light.py
@@ -0,0 +1,363 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Menu, Panel
+from rna_prop_ui import PropertyPanel
+
+
+class DataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.engine
+ return context.light and (engine in cls.COMPAT_ENGINES)
+
+
+class DATA_PT_context_light(DataButtonsPanel, Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ light = context.light
+ space = context.space_data
+
+ split = layout.split(percentage=0.65)
+
+ if ob:
+ split.template_ID(ob, "data")
+ elif light:
+ split.template_ID(space, "pin_id")
+
+
+class DATA_PT_preview(DataButtonsPanel, Panel):
+ bl_label = "Preview"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ self.layout.template_preview(context.light)
+
+
+class DATA_PT_light(DataButtonsPanel, Panel):
+ bl_label = "Light"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ light = context.light
+
+ layout.row().prop(light, "type", expand=True)
+
+ layout.use_property_split = True
+
+ col = col.column()
+ col.prop(light, "color")
+ col.prop(light, "energy")
+
+ if light.type in {'POINT', 'SPOT'}:
+
+ col = col.column()
+ col.label(text="Falloff")
+ col.prop(light, "falloff_type")
+ col.prop(light, "distance")
+ col.prop(light, "shadow_soft_size")
+
+ if light.falloff_type == 'LINEAR_QUADRATIC_WEIGHTED':
+ sub = col.column(align=True)
+ sub.prop(light, "linear_attenuation", slider=True, text="Linear")
+ sub.prop(light, "quadratic_attenuation", slider=True, text="Quadratic")
+
+ elif light.falloff_type == 'INVERSE_COEFFICIENTS':
+ col.label(text="Inverse Coefficients")
+ sub = col.column(align=True)
+ sub.prop(light, "constant_coefficient", text="Constant")
+ sub.prop(light, "linear_coefficient", text="Linear")
+ sub.prop(light, "quadratic_coefficient", text="Quadratic")
+
+ if light.type == 'AREA':
+ col.prop(light, "distance")
+
+ col = split.column()
+ col.label()
+
+
+class DATA_PT_EEVEE_light(DataButtonsPanel, Panel):
+ bl_label = "Light"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ light = context.light
+
+ layout.row().prop(light, "type", expand=True)
+
+ layout.use_property_split = True
+
+ col = layout.column()
+ col.prop(light, "color")
+ col.prop(light, "energy")
+ col.prop(light, "specular_factor", text="Specular")
+
+ col.separator()
+
+ if light.type in {'POINT', 'SPOT', 'SUN'}:
+ col.prop(light, "shadow_soft_size", text="Radius")
+ elif light.type == 'AREA':
+ col.prop(light, "shape")
+
+ sub = col.column(align=True)
+
+ if light.shape in {'SQUARE', 'DISK'}:
+ sub.prop(light, "size")
+ elif light.shape in {'RECTANGLE', 'ELLIPSE'}:
+ sub.prop(light, "size", text="Size X")
+ sub.prop(light, "size_y", text="Y")
+
+
+class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel):
+ bl_label = "Shadow"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ light = context.light
+ engine = context.engine
+ return (light and light.type in {'POINT', 'SUN', 'SPOT', 'AREA'}) and (engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ light = context.light
+ self.layout.prop(light, "use_shadow", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ light = context.light
+
+ layout.active = light.use_shadow
+
+ col = layout.column()
+ sub = col.column(align=True)
+ sub.prop(light, "shadow_buffer_clip_start", text="Clip Start")
+ sub.prop(light, "shadow_buffer_clip_end", text="End")
+
+ col.prop(light, "shadow_buffer_soft", text="Softness")
+
+ col.separator()
+
+ col.prop(light, "shadow_buffer_bias", text="Bias")
+ col.prop(light, "shadow_buffer_exp", text="Exponent")
+ col.prop(light, "shadow_buffer_bleed_bias", text="Bleed Bias")
+
+
+class DATA_PT_EEVEE_shadow_cascaded_shadow_map(DataButtonsPanel, Panel):
+ bl_label = "Cascaded Shadow Map"
+ bl_parent_id = "DATA_PT_EEVEE_shadow"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ light = context.light
+ engine = context.engine
+
+ return (light and light.type == 'SUN') and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ light = context.light
+ layout.use_property_split = True
+
+ col = layout.column()
+
+ col.prop(light, "shadow_cascade_count", text="Count")
+ col.prop(light, "shadow_cascade_fade", text="Fade")
+
+ col.prop(light, "shadow_cascade_max_distance", text="Max Distance")
+ col.prop(light, "shadow_cascade_exponent", text="Distribution")
+
+
+class DATA_PT_EEVEE_shadow_contact(DataButtonsPanel, Panel):
+ bl_label = "Contact Shadows"
+ bl_parent_id = "DATA_PT_EEVEE_shadow"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ light = context.light
+ engine = context.engine
+ return (light and light.type in {'POINT', 'SUN', 'SPOT', 'AREA'}) and (engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ light = context.light
+
+ layout = self.layout
+ layout.active = light.use_shadow
+ layout.prop(light, "use_contact_shadow", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ light = context.light
+ layout.use_property_split = True
+
+ col = layout.column()
+ col.active = light.use_shadow and light.use_contact_shadow
+
+ col.prop(light, "contact_shadow_distance", text="Distance")
+ col.prop(light, "contact_shadow_soft_size", text="Softness")
+ col.prop(light, "contact_shadow_bias", text="Bias")
+ col.prop(light, "contact_shadow_thickness", text="Thickness")
+
+
+class DATA_PT_area(DataButtonsPanel, Panel):
+ bl_label = "Area Shape"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ light = context.light
+ engine = context.engine
+ return (light and light.type == 'AREA') and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ light = context.light
+
+ col = layout.column()
+ col.row().prop(light, "shape", expand=True)
+ sub = col.row(align=True)
+
+ if light.shape in {'SQUARE', 'DISK'}:
+ sub.prop(light, "size")
+ elif light.shape in {'RECTANGLE', 'ELLIPSE'}:
+ sub.prop(light, "size", text="Size X")
+ sub.prop(light, "size_y", text="Size Y")
+
+
+class DATA_PT_spot(DataButtonsPanel, Panel):
+ bl_label = "Spot Shape"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ light = context.light
+ engine = context.engine
+ return (light and light.type == 'SPOT') and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ light = context.light
+
+ split = layout.split()
+
+ col = split.column()
+ sub = col.column()
+ sub.prop(light, "spot_size", text="Size")
+ sub.prop(light, "spot_blend", text="Blend", slider=True)
+ col.prop(light, "use_square")
+ col.prop(light, "show_cone")
+
+ col = split.column()
+
+ col.active = (light.shadow_method != 'BUFFER_SHADOW' or light.shadow_buffer_type != 'DEEP')
+ col.prop(light, "use_halo")
+ sub = col.column(align=True)
+ sub.active = light.use_halo
+ sub.prop(light, "halo_intensity", text="Intensity")
+ if light.shadow_method == 'BUFFER_SHADOW':
+ sub.prop(light, "halo_step", text="Step")
+
+
+class DATA_PT_spot(DataButtonsPanel, Panel):
+ bl_label = "Spot Shape"
+ bl_parent_id = "DATA_PT_EEVEE_light"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ light = context.light
+ engine = context.engine
+ return (light and light.type == 'SPOT') and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ light = context.light
+
+ col = layout.column()
+
+ col.prop(light, "spot_size", text="Size")
+ col.prop(light, "spot_blend", text="Blend", slider=True)
+
+ col.prop(light, "show_cone")
+
+
+class DATA_PT_falloff_curve(DataButtonsPanel, Panel):
+ bl_label = "Falloff Curve"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ light = context.light
+ engine = context.engine
+
+ return (light and light.type in {'POINT', 'SPOT'} and light.falloff_type == 'CUSTOM_CURVE') and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ light = context.light
+
+ self.layout.template_curve_mapping(light, "falloff_curve", use_negative_slope=True)
+
+
+class DATA_PT_custom_props_light(DataButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ _context_path = "object.data"
+ _property_type = bpy.types.Light
+
+
+classes = (
+ DATA_PT_context_light,
+ DATA_PT_preview,
+ DATA_PT_light,
+ DATA_PT_EEVEE_light,
+ DATA_PT_EEVEE_shadow,
+ DATA_PT_EEVEE_shadow_contact,
+ DATA_PT_EEVEE_shadow_cascaded_shadow_map,
+ DATA_PT_area,
+ DATA_PT_spot,
+ DATA_PT_falloff_curve,
+ DATA_PT_custom_props_light,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_lightprobe.py b/release/scripts/startup/bl_ui/properties_data_lightprobe.py
new file mode 100644
index 00000000000..10b66dd0033
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_lightprobe.py
@@ -0,0 +1,185 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Panel
+
+
+class DataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.engine
+ return context.lightprobe and (engine in cls.COMPAT_ENGINES)
+
+
+class DATA_PT_context_lightprobe(DataButtonsPanel, Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ probe = context.lightprobe
+ space = context.space_data
+
+ if ob:
+ layout.template_ID(ob, "data")
+ elif probe:
+ layout.template_ID(space, "pin_id")
+
+
+class DATA_PT_lightprobe(DataButtonsPanel, Panel):
+ bl_label = "Probe"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+ probe = context.lightprobe
+
+# layout.prop(probe, "type")
+
+ if probe.type == 'GRID':
+ col = layout.column()
+ col.prop(probe, "influence_distance", "Distance")
+ col.prop(probe, "falloff")
+ col.prop(probe, "intensity")
+
+ col.separator()
+
+ col.prop(probe, "grid_resolution_x", text="Resolution X")
+ col.prop(probe, "grid_resolution_y", text="Y")
+ col.prop(probe, "grid_resolution_z", text="Z")
+
+ elif probe.type == 'PLANAR':
+ col = layout.column()
+ col.prop(probe, "influence_distance", "Distance")
+ col.prop(probe, "falloff")
+ else:
+ col = layout.column()
+ col.prop(probe, "influence_type")
+
+ if probe.influence_type == 'ELIPSOID':
+ col.prop(probe, "influence_distance", "Radius")
+ else:
+ col.prop(probe, "influence_distance", "Size")
+
+ col.prop(probe, "falloff")
+ col.prop(probe, "intensity")
+
+ col = layout.column()
+ sub = col.column()
+ sub.prop(probe, "clip_start", text="Clipping Start")
+
+ if probe.type != "PLANAR":
+ sub.prop(probe, "clip_end", text="End")
+
+ if probe.type == 'GRID':
+ col.separator()
+ col.label("Visibility")
+ col.prop(probe, "visibility_buffer_bias", "Bias")
+ col.prop(probe, "visibility_bleed_bias", "Bleed Bias")
+ col.prop(probe, "visibility_blur", "Blur")
+
+ col.separator()
+
+ row = col.row(align=True)
+ row.prop(probe, "visibility_collection")
+ row.prop(probe, "invert_visibility_collection", text="", icon='ARROW_LEFTRIGHT')
+
+
+class DATA_PT_lightprobe_parallax(DataButtonsPanel, Panel):
+ bl_label = "Custom Parallax"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.engine
+ return context.lightprobe and context.lightprobe.type == 'CUBEMAP' and (engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ probe = context.lightprobe
+ self.layout.prop(probe, "use_custom_parallax", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ probe = context.lightprobe
+
+ col = layout.column()
+ col.active = probe.use_custom_parallax
+
+ col.prop(probe, "parallax_type")
+
+ if probe.parallax_type == 'ELIPSOID':
+ col.prop(probe, "parallax_distance", "Radius")
+ else:
+ col.prop(probe, "parallax_distance", "Size")
+
+
+class DATA_PT_lightprobe_display(DataButtonsPanel, Panel):
+ bl_label = "Display"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+ probe = context.lightprobe
+
+ col = layout.column()
+
+ if probe.type != 'PLANAR':
+ col.prop(probe, "data_draw_size", text="Size")
+ else:
+ col.prop(ob, "empty_draw_size", text="Arrow Size")
+
+ col.prop(probe, "show_data")
+
+ if probe.type in {'GRID', 'CUBEMAP'}:
+ col.prop(probe, "show_influence")
+ col.prop(probe, "show_clip")
+
+ if probe.type == 'CUBEMAP':
+ sub = col.column()
+ sub.active = probe.use_custom_parallax
+ sub.prop(probe, "show_parallax")
+
+
+classes = (
+ DATA_PT_context_lightprobe,
+ DATA_PT_lightprobe,
+ DATA_PT_lightprobe_parallax,
+ DATA_PT_lightprobe_display,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 2ab9aa2e93f..e8015327c1d 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -24,7 +24,7 @@ from rna_prop_ui import PropertyPanel
class MESH_MT_vertex_group_specials(Menu):
bl_label = "Vertex Group Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -48,7 +48,7 @@ class MESH_MT_vertex_group_specials(Menu):
class MESH_MT_shape_key_specials(Menu):
bl_label = "Shape Key Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -76,6 +76,17 @@ class MESH_UL_vgroups(UIList):
layout.label(text="", icon_value=icon)
+class MESH_UL_fmaps(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.FaceMap))
+ fmap = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.prop(fmap, "name", text="", emboss=False, icon_value=icon)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
class MESH_UL_shape_keys(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.ShapeKey))
@@ -119,14 +130,14 @@ class MeshButtonsPanel:
@classmethod
def poll(cls, context):
- engine = context.scene.render.engine
+ engine = context.engine
return context.mesh and (engine in cls.COMPAT_ENGINES)
class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -143,31 +154,31 @@ class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
class DATA_PT_normals(MeshButtonsPanel, Panel):
bl_label = "Normals"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
mesh = context.mesh
- split = layout.split()
+ col = layout.column()
+ col.prop(mesh, "show_double_sided")
- col = split.column()
col.prop(mesh, "use_auto_smooth")
sub = col.column()
sub.active = mesh.use_auto_smooth and not mesh.has_custom_normals
sub.prop(mesh, "auto_smooth_angle", text="Angle")
- split.prop(mesh, "show_double_sided")
-
class DATA_PT_texture_space(MeshButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
mesh = context.mesh
@@ -176,18 +187,18 @@ class DATA_PT_texture_space(MeshButtonsPanel, Panel):
layout.separator()
layout.prop(mesh, "use_auto_texspace")
- row = layout.row()
- row.column().prop(mesh, "texspace_location", text="Location")
- row.column().prop(mesh, "texspace_size", text="Size")
+
+ layout.prop(mesh, "texspace_location", text="Location")
+ layout.prop(mesh, "texspace_size", text="Size")
class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
bl_label = "Vertex Groups"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- engine = context.scene.render.engine
+ engine = context.engine
obj = context.object
return (obj and obj.type in {'MESH', 'LATTICE'} and (engine in cls.COMPAT_ENGINES))
@@ -228,13 +239,55 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
+class DATA_PT_face_maps(MeshButtonsPanel, Panel):
+ bl_label = "Face Maps"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.type == 'MESH')
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ facemap = ob.face_maps.active
+
+ rows = 2
+ if facemap:
+ rows = 4
+
+ row = layout.row()
+ row.template_list("MESH_UL_fmaps", "", ob, "face_maps", ob.face_maps, "active_index", rows=rows)
+
+ col = row.column(align=True)
+ col.operator("object.face_map_add", icon='ZOOMIN', text="")
+ col.operator("object.face_map_remove", icon='ZOOMOUT', text="")
+ if facemap:
+ col.separator()
+ col.operator("object.face_map_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("object.face_map_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
+ if ob.face_maps and (ob.mode == 'EDIT' and ob.type == 'MESH'):
+ row = layout.row()
+
+ sub = row.row(align=True)
+ sub.operator("object.face_map_assign", text="Assign")
+ sub.operator("object.face_map_remove_from", text="Remove")
+
+ sub = row.row(align=True)
+ sub.operator("object.face_map_select", text="Select")
+ sub.operator("object.face_map_deselect", text="Deselect")
+
+
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
bl_label = "Shape Keys"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- engine = context.scene.render.engine
+ engine = context.engine
obj = context.object
return (obj and obj.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'} and (engine in cls.COMPAT_ENGINES))
@@ -300,19 +353,16 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
row.active = enable_edit_value
row.prop(kb, "value")
- split = layout.split()
+ layout.use_property_split = True
- col = split.column(align=True)
- col.active = enable_edit_value
- col.label(text="Range:")
- col.prop(kb, "slider_min", text="Min")
- col.prop(kb, "slider_max", text="Max")
+ col = layout.column()
+ sub.active = enable_edit_value
+ sub = col.column(align=True)
+ sub.prop(kb, "slider_min", text="Range Min")
+ sub.prop(kb, "slider_max", text="Max")
- col = split.column(align=True)
- col.active = enable_edit_value
- col.label(text="Blend:")
- col.prop_search(kb, "vertex_group", ob, "vertex_groups", text="")
- col.prop_search(kb, "relative_key", key, "key_blocks", text="")
+ col.prop_search(kb, "vertex_group", ob, "vertex_groups", text="Vertex Group")
+ col.prop_search(kb, "relative_key", key, "key_blocks", text="Relative To")
else:
layout.prop(kb, "interpolation")
@@ -323,7 +373,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
bl_label = "UV Maps"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -333,7 +383,7 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list("MESH_UL_uvmaps_vcols", "uvmaps", me, "uv_textures", me.uv_textures, "active_index", rows=1)
+ col.template_list("MESH_UL_uvmaps_vcols", "uvmaps", me, "uv_layers", me.uv_layers, "active_index", rows=1)
col = row.column(align=True)
col.operator("mesh.uv_texture_add", icon='ZOOMIN', text="")
@@ -342,7 +392,7 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
bl_label = "Vertex Colors"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -362,10 +412,11 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
class DATA_PT_customdata(MeshButtonsPanel, Panel):
bl_label = "Geometry Data"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
obj = context.object
me = context.mesh
@@ -388,7 +439,7 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "object.data"
_property_type = bpy.types.Mesh
@@ -397,12 +448,14 @@ classes = (
MESH_MT_vertex_group_specials,
MESH_MT_shape_key_specials,
MESH_UL_vgroups,
+ MESH_UL_fmaps,
MESH_UL_shape_keys,
MESH_UL_uvmaps_vcols,
DATA_PT_context_mesh,
DATA_PT_normals,
DATA_PT_texture_space,
DATA_PT_vertex_groups,
+ DATA_PT_face_maps,
DATA_PT_shape_keys,
DATA_PT_uv_texture,
DATA_PT_vertex_colors,
diff --git a/release/scripts/startup/bl_ui/properties_data_metaball.py b/release/scripts/startup/bl_ui/properties_data_metaball.py
index dd62c4523b1..2a61e6cda79 100644
--- a/release/scripts/startup/bl_ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -54,40 +54,36 @@ class DATA_PT_metaball(DataButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
mball = context.meta_ball
- split = layout.split()
-
- col = split.column()
+ col = layout.column()
col.label(text="Resolution:")
sub = col.column(align=True)
- sub.prop(mball, "resolution", text="View")
+ sub.prop(mball, "resolution", text="Resolution View")
sub.prop(mball, "render_resolution", text="Render")
- col = split.column()
- col.label(text="Settings:")
col.prop(mball, "threshold", text="Threshold")
-
- layout.label(text="Update:")
- layout.row().prop(mball, "update_method", expand=True)
+ col.prop(mball, "update_method")
class DATA_PT_mball_texture_space(DataButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
mball = context.meta_ball
layout.prop(mball, "use_auto_texspace")
- row = layout.row()
- row.column().prop(mball, "texspace_location", text="Location")
- row.column().prop(mball, "texspace_size", text="Size")
+ col = layout.column()
+ col.prop(mball, "texspace_location")
+ col.prop(mball, "texspace_size")
class DATA_PT_metaball_element(DataButtonsPanel, Panel):
@@ -99,39 +95,37 @@ class DATA_PT_metaball_element(DataButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
metaelem = context.meta_ball.elements.active
- layout.prop(metaelem, "type")
+ col = layout.column()
- split = layout.split()
+ col.prop(metaelem, "type")
+
+ col.separator()
- col = split.column(align=True)
- col.label(text="Settings:")
col.prop(metaelem, "stiffness", text="Stiffness")
col.prop(metaelem, "use_negative", text="Negative")
col.prop(metaelem, "hide", text="Hide")
- col = split.column(align=True)
+ sub = col.column(align=True)
if metaelem.type in {'CUBE', 'ELLIPSOID'}:
- col.label(text="Size:")
- col.prop(metaelem, "size_x", text="X")
- col.prop(metaelem, "size_y", text="Y")
- col.prop(metaelem, "size_z", text="Z")
+ sub.prop(metaelem, "size_x", text="Size X")
+ sub.prop(metaelem, "size_y", text="Y")
+ sub.prop(metaelem, "size_z", text="Z")
elif metaelem.type == 'TUBE':
- col.label(text="Size:")
- col.prop(metaelem, "size_x", text="X")
+ sub.prop(metaelem, "size_x", text="Size X")
elif metaelem.type == 'PLANE':
- col.label(text="Size:")
- col.prop(metaelem, "size_x", text="X")
- col.prop(metaelem, "size_y", text="Y")
+ sub.prop(metaelem, "size_x", text="Size X")
+ sub.prop(metaelem, "size_y", text="Y")
class DATA_PT_custom_props_metaball(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "object.data"
_property_type = bpy.types.MetaBall
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index a147950a36d..03ebea69d2b 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -327,8 +327,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.prop(md, "delimit")
layout_info = layout
- layout_info.label(text=iface_("Face Count: {:,}".format(md.face_count)),
- translate=False)
+ layout_info.label(
+ text=iface_("Face Count: {:,}".format(md.face_count)),
+ translate=False,
+ )
def DISPLACE(self, layout, ob, md):
has_texture = (md.texture is not None)
@@ -357,7 +359,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "texture_coords_object", text="")
elif md.texture_coords == 'UV' and ob.type == 'MESH':
col.label(text="UV Map:")
- col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
+ col.prop_search(md, "uv_layer", ob.data, "uv_layers", text="")
layout.separator()
@@ -389,7 +391,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
sub.active = bool(md.vertex_group)
sub.prop(md, "protect")
col.label(text="Particle UV")
- col.prop_search(md, "particle_uv", ob.data, "uv_textures", text="")
+ col.prop_search(md, "particle_uv", ob.data, "uv_layers", text="")
col = split.column()
col.prop(md, "use_edge_cut")
@@ -951,7 +953,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
scene = context.scene
- engine = scene.render.engine
+ engine = context.engine
show_adaptive_options = (
engine == 'CYCLES' and md == ob.modifiers[-1] and
scene.cycles.feature_set == 'EXPERIMENTAL'
@@ -1014,18 +1016,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
def UV_PROJECT(self, layout, ob, md):
split = layout.split()
-
- col = split.column()
- col.label(text="Image:")
- col.prop(md, "image", text="")
-
col = split.column()
- col.label(text="UV Map:")
- col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
+ col.prop_search(md, "uv_layer", ob.data, "uv_layers")
+ col.separator()
- split = layout.split()
- col = split.column()
- col.prop(md, "use_image_override")
col.prop(md, "projector_count", text="Projectors")
for proj in md.projectors:
col.prop(proj, "object", text="")
@@ -1079,7 +1073,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
if md.texture_coords == 'OBJECT':
layout.prop(md, "texture_coords_object", text="Object")
elif md.texture_coords == 'UV' and ob.type == 'MESH':
- layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
+ layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
def WAVE(self, layout, ob, md):
split = layout.split()
@@ -1125,7 +1119,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.template_ID(md, "texture", new="texture.new")
layout.prop(md, "texture_coords")
if md.texture_coords == 'UV' and ob.type == 'MESH':
- layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
+ layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
elif md.texture_coords == 'OBJECT':
layout.prop(md, "texture_coords_object")
@@ -1192,7 +1186,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
if md.mask_tex_mapping == 'OBJECT':
layout.prop(md, "mask_tex_map_object", text="Object")
elif md.mask_tex_mapping == 'UV' and ob.type == 'MESH':
- layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_textures")
+ layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_layers")
def VERTEX_WEIGHT_EDIT(self, layout, ob, md):
split = layout.split()
@@ -1361,7 +1355,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.label(text="UV Map:")
- col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
+ col.prop_search(md, "uv_layer", ob.data, "uv_layers", text="")
def WIREFRAME(self, layout, ob, md):
has_vgroup = bool(md.vertex_group)
diff --git a/release/scripts/startup/bl_ui/properties_data_speaker.py b/release/scripts/startup/bl_ui/properties_data_speaker.py
index eecb2690302..2a3dc4d02c1 100644
--- a/release/scripts/startup/bl_ui/properties_data_speaker.py
+++ b/release/scripts/startup/bl_ui/properties_data_speaker.py
@@ -29,14 +29,14 @@ class DataButtonsPanel:
@classmethod
def poll(cls, context):
- engine = context.scene.render.engine
+ engine = context.engine
return context.speaker and (engine in cls.COMPAT_ENGINES)
class DATA_PT_context_speaker(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -55,69 +55,73 @@ class DATA_PT_context_speaker(DataButtonsPanel, Panel):
class DATA_PT_speaker(DataButtonsPanel, Panel):
bl_label = "Sound"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
speaker = context.speaker
- split = layout.split(percentage=0.75)
+ layout.template_ID(speaker, "sound", open="sound.open_mono")
- split.template_ID(speaker, "sound", open="sound.open_mono")
- split.prop(speaker, "muted")
+ layout.use_property_split = True
- row = layout.row()
- row.prop(speaker, "volume")
- row.prop(speaker, "pitch")
+ layout.prop(speaker, "muted")
+
+ col = layout.column()
+ col.active = not speaker.muted
+ col.prop(speaker, "volume", slider=True)
+ col.prop(speaker, "pitch")
class DATA_PT_distance(DataButtonsPanel, Panel):
bl_label = "Distance"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
- speaker = context.speaker
+ layout.use_property_split = True
- split = layout.split()
+ speaker = context.speaker
+ layout.active = not speaker.muted
- col = split.column()
- col.label("Volume:")
- col.prop(speaker, "volume_min", text="Minimum")
- col.prop(speaker, "volume_max", text="Maximum")
+ col = layout.column()
+ sub = col.column(align=True)
+ sub.prop(speaker, "volume_min", slider=True, text="Volume Min")
+ sub.prop(speaker, "volume_max", slider=True, text="Max")
col.prop(speaker, "attenuation")
- col = split.column()
- col.label("Distance:")
- col.prop(speaker, "distance_max", text="Maximum")
- col.prop(speaker, "distance_reference", text="Reference")
+ col.separator()
+ col.prop(speaker, "distance_max", text="Max Distance")
+ col.prop(speaker, "distance_reference", text="Distance Reference")
class DATA_PT_cone(DataButtonsPanel, Panel):
bl_label = "Cone"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
speaker = context.speaker
+ layout.active = not speaker.muted
+
+ col = layout.column()
- split = layout.split()
+ sub = col.column(align=True)
+ sub.prop(speaker, "cone_angle_outer", text="Angle Outer")
+ sub.prop(speaker, "cone_angle_inner", text="Inner")
- col = split.column()
- col.label("Angle:")
- col.prop(speaker, "cone_angle_outer", text="Outer")
- col.prop(speaker, "cone_angle_inner", text="Inner")
+ col.separator()
- col = split.column()
- col.label("Volume:")
- col.prop(speaker, "cone_volume_outer", text="Outer")
+ col.prop(speaker, "cone_volume_outer", slider=True)
class DATA_PT_custom_props_speaker(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "object.data"
_property_type = bpy.types.Speaker
diff --git a/release/scripts/startup/bl_ui/properties_data_workspace.py b/release/scripts/startup/bl_ui/properties_data_workspace.py
new file mode 100644
index 00000000000..3cda3dd0abd
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_workspace.py
@@ -0,0 +1,101 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import (
+ Panel,
+)
+
+from rna_prop_ui import PropertyPanel
+
+
+class WorkSpaceButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "workspace"
+
+
+class WORKSPACE_PT_owner_ids(WorkSpaceButtonsPanel, Panel):
+ bl_label = "Workspace Add-ons"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header(self, context):
+ workspace = context.workspace
+ self.layout.prop(workspace, "use_filter_by_owner", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ # align just to pack more tightly
+ col = layout.box().column(align=True)
+
+ workspace = context.workspace
+ userpref = context.user_preferences
+
+ col.active = workspace.use_filter_by_owner
+
+ import addon_utils
+ addon_map = {mod.__name__: mod for mod in addon_utils.modules()}
+ owner_ids = {owner_id.name for owner_id in workspace.owner_ids}
+
+ for addon in userpref.addons:
+ module_name = addon.module
+ info = addon_utils.module_bl_info(addon_map[module_name])
+ if not info["use_owner"]:
+ continue
+ is_enabled = module_name in owner_ids
+ row = col.row()
+ row.operator(
+ "wm.owner_disable" if is_enabled else "wm.owner_enable",
+ icon='CHECKBOX_HLT' if is_enabled else 'CHECKBOX_DEHLT',
+ text="",
+ emboss=False,
+ ).owner_id = module_name
+ row.label("%s: %s" % (info["category"], info["name"]))
+ if is_enabled:
+ owner_ids.remove(module_name)
+
+ # Detect unused
+ if owner_ids:
+ layout.label(text="Unknown add-ons", icon='ERROR')
+ col = layout.box().column(align=True)
+ for module_name in sorted(owner_ids):
+ row = col.row()
+ row.operator(
+ "wm.owner_disable",
+ icon='CHECKBOX_HLT',
+ text="",
+ emboss=False,
+ ).owner_id = module_name
+ row.label(module_name)
+
+
+class WORKSPACE_PT_custom_props(WorkSpaceButtonsPanel, PropertyPanel, Panel):
+ _context_path = "workspace"
+ _property_type = bpy.types.WorkSpace
+
+
+classes = (
+ WORKSPACE_PT_owner_ids,
+ WORKSPACE_PT_custom_props,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index 7b656f9be81..12ecbeb3e6b 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -33,13 +33,13 @@ class RenderFreestyleButtonsPanel:
def poll(cls, context):
scene = context.scene
with_freestyle = bpy.app.build_options.freestyle
- return scene and with_freestyle and(scene.render.engine in cls.COMPAT_ENGINES)
+ return scene and with_freestyle and(context.engine in cls.COMPAT_ENGINES)
class RENDER_PT_freestyle(RenderFreestyleButtonsPanel, Panel):
bl_label = "Freestyle"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
rd = context.scene.render
@@ -62,34 +62,34 @@ class RENDER_PT_freestyle(RenderFreestyleButtonsPanel, Panel):
# Render layer properties
-class RenderLayerFreestyleButtonsPanel:
+class ViewLayerFreestyleButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
- bl_context = "render_layer"
+ bl_context = "view_layer"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
@classmethod
def poll(cls, context):
scene = context.scene
- rd = context.scene.render
+ rd = scene.render
with_freestyle = bpy.app.build_options.freestyle
return (scene and with_freestyle and rd.use_freestyle and
- rd.layers.active and(scene.render.engine in cls.COMPAT_ENGINES))
+ (context.engine in cls.COMPAT_ENGINES))
-class RenderLayerFreestyleEditorButtonsPanel(RenderLayerFreestyleButtonsPanel):
+class ViewLayerFreestyleEditorButtonsPanel(ViewLayerFreestyleButtonsPanel):
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
@classmethod
def poll(cls, context):
if not super().poll(context):
return False
- rl = context.scene.render.layers.active
- return rl and rl.freestyle_settings.mode == 'EDITOR'
+ view_layer = context.view_layer
+ return view_layer and view_layer.freestyle_settings.mode == 'EDITOR'
-class RENDERLAYER_UL_linesets(UIList):
+class VIEWLAYER_UL_linesets(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
lineset = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
@@ -109,18 +109,18 @@ class RENDER_MT_lineset_specials(Menu):
layout.operator("scene.freestyle_lineset_paste", icon='PASTEDOWN')
-class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
+class VIEWLAYER_PT_freestyle(ViewLayerFreestyleButtonsPanel, Panel):
bl_label = "Freestyle"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
- rd = context.scene.render
- rl = rd.layers.active
- freestyle = rl.freestyle_settings
+ scene = context.scene
+ view_layer = context.view_layer
+ freestyle = view_layer.freestyle_settings
- layout.active = rl.use_freestyle
+ layout.active = view_layer.use_freestyle
row = layout.row()
layout.prop(freestyle, "mode", text="Control Mode")
@@ -165,9 +165,9 @@ class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
row.operator("scene.freestyle_module_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
-class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, Panel):
+class VIEWLAYER_PT_freestyle_lineset(ViewLayerFreestyleEditorButtonsPanel, Panel):
bl_label = "Freestyle Line Set"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_edge_type_buttons(self, box, lineset, edge_type):
# property names
@@ -183,16 +183,18 @@ class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, P
def draw(self, context):
layout = self.layout
- rd = context.scene.render
- rl = rd.layers.active
- freestyle = rl.freestyle_settings
+ scene = context.scene
+ rd = scene.render
+
+ view_layer = context.view_layer
+ freestyle = view_layer.freestyle_settings
lineset = freestyle.linesets.active
- layout.active = rl.use_freestyle
+ layout.active = view_layer.use_freestyle
row = layout.row()
rows = 4 if lineset else 2
- row.template_list("RENDERLAYER_UL_linesets", "", freestyle, "linesets", freestyle.linesets, "active_index", rows=rows)
+ row.template_list("VIEWLAYER_UL_linesets", "", freestyle, "linesets", freestyle.linesets, "active_index", rows=rows)
sub = row.column(align=True)
sub.operator("scene.freestyle_lineset_add", icon='ZOOMIN', text="")
@@ -256,10 +258,10 @@ class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, P
row.prop(lineset, "group_negation", expand=True)
-class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, Panel):
+class VIEWLAYER_PT_freestyle_linestyle(ViewLayerFreestyleEditorButtonsPanel, Panel):
bl_label = "Freestyle Line Style"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_modifier_box_header(self, box, modifier):
row = box.row()
@@ -376,7 +378,7 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
row = box.row(align=True)
row.prop(modifier, "curvature_min")
row.prop(modifier, "curvature_max")
- freestyle = context.scene.render.layers.active.freestyle_settings
+ freestyle = context.view_layer.freestyle_settings
if not freestyle.use_smoothness:
message = "Enable Face Smoothness to use this modifier"
self.draw_modifier_box_error(col.box(), modifier, message)
@@ -431,7 +433,7 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
row = box.row(align=True)
row.prop(modifier, "curvature_min")
row.prop(modifier, "curvature_max")
- freestyle = context.scene.render.layers.active.freestyle_settings
+ freestyle = context.view_layer.freestyle_settings
if not freestyle.use_smoothness:
message = "Enable Face Smoothness to use this modifier"
self.draw_modifier_box_error(col.box(), modifier, message)
@@ -503,7 +505,7 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
row = box.row(align=True)
row.prop(modifier, "curvature_min")
row.prop(modifier, "curvature_max")
- freestyle = context.scene.render.layers.active.freestyle_settings
+ freestyle = context.view_layer.freestyle_settings
if not freestyle.use_smoothness:
message = "Enable Face Smoothness to use this modifier"
self.draw_modifier_box_error(col.box(), modifier, message)
@@ -611,11 +613,11 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
def draw(self, context):
layout = self.layout
- rd = context.scene.render
- rl = rd.layers.active
- lineset = rl.freestyle_settings.linesets.active
+ scene = context.scene
+ view_layer = context.view_layer
+ lineset = view_layer.freestyle_settings.linesets.active
- layout.active = rl.use_freestyle
+ layout.active = view_layer.use_freestyle
if lineset is None:
return
@@ -779,10 +781,7 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel,
layout.separator()
row = layout.row()
- if rd.use_shading_nodes:
- row.prop(linestyle, "use_nodes")
- else:
- row.prop(linestyle, "use_texture")
+ row.prop(linestyle, "use_nodes")
row.prop(linestyle, "texture_spacing", text="Spacing Along Stroke")
row = layout.row()
@@ -811,13 +810,13 @@ class MaterialFreestyleButtonsPanel:
material = context.material
with_freestyle = bpy.app.build_options.freestyle
return with_freestyle and material and scene and scene.render.use_freestyle and \
- (scene.render.engine in cls.COMPAT_ENGINES)
+ (context.engine in cls.COMPAT_ENGINES)
class MATERIAL_PT_freestyle_line(MaterialFreestyleButtonsPanel, Panel):
bl_label = "Freestyle Line"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -831,11 +830,11 @@ class MATERIAL_PT_freestyle_line(MaterialFreestyleButtonsPanel, Panel):
classes = (
RENDER_PT_freestyle,
- RENDERLAYER_UL_linesets,
+ VIEWLAYER_UL_linesets,
RENDER_MT_lineset_specials,
- RENDERLAYER_PT_freestyle,
- RENDERLAYER_PT_freestyle_lineset,
- RENDERLAYER_PT_freestyle_linestyle,
+ VIEWLAYER_PT_freestyle,
+ VIEWLAYER_PT_freestyle_lineset,
+ VIEWLAYER_PT_freestyle_linestyle,
MATERIAL_PT_freestyle_line,
)
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
deleted file mode 100644
index ac51b97e87d..00000000000
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ /dev/null
@@ -1,881 +0,0 @@
-# ##### 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.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-import bpy
-from bpy.types import Panel, Menu
-
-
-class PhysicsButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "physics"
-
-
-class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
- bl_label = "Physics"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- ob = context.active_object
- rd = context.scene.render
- return ob and ob.game and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.active_object
- game = ob.game
- soft = ob.game.soft_body
-
- layout.prop(game, "physics_type")
- layout.separator()
-
- physics_type = game.physics_type
-
- if physics_type == 'CHARACTER':
- layout.prop(game, "use_actor")
- layout.prop(ob, "hide_render", text="Invisible") # out of place but useful
- layout.prop(game, "step_height", slider=True)
- layout.prop(game, "jump_speed")
- layout.prop(game, "fall_speed")
- layout.prop(game, "jump_max")
-
- elif physics_type in {'DYNAMIC', 'RIGID_BODY'}:
- split = layout.split()
-
- col = split.column()
- col.prop(game, "use_actor")
- col.prop(game, "use_ghost")
- col.prop(ob, "hide_render", text="Invisible") # out of place but useful
-
- col = split.column()
- col.prop(game, "use_material_physics_fh")
- col.prop(game, "use_rotate_from_normal")
- col.prop(game, "use_sleep")
-
- layout.separator()
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Attributes:")
- col.prop(game, "mass")
- col.prop(game, "radius")
- col.prop(game, "form_factor")
-
- col = split.column()
- sub = col.column()
- sub.prop(game, "use_anisotropic_friction")
- subsub = sub.column()
- subsub.active = game.use_anisotropic_friction
- subsub.prop(game, "friction_coefficients", text="", slider=True)
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Linear Velocity:")
- sub = col.column(align=True)
- sub.prop(game, "velocity_min", text="Minimum")
- sub.prop(game, "velocity_max", text="Maximum")
- col.label(text="Angular Velocity:")
- sub = col.column(align=True)
- sub.prop(game, "angular_velocity_min", text="Minimum")
- sub.prop(game, "angular_velocity_max", text="Maximum")
-
- col = split.column()
- col.label(text="Damping:")
- sub = col.column(align=True)
- sub.prop(game, "damping", text="Translation", slider=True)
- sub.prop(game, "rotation_damping", text="Rotation", slider=True)
-
- layout.separator()
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Lock Translation:")
- col.prop(game, "lock_location_x", text="X")
- col.prop(game, "lock_location_y", text="Y")
- col.prop(game, "lock_location_z", text="Z")
-
- if physics_type == 'RIGID_BODY':
- col = split.column()
- col.label(text="Lock Rotation:")
- col.prop(game, "lock_rotation_x", text="X")
- col.prop(game, "lock_rotation_y", text="Y")
- col.prop(game, "lock_rotation_z", text="Z")
-
- elif physics_type == 'SOFT_BODY':
- col = layout.column()
- col.prop(game, "use_actor")
- col.prop(game, "use_ghost")
- col.prop(ob, "hide_render", text="Invisible")
-
- layout.separator()
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Attributes:")
- col.prop(game, "mass")
- # disabled in the code
- # col.prop(soft, "weld_threshold")
- col.prop(soft, "location_iterations")
- col.prop(soft, "linear_stiffness", slider=True)
- col.prop(soft, "dynamic_friction", slider=True)
- col.prop(soft, "collision_margin", slider=True)
- col.prop(soft, "use_bending_constraints", text="Bending Constraints")
-
- col = split.column()
- col.prop(soft, "use_shape_match")
- sub = col.column()
- sub.active = soft.use_shape_match
- sub.prop(soft, "shape_threshold", slider=True)
-
- col.separator()
-
- col.label(text="Cluster Collision:")
- col.prop(soft, "use_cluster_rigid_to_softbody")
- col.prop(soft, "use_cluster_soft_to_softbody")
- sub = col.column()
- sub.active = (soft.use_cluster_rigid_to_softbody or soft.use_cluster_soft_to_softbody)
- sub.prop(soft, "cluster_iterations", text="Iterations")
-
- elif physics_type == 'STATIC':
- col = layout.column()
- col.prop(game, "use_actor")
- col.prop(game, "use_ghost")
- col.prop(game, "use_record_animation")
- col.prop(ob, "hide_render", text="Invisible")
-
- layout.separator()
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Attributes:")
- col.prop(game, "radius")
-
- col = split.column()
- sub = col.column()
- sub.prop(game, "use_anisotropic_friction")
- subsub = sub.column()
- subsub.active = game.use_anisotropic_friction
- subsub.prop(game, "friction_coefficients", text="", slider=True)
-
- elif physics_type == 'SENSOR':
- col = layout.column()
- col.prop(game, "use_actor", text="Detect Actors")
- col.prop(ob, "hide_render", text="Invisible")
-
- elif physics_type in {'INVISIBLE', 'NO_COLLISION', 'OCCLUDER'}:
- layout.prop(ob, "hide_render", text="Invisible")
-
- elif physics_type == 'NAVMESH':
- layout.operator("mesh.navmesh_face_copy")
- layout.operator("mesh.navmesh_face_add")
-
- layout.separator()
-
- layout.operator("mesh.navmesh_reset")
- layout.operator("mesh.navmesh_clear")
-
-
-class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
- bl_label = "Collision Bounds"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- game = context.object.game
- rd = context.scene.render
- return (rd.engine in cls.COMPAT_ENGINES) \
- and (game.physics_type in {'SENSOR', 'STATIC', 'DYNAMIC', 'RIGID_BODY', 'CHARACTER', 'SOFT_BODY'})
-
- def draw_header(self, context):
- game = context.active_object.game
-
- self.layout.prop(game, "use_collision_bounds", text="")
-
- def draw(self, context):
- layout = self.layout
-
- game = context.active_object.game
- split = layout.split()
- split.active = game.use_collision_bounds
-
- col = split.column()
- col.prop(game, "collision_bounds_type", text="Bounds")
-
- row = col.row()
- row.prop(game, "collision_margin", text="Margin", slider=True)
-
- sub = row.row()
- sub.active = game.physics_type not in {'SOFT_BODY', 'CHARACTER'}
- sub.prop(game, "use_collision_compound", text="Compound")
-
- layout.separator()
- split = layout.split()
- col = split.column()
- col.prop(game, "collision_group")
- col = split.column()
- col.prop(game, "collision_mask")
-
-
-class PHYSICS_PT_game_obstacles(PhysicsButtonsPanel, Panel):
- bl_label = "Create Obstacle"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- game = context.object.game
- rd = context.scene.render
- return (rd.engine in cls.COMPAT_ENGINES) \
- and (game.physics_type in {'SENSOR', 'STATIC', 'DYNAMIC', 'RIGID_BODY', 'SOFT_BODY', 'CHARACTER', 'NO_COLLISION'})
-
- def draw_header(self, context):
- game = context.active_object.game
-
- self.layout.prop(game, "use_obstacle_create", text="")
-
- def draw(self, context):
- layout = self.layout
-
- game = context.active_object.game
-
- layout.active = game.use_obstacle_create
-
- row = layout.row()
- row.prop(game, "obstacle_radius", text="Radius")
- row.label()
-
-
-class RenderButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "render"
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return (rd.engine in cls.COMPAT_ENGINES)
-
-
-class RENDER_PT_embedded(RenderButtonsPanel, Panel):
- bl_label = "Embedded Player"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render
-
- row = layout.row()
- row.operator("view3d.game_start", text="Start")
- row = layout.row()
- row.label(text="Resolution:")
- row = layout.row(align=True)
- row.prop(rd, "resolution_x", slider=False, text="X")
- row.prop(rd, "resolution_y", slider=False, text="Y")
-
-
-class RENDER_PT_game_player(RenderButtonsPanel, Panel):
- bl_label = "Standalone Player"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- def draw(self, context):
- import sys
- layout = self.layout
- not_osx = sys.platform != "darwin"
-
- gs = context.scene.game_settings
-
- row = layout.row()
- row.operator("wm.blenderplayer_start", text="Start")
- row = layout.row()
- row.label(text="Resolution:")
- row = layout.row(align=True)
- row.active = not_osx or not gs.show_fullscreen
- row.prop(gs, "resolution_x", slider=False, text="X")
- row.prop(gs, "resolution_y", slider=False, text="Y")
- row = layout.row()
- col = row.column()
- col.prop(gs, "show_fullscreen")
-
- if not_osx:
- col = row.column()
- col.prop(gs, "use_desktop")
- col.active = gs.show_fullscreen
-
- col = layout.column()
- col.label(text="Quality:")
- col.prop(gs, "samples")
- col = layout.column(align=True)
- col.prop(gs, "depth", text="Bit Depth", slider=False)
- col.prop(gs, "frequency", text="Refresh Rate", slider=False)
-
-
-class RENDER_PT_game_stereo(RenderButtonsPanel, Panel):
- bl_label = "Stereo"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
- stereo_mode = gs.stereo
-
- # stereo options:
- layout.row().prop(gs, "stereo", expand=True)
-
- # stereo:
- if stereo_mode == 'STEREO':
- layout.prop(gs, "stereo_mode")
- layout.prop(gs, "stereo_eye_separation")
-
- # dome:
- elif stereo_mode == 'DOME':
- layout.prop(gs, "dome_mode", text="Dome Type")
-
- dome_type = gs.dome_mode
-
- split = layout.split()
-
- if dome_type in {'FISHEYE', 'TRUNCATED_REAR', 'TRUNCATED_FRONT'}:
- col = split.column()
- col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
- col.prop(gs, "dome_angle", slider=True)
-
- col = split.column()
- col.prop(gs, "dome_tessellation", text="Tessellation")
- col.prop(gs, "dome_tilt")
-
- elif dome_type == 'PANORAM_SPH':
- col = split.column()
- col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
-
- col = split.column()
- col.prop(gs, "dome_tessellation", text="Tessellation")
-
- else: # cube map
- col = split.column()
- col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
-
- col = split.column()
-
- layout.prop(gs, "dome_text")
-
-
-class RENDER_PT_game_shading(RenderButtonsPanel, Panel):
- bl_label = "Shading"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
-
- layout.row().prop(gs, "material_mode", expand=True)
-
- if gs.material_mode == 'GLSL':
- split = layout.split()
-
- col = split.column()
- col.prop(gs, "use_glsl_lights", text="Lights")
- col.prop(gs, "use_glsl_shaders", text="Shaders")
- col.prop(gs, "use_glsl_shadows", text="Shadows")
- col.prop(gs, "use_glsl_environment_lighting", text="Environment Lighting")
-
- col = split.column()
- col.prop(gs, "use_glsl_ramps", text="Ramps")
- col.prop(gs, "use_glsl_nodes", text="Nodes")
- col.prop(gs, "use_glsl_extra_textures", text="Extra Textures")
-
-
-class RENDER_PT_game_system(RenderButtonsPanel, Panel):
- bl_label = "System"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
- col = layout.column()
- row = col.row()
- col = row.column()
- col.prop(gs, "use_frame_rate")
- col.prop(gs, "use_restrict_animation_updates")
- col.prop(gs, "use_material_caching")
- col = row.column()
- col.prop(gs, "use_display_lists")
- col.active = gs.raster_storage != 'VERTEX_BUFFER_OBJECT'
-
- row = layout.row()
- row.prop(gs, "vsync")
-
- row = layout.row()
- row.prop(gs, "raster_storage")
-
- row = layout.row()
- row.label("Exit Key")
- row.prop(gs, "exit_key", text="", event=True)
-
-
-class RENDER_PT_game_display(RenderButtonsPanel, Panel):
- bl_label = "Display"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
-
- layout.prop(context.scene.render, "fps", text="Animation Frame Rate", slider=False)
-
- flow = layout.column_flow()
- flow.prop(gs, "show_debug_properties", text="Debug Properties")
- flow.prop(gs, "show_framerate_profile", text="Framerate and Profile")
- flow.prop(gs, "show_physics_visualization", text="Physics Visualization")
- flow.prop(gs, "use_deprecation_warnings")
- flow.prop(gs, "show_mouse", text="Mouse Cursor")
-
- col = layout.column()
- col.label(text="Framing:")
- col.row().prop(gs, "frame_type", expand=True)
- if gs.frame_type == 'LETTERBOX':
- col.prop(gs, "frame_color", text="")
-
-
-class SceneButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "scene"
-
-
-class SCENE_PT_game_physics(SceneButtonsPanel, Panel):
- bl_label = "Physics"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
-
- layout.prop(gs, "physics_engine", text="Engine")
- if gs.physics_engine != 'NONE':
- layout.prop(gs, "physics_gravity", text="Gravity")
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Physics Steps:")
- sub = col.column(align=True)
- sub.prop(gs, "physics_step_max", text="Max")
- sub.prop(gs, "physics_step_sub", text="Substeps")
- col.prop(gs, "fps", text="FPS")
-
- col = split.column()
- col.label(text="Logic Steps:")
- col.prop(gs, "logic_step_max", text="Max")
-
- col = layout.column()
- col.label(text="Physics Deactivation:")
- sub = col.row(align=True)
- sub.prop(gs, "deactivation_linear_threshold", text="Linear Threshold")
- sub.prop(gs, "deactivation_angular_threshold", text="Angular Threshold")
- sub = col.row()
- sub.prop(gs, "deactivation_time", text="Time")
-
- col = layout.column()
- col.prop(gs, "use_occlusion_culling", text="Occlusion Culling")
- sub = col.column()
- sub.active = gs.use_occlusion_culling
- sub.prop(gs, "occlusion_culling_resolution", text="Resolution")
-
- else:
- split = layout.split()
-
- col = split.column()
- col.label(text="Physics Steps:")
- col.prop(gs, "fps", text="FPS")
-
- col = split.column()
- col.label(text="Logic Steps:")
- col.prop(gs, "logic_step_max", text="Max")
-
-
-class SCENE_PT_game_physics_obstacles(SceneButtonsPanel, Panel):
- bl_label = "Obstacle Simulation"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
-
- layout.prop(gs, "obstacle_simulation", text="Type")
- if gs.obstacle_simulation != 'NONE':
- layout.prop(gs, "level_height")
- layout.prop(gs, "show_obstacle_simulation")
-
-
-class SCENE_PT_game_navmesh(SceneButtonsPanel, Panel):
- bl_label = "Navigation Mesh"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene and scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.game_settings.recast_data
-
- layout.operator("mesh.navmesh_make", text="Build Navigation Mesh")
-
- col = layout.column()
- col.label(text="Rasterization:")
- row = col.row()
- row.prop(rd, "cell_size")
- row.prop(rd, "cell_height")
-
- col = layout.column()
- col.label(text="Agent:")
- split = col.split()
-
- col = split.column()
- col.prop(rd, "agent_height", text="Height")
- col.prop(rd, "agent_radius", text="Radius")
-
- col = split.column()
- col.prop(rd, "slope_max")
- col.prop(rd, "climb_max")
-
- col = layout.column()
- col.label(text="Region:")
- row = col.row()
- row.prop(rd, "region_min_size")
- if rd.partitioning != 'LAYERS':
- row.prop(rd, "region_merge_size")
-
- col = layout.column()
- col.prop(rd, "partitioning")
-
- col = layout.column()
- col.label(text="Polygonization:")
- split = col.split()
-
- col = split.column()
- col.prop(rd, "edge_max_len")
- col.prop(rd, "edge_max_error")
-
- split.prop(rd, "verts_per_poly")
-
- col = layout.column()
- col.label(text="Detail Mesh:")
- row = col.row()
- row.prop(rd, "sample_dist")
- row.prop(rd, "sample_max_error")
-
-
-class SCENE_PT_game_hysteresis(SceneButtonsPanel, Panel):
- bl_label = "Level of Detail"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene and scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- gs = context.scene.game_settings
-
- row = layout.row()
- row.prop(gs, "use_scene_hysteresis", text="Hysteresis")
- row = layout.row()
- row.active = gs.use_scene_hysteresis
- row.prop(gs, "scene_hysteresis_percentage", text="")
-
-
-class WorldButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "world"
-
-
-class WORLD_PT_game_context_world(WorldButtonsPanel, Panel):
- bl_label = ""
- bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return (context.scene) and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- world = context.world
- space = context.space_data
-
- split = layout.split(percentage=0.65)
- if scene:
- split.template_ID(scene, "world", new="world.new")
- elif world:
- split.template_ID(space, "pin_id")
-
-
-class WORLD_PT_game_world(WorldButtonsPanel, Panel):
- bl_label = "World"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- world = context.world
-
- row = layout.row()
- row.column().prop(world, "horizon_color")
- row.column().prop(world, "zenith_color")
- row.column().prop(world, "ambient_color")
-
-
-class WORLD_PT_game_environment_lighting(WorldButtonsPanel, Panel):
- bl_label = "Environment Lighting"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- light = context.world.light_settings
- self.layout.prop(light, "use_environment_light", text="")
-
- def draw(self, context):
- layout = self.layout
-
- light = context.world.light_settings
-
- layout.active = light.use_environment_light
-
- split = layout.split()
- split.prop(light, "environment_energy", text="Energy")
- split.prop(light, "environment_color", text="")
-
-
-class WORLD_PT_game_mist(WorldButtonsPanel, Panel):
- bl_label = "Mist"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- world = context.world
-
- self.layout.prop(world.mist_settings, "use_mist", text="")
-
- def draw(self, context):
- layout = self.layout
-
- world = context.world
-
- layout.active = world.mist_settings.use_mist
-
- layout.prop(world.mist_settings, "falloff")
-
- row = layout.row(align=True)
- row.prop(world.mist_settings, "start")
- row.prop(world.mist_settings, "depth")
-
- layout.prop(world.mist_settings, "intensity", text="Minimum Intensity")
-
-
-class DataButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "data"
-
-
-class DATA_PT_shadow_game(DataButtonsPanel, Panel):
- bl_label = "Shadow"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- COMPAT_LIGHTS = {'SPOT', 'SUN'}
- lamp = context.lamp
- engine = context.scene.render.engine
- return (lamp and lamp.type in COMPAT_LIGHTS) and (engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- lamp = context.lamp
-
- self.layout.prop(lamp, "use_shadow", text="")
-
- def draw(self, context):
- layout = self.layout
-
- lamp = context.lamp
-
- layout.active = lamp.use_shadow
-
- split = layout.split()
-
- col = split.column()
- col.prop(lamp, "shadow_color", text="")
- if lamp.type == 'SUN':
- col.prop(lamp, "show_shadow_box")
-
- col = split.column()
- col.prop(lamp, "use_shadow_layer", text="This Layer Only")
- col.prop(lamp, "use_only_shadow")
-
- col = layout.column()
- col.label("Buffer Type:")
- col.prop(lamp, "ge_shadow_buffer_type", text="", toggle=True)
- col.label("Quality:")
- col = layout.column(align=True)
- col.prop(lamp, "shadow_buffer_size", text="Size")
- col.prop(lamp, "shadow_buffer_bias", text="Bias")
- col.prop(lamp, "shadow_buffer_bleed_bias", text="Bleed Bias")
-
- row = layout.row()
- row.label("Clipping:")
- row = layout.row(align=True)
- row.prop(lamp, "shadow_buffer_clip_start", text="Clip Start")
- row.prop(lamp, "shadow_buffer_clip_end", text="Clip End")
-
- if lamp.type == 'SUN':
- row = layout.row()
- row.prop(lamp, "shadow_frustum_size", text="Frustum Size")
-
-
-class ObjectButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "object"
-
-
-class OBJECT_MT_lod_tools(Menu):
- bl_label = "Level Of Detail Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("object.lod_by_name", text="Set By Name")
- layout.operator("object.lod_generate", text="Generate")
- layout.operator("object.lod_clear_all", text="Clear All", icon='PANEL_CLOSE')
-
-
-class OBJECT_PT_levels_of_detail(ObjectButtonsPanel, Panel):
- bl_label = "Levels of Detail"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- return context.scene.render.engine in cls.COMPAT_ENGINES
-
- def draw(self, context):
- layout = self.layout
- ob = context.object
- gs = context.scene.game_settings
-
- col = layout.column()
-
- for i, level in enumerate(ob.lod_levels):
- if i == 0:
- continue
- box = col.box()
- row = box.row()
- row.prop(level, "object", text="")
- row.operator("object.lod_remove", text="", icon='PANEL_CLOSE').index = i
-
- row = box.row()
- row.prop(level, "distance")
- row = row.row(align=True)
- row.prop(level, "use_mesh", text="")
- row.prop(level, "use_material", text="")
-
- row = box.row()
- row.active = gs.use_scene_hysteresis
- row.prop(level, "use_object_hysteresis", text="Hysteresis Override")
- row = box.row()
- row.active = gs.use_scene_hysteresis and level.use_object_hysteresis
- row.prop(level, "object_hysteresis_percentage", text="")
-
- row = col.row(align=True)
- row.operator("object.lod_add", text="Add", icon='ZOOMIN')
- row.menu("OBJECT_MT_lod_tools", text="", icon='TRIA_DOWN')
-
-
-classes = (
- PHYSICS_PT_game_physics,
- PHYSICS_PT_game_collision_bounds,
- PHYSICS_PT_game_obstacles,
- RENDER_PT_embedded,
- RENDER_PT_game_player,
- RENDER_PT_game_stereo,
- RENDER_PT_game_shading,
- RENDER_PT_game_system,
- RENDER_PT_game_display,
- SCENE_PT_game_physics,
- SCENE_PT_game_physics_obstacles,
- SCENE_PT_game_navmesh,
- SCENE_PT_game_hysteresis,
- WORLD_PT_game_context_world,
- WORLD_PT_game_world,
- WORLD_PT_game_environment_lighting,
- WORLD_PT_game_mist,
- DATA_PT_shadow_game,
- OBJECT_MT_lod_tools,
- OBJECT_PT_levels_of_detail,
-)
-
-if __name__ == "__main__": # only for live edit.
- from bpy.utils import register_class
- for cls in classes:
- register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 72d8a53dd69..a2ccfb4f1b8 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -97,6 +97,11 @@ class GreasePencilDrawingToolsPanel:
bl_category = "Grease Pencil"
bl_region_type = 'TOOLS'
+ @classmethod
+ def poll(cls, context):
+ # XXX - disabled in 2.8 branch.
+ return False
+
@staticmethod
def draw(self, context):
layout = self.layout
@@ -171,6 +176,9 @@ class GreasePencilStrokeEditPanel:
@classmethod
def poll(cls, context):
+ # XXX - disabled in 2.8 branch.
+ return False
+
if context.gpencil_data is None:
return False
@@ -259,6 +267,9 @@ class GreasePencilInterpolatePanel:
@classmethod
def poll(cls, context):
+ # XXX - disabled in 2.8 branch.
+ return False
+
if context.gpencil_data is None:
return False
elif context.space_data.type != 'VIEW_3D':
@@ -307,6 +318,11 @@ class GreasePencilBrushPanel:
bl_category = "Grease Pencil"
bl_region_type = 'TOOLS'
+ @classmethod
+ def poll(cls, context):
+ # XXX - disabled in 2.8 branch.
+ return False
+
@staticmethod
def draw(self, context):
layout = self.layout
@@ -376,6 +392,9 @@ class GreasePencilStrokeSculptPanel:
@classmethod
def poll(cls, context):
+ # XXX - disabled in 2.8 branch.
+ return False
+
if context.gpencil_data is None:
return False
@@ -436,6 +455,9 @@ class GreasePencilBrushCurvesPanel:
@classmethod
def poll(cls, context):
+ # XXX - disabled in 2.8 branch.
+ return False
+
if context.active_gpencil_brush is None:
return False
@@ -1026,6 +1048,9 @@ class GreasePencilPaletteColorPanel:
@classmethod
def poll(cls, context):
+ # XXX - disabled in 2.8 branch.
+ return False
+
if context.gpencil_data is None:
return False
@@ -1128,6 +1153,9 @@ class GreasePencilToolsPanel:
@classmethod
def poll(cls, context):
+ # XXX - disabled in 2.8 branch.
+ return False
+
return (context.gpencil_data is not None)
@staticmethod
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index 450ca80bbc2..c766c8dedbc 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -378,6 +378,12 @@ class MASK_MT_select(Menu):
def draw(self, context):
layout = self.layout
+ layout.operator("mask.select_all", text="All").action = 'SELECT'
+ layout.operator("mask.select_all", text="None").action = 'DESELECT'
+ layout.operator("mask.select_all", text="Invert").action = 'INVERT'
+
+ layout.separator()
+
layout.operator("mask.select_border")
layout.operator("mask.select_circle")
@@ -388,8 +394,6 @@ class MASK_MT_select(Menu):
layout.separator()
- layout.operator("mask.select_all").action = 'TOGGLE'
- layout.operator("mask.select_all", text="Inverse").action = 'INVERT'
layout.operator("mask.select_linked", text="Select Linked")
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 73740df37e8..3761cbba372 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -21,42 +21,7 @@ import bpy
from bpy.types import Menu, Panel, UIList
from rna_prop_ui import PropertyPanel
from bpy.app.translations import pgettext_iface as iface_
-
-
-def active_node_mat(mat):
- # TODO, 2.4x has a pipeline section, for 2.5 we need to communicate
- # which settings from node-materials are used
- if mat is not None:
- mat_node = mat.active_node_material
- if mat_node:
- return mat_node
- else:
- return mat
-
- return None
-
-
-def check_material(mat):
- if mat is not None:
- if mat.use_nodes:
- if mat.active_node_material is not None:
- return True
- return False
- return True
- return False
-
-
-def simple_material(mat):
- if (mat is not None) and (not mat.use_nodes):
- return True
- return False
-
-
-class MATERIAL_MT_sss_presets(Menu):
- bl_label = "SSS Presets"
- preset_subdir = "sss"
- preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+from bpy_extras.node_utils import find_node_input
class MATERIAL_MT_specials(Menu):
@@ -82,12 +47,6 @@ class MATERIAL_UL_matslots(UIList):
layout.prop(ma, "name", text="", emboss=False, icon_value=icon)
else:
layout.label(text="", icon_value=icon)
- if ma and not context.scene.render.use_shading_nodes:
- manode = ma.active_node_material
- if manode:
- layout.label(text=iface_("Node %s") % manode.name, translate=False, icon_value=layout.icon(manode))
- elif ma.use_nodes:
- layout.label(text="Node <none>")
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
@@ -101,20 +60,32 @@ class MaterialButtonsPanel:
@classmethod
def poll(cls, context):
- return context.material and (context.scene.render.engine in cls.COMPAT_ENGINES)
+ return context.material and (context.engine in cls.COMPAT_ENGINES)
+
+
+class MATERIAL_PT_preview(MaterialButtonsPanel, Panel):
+ bl_label = "Preview"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ self.layout.template_preview(context.material)
+
+
+class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+ _context_path = "material"
+ _property_type = bpy.types.Material
-class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
+class EEVEE_MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
bl_label = ""
+ bl_context = "material"
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- # An exception, don't call the parent poll func because
- # this manages materials for all engine types
-
- engine = context.scene.render.engine
+ engine = context.engine
return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
@@ -126,10 +97,9 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
space = context.space_data
if ob:
- is_sortable = (len(ob.material_slots) > 1)
-
- rows = 1
- if is_sortable:
+ is_sortable = len(ob.material_slots) > 1
+ rows = 2
+ if (is_sortable):
rows = 4
row = layout.row()
@@ -159,8 +129,6 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
if ob:
split.template_ID(ob, "active_material", new="material.new")
row = split.row()
- if mat:
- row.prop(mat, "use_nodes", icon='NODETREE', text="")
if slot:
row.prop(slot, "link", text="")
@@ -170,921 +138,118 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
split.template_ID(space, "pin_id")
split.separator()
- if mat:
- layout.row().prop(mat, "type", expand=True)
- if mat.use_nodes:
- row = layout.row()
- row.label(text="", icon='NODETREE')
- if mat.active_node_material:
- row.prop(mat.active_node_material, "name", text="")
- else:
- row.label(text="No material node selected")
-
-
-class MATERIAL_PT_preview(MaterialButtonsPanel, Panel):
- bl_label = "Preview"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- self.layout.template_preview(context.material)
-
-
-class MATERIAL_PT_pipeline(MaterialButtonsPanel, Panel):
- bl_label = "Render Pipeline Options"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return mat and (not simple_material(mat)) and (mat.type in {'SURFACE', 'WIRE', 'VOLUME'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self. layout
-
- mat = context.material
- mat_type = mat.type in {'SURFACE', 'WIRE'}
-
- row = layout.row()
- row.active = mat_type
- row.prop(mat, "use_transparency")
- sub = row.column()
- sub.prop(mat, "offset_z")
-
- sub.active = mat_type and mat.use_transparency and mat.transparency_method == 'Z_TRANSPARENCY'
-
- row = layout.row()
- row.active = mat.use_transparency or not mat_type
- row.prop(mat, "transparency_method", expand=True)
-
- layout.separator()
-
- split = layout.split()
- col = split.column()
-
- col.prop(mat, "use_raytrace")
- col.prop(mat, "use_full_oversampling")
- sub = col.column()
- sub.active = mat_type
- sub.prop(mat, "use_sky")
- sub.prop(mat, "invert_z")
- col.prop(mat, "pass_index")
-
- col = split.column()
- col.active = mat_type
-
- col.prop(mat, "use_cast_shadows", text="Cast")
- col.prop(mat, "use_cast_shadows_only", text="Cast Only")
- col.prop(mat, "use_cast_buffer_shadows")
- sub = col.column()
- sub.active = mat.use_cast_buffer_shadows
- sub.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
- col.prop(mat, "use_cast_approximate")
-
-
-class MATERIAL_PT_diffuse(MaterialButtonsPanel, Panel):
- bl_label = "Diffuse"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- mat = active_node_mat(context.material)
-
- split = layout.split()
-
- col = split.column()
- col.prop(mat, "diffuse_color", text="")
- sub = col.column()
- sub.active = (not mat.use_shadeless)
- sub.prop(mat, "diffuse_intensity", text="Intensity")
-
- col = split.column()
- col.active = (not mat.use_shadeless)
- col.prop(mat, "diffuse_shader", text="")
- col.prop(mat, "use_diffuse_ramp", text="Ramp")
-
- col = layout.column()
- col.active = (not mat.use_shadeless)
- if mat.diffuse_shader == 'OREN_NAYAR':
- col.prop(mat, "roughness")
- elif mat.diffuse_shader == 'MINNAERT':
- col.prop(mat, "darkness")
- elif mat.diffuse_shader == 'TOON':
- row = col.row()
- row.prop(mat, "diffuse_toon_size", text="Size")
- row.prop(mat, "diffuse_toon_smooth", text="Smooth")
- elif mat.diffuse_shader == 'FRESNEL':
- row = col.row()
- row.prop(mat, "diffuse_fresnel", text="Fresnel")
- row.prop(mat, "diffuse_fresnel_factor", text="Factor")
-
- if mat.use_diffuse_ramp:
- col = layout.column()
- col.active = (not mat.use_shadeless)
- col.separator()
- col.template_color_ramp(mat, "diffuse_ramp", expand=True)
- col.separator()
-
- row = col.row()
- row.prop(mat, "diffuse_ramp_input", text="Input")
- row.prop(mat, "diffuse_ramp_blend", text="Blend")
-
- col.prop(mat, "diffuse_ramp_factor", text="Factor")
-
-
-class MATERIAL_PT_specular(MaterialButtonsPanel, Panel):
- bl_label = "Specular"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- mat = active_node_mat(context.material)
-
- layout.active = (not mat.use_shadeless)
-
- split = layout.split()
-
- col = split.column()
- col.prop(mat, "specular_color", text="")
- col.prop(mat, "specular_intensity", text="Intensity")
-
- col = split.column()
- col.prop(mat, "specular_shader", text="")
- col.prop(mat, "use_specular_ramp", text="Ramp")
-
- col = layout.column()
- if mat.specular_shader in {'COOKTORR', 'PHONG'}:
- col.prop(mat, "specular_hardness", text="Hardness")
- elif mat.specular_shader == 'BLINN':
- row = col.row()
- row.prop(mat, "specular_hardness", text="Hardness")
- row.prop(mat, "specular_ior", text="IOR")
- elif mat.specular_shader == 'WARDISO':
- col.prop(mat, "specular_slope", text="Slope")
- elif mat.specular_shader == 'TOON':
- row = col.row()
- row.prop(mat, "specular_toon_size", text="Size")
- row.prop(mat, "specular_toon_smooth", text="Smooth")
-
- if mat.use_specular_ramp:
- layout.separator()
- layout.template_color_ramp(mat, "specular_ramp", expand=True)
- layout.separator()
-
- row = layout.row()
- row.prop(mat, "specular_ramp_input", text="Input")
- row.prop(mat, "specular_ramp_blend", text="Blend")
-
- layout.prop(mat, "specular_ramp_factor", text="Factor")
-
-
-class MATERIAL_PT_shading(MaterialButtonsPanel, Panel):
- bl_label = "Shading"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- mat = active_node_mat(context.material)
-
- if mat.type in {'SURFACE', 'WIRE'}:
- split = layout.split()
-
- col = split.column()
- sub = col.column()
- sub.active = not mat.use_shadeless
- sub.prop(mat, "emit")
- sub.prop(mat, "ambient")
- sub = col.column()
- sub.prop(mat, "translucency")
-
- col = split.column()
- col.prop(mat, "use_shadeless")
- sub = col.column()
- sub.active = not mat.use_shadeless
- sub.prop(mat, "use_tangent_shading")
- sub.prop(mat, "use_cubic")
-
-
-class MATERIAL_PT_transp(MaterialButtonsPanel, Panel):
- bl_label = "Transparency"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- mat = context.material
-
- if simple_material(mat):
- self.layout.prop(mat, "use_transparency", text="")
-
- def draw(self, context):
- layout = self.layout
-
- base_mat = context.material
- mat = active_node_mat(context.material)
- rayt = mat.raytrace_transparency
-
- if simple_material(base_mat):
- row = layout.row()
- row.active = mat.use_transparency
- row.prop(mat, "transparency_method", expand=True)
-
- split = layout.split()
- split.active = base_mat.use_transparency
-
- col = split.column()
- col.prop(mat, "alpha")
- row = col.row()
- row.active = (base_mat.transparency_method != 'MASK') and (not mat.use_shadeless)
- row.prop(mat, "specular_alpha", text="Specular")
-
- col = split.column()
- col.active = (not mat.use_shadeless)
- col.prop(rayt, "fresnel")
- sub = col.column()
- sub.active = (rayt.fresnel > 0.0)
- sub.prop(rayt, "fresnel_factor", text="Blend")
-
- if base_mat.transparency_method == 'RAYTRACE':
- layout.separator()
- split = layout.split()
- split.active = base_mat.use_transparency
-
- col = split.column()
- col.prop(rayt, "ior")
- col.prop(rayt, "filter")
- col.prop(rayt, "falloff")
- col.prop(rayt, "depth_max")
- col.prop(rayt, "depth")
-
- col = split.column()
- col.label(text="Gloss:")
- col.prop(rayt, "gloss_factor", text="Amount")
- sub = col.column()
- sub.active = rayt.gloss_factor < 1.0
- sub.prop(rayt, "gloss_threshold", text="Threshold")
- sub.prop(rayt, "gloss_samples", text="Samples")
-
-
-class MATERIAL_PT_mirror(MaterialButtonsPanel, Panel):
- bl_label = "Mirror"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- raym = active_node_mat(context.material).raytrace_mirror
-
- self.layout.prop(raym, "use", text="")
-
- def draw(self, context):
- layout = self.layout
-
- mat = active_node_mat(context.material)
- raym = mat.raytrace_mirror
-
- layout.active = raym.use
-
- split = layout.split()
-
- col = split.column()
- col.prop(raym, "reflect_factor")
- col.prop(mat, "mirror_color", text="")
-
- col = split.column()
- col.prop(raym, "fresnel")
- sub = col.column()
- sub.active = (raym.fresnel > 0.0)
- sub.prop(raym, "fresnel_factor", text="Blend")
-
- split = layout.split()
-
- col = split.column()
- col.separator()
- col.prop(raym, "depth")
- col.prop(raym, "distance", text="Max Dist")
- col.separator()
- sub = col.split(percentage=0.4)
- sub.active = (raym.distance > 0.0)
- sub.label(text="Fade To:")
- sub.prop(raym, "fade_to", text="")
-
- col = split.column()
- col.label(text="Gloss:")
- col.prop(raym, "gloss_factor", text="Amount")
- sub = col.column()
- sub.active = (raym.gloss_factor < 1.0)
- sub.prop(raym, "gloss_threshold", text="Threshold")
- sub.prop(raym, "gloss_samples", text="Samples")
- sub.prop(raym, "gloss_anisotropic", text="Anisotropic")
-
-
-class MATERIAL_PT_sss(MaterialButtonsPanel, Panel):
- bl_label = "Subsurface Scattering"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- mat = active_node_mat(context.material)
- sss = mat.subsurface_scattering
-
- self.layout.active = (not mat.use_shadeless)
- self.layout.prop(sss, "use", text="")
-
- def draw(self, context):
- layout = self.layout
-
- mat = active_node_mat(context.material)
- sss = mat.subsurface_scattering
-
- layout.active = (sss.use) and (not mat.use_shadeless)
-
- row = layout.row().split()
- sub = row.row(align=True).split(align=True, percentage=0.75)
- sub.menu("MATERIAL_MT_sss_presets", text=bpy.types.MATERIAL_MT_sss_presets.bl_label)
- sub.operator("material.sss_preset_add", text="", icon='ZOOMIN')
- sub.operator("material.sss_preset_add", text="", icon='ZOOMOUT').remove_active = True
-
- split = layout.split()
-
- col = split.column()
- col.prop(sss, "ior")
- col.prop(sss, "scale")
- col.prop(sss, "color", text="")
- col.prop(sss, "radius", text="RGB Radius", expand=True)
-
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Blend:")
- sub.prop(sss, "color_factor", text="Color")
- sub.prop(sss, "texture_factor", text="Texture")
- sub.label(text="Scattering Weight:")
- sub.prop(sss, "front")
- sub.prop(sss, "back")
- col.separator()
- col.prop(sss, "error_threshold", text="Error")
-
-class MATERIAL_PT_halo(MaterialButtonsPanel, Panel):
- bl_label = "Halo"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return mat and (mat.type == 'HALO') and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- mat = context.material # don't use node material
- halo = mat.halo
-
- def number_but(layout, toggle, number, name, color):
- row = layout.row(align=True)
- row.prop(halo, toggle, text="")
- sub = row.column(align=True)
- sub.active = getattr(halo, toggle)
- sub.prop(halo, number, text=name, translate=False)
- if not color == "":
- sub.prop(mat, color, text="")
-
- split = layout.split()
-
- col = split.column()
- col.prop(mat, "alpha")
- col.prop(mat, "diffuse_color", text="")
- col.prop(halo, "seed")
-
- col = split.column()
- col.prop(halo, "size")
- col.prop(halo, "hardness")
- col.prop(halo, "add")
-
- layout.label(text="Options:")
-
- split = layout.split()
- col = split.column()
- col.prop(halo, "use_texture")
- col.prop(halo, "use_vertex_normal")
- col.prop(halo, "use_extreme_alpha")
- col.prop(halo, "use_shaded")
- col.prop(halo, "use_soft")
-
- col = split.column()
- number_but(col, "use_ring", "ring_count", iface_("Rings"), "mirror_color")
- number_but(col, "use_lines", "line_count", iface_("Lines"), "specular_color")
- number_but(col, "use_star", "star_tip_count", iface_("Star Tips"), "")
-
-
-class MATERIAL_PT_flare(MaterialButtonsPanel, Panel):
- bl_label = "Flare"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return mat and (mat.type == 'HALO') and (engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- halo = context.material.halo
-
- self.layout.prop(halo, "use_flare_mode", text="")
-
- def draw(self, context):
- layout = self.layout
-
- mat = context.material # don't use node material
- halo = mat.halo
-
- layout.active = halo.use_flare_mode
-
- split = layout.split()
-
- col = split.column()
- col.prop(halo, "flare_size", text="Size")
- col.prop(halo, "flare_boost", text="Boost")
- col.prop(halo, "flare_seed", text="Seed")
-
- col = split.column()
- col.prop(halo, "flare_subflare_count", text="Subflares")
- col.prop(halo, "flare_subflare_size", text="Subsize")
-
-
-class MATERIAL_PT_game_settings(MaterialButtonsPanel, Panel):
- bl_label = "Game Settings"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- return context.material and (context.scene.render.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- game = context.material.game_settings # don't use node material
-
- row = layout.row()
- row.prop(game, "use_backface_culling")
- row.prop(game, "invisible")
- row.prop(game, "text")
-
- row = layout.row()
- row.label(text="Alpha Blend:")
- row.label(text="Face Orientation:")
- row = layout.row()
- row.prop(game, "alpha_blend", text="")
- row.prop(game, "face_orientation", text="")
+def panel_node_draw(layout, ntree, output_type):
+ node = ntree.get_output_node('EEVEE')
+ if node:
+ input = find_node_input(node, 'Surface')
+ if input:
+ layout.template_node_view(ntree, node, input)
+ else:
+ layout.label(text="Incompatible output node")
+ else:
+ layout.label(text="No output node")
-class MATERIAL_PT_physics(MaterialButtonsPanel, Panel):
- bl_label = "Physics"
- COMPAT_ENGINES = {'BLENDER_GAME'}
- def draw_header(self, context):
- game = context.material.game_settings
- self.layout.prop(game, "physics", text="")
+class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel):
+ bl_label = "Surface"
+ bl_context = "material"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- return context.material and (context.scene.render.engine in cls.COMPAT_ENGINES)
+ engine = context.engine
+ return context.material and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- layout.active = context.material.game_settings.physics
-
- phys = context.material.physics # don't use node material
-
- split = layout.split()
- row = split.row()
- row.prop(phys, "friction")
- row.prop(phys, "elasticity", slider=True)
- row = layout.row()
- row.label(text="Force Field:")
-
- row = layout.row()
- row.prop(phys, "fh_force")
- row.prop(phys, "fh_damping", slider=True)
-
- row = layout.row()
- row.prop(phys, "fh_distance")
- row.prop(phys, "use_fh_normal")
-
-
-class MATERIAL_PT_strand(MaterialButtonsPanel, Panel):
- bl_label = "Strand"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
mat = context.material
- engine = context.scene.render.engine
- return mat and (mat.type in {'SURFACE', 'WIRE', 'HALO'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- mat = context.material # don't use node material
- tan = mat.strand
- split = layout.split()
-
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Size:")
- sub.prop(tan, "root_size", text="Root")
- sub.prop(tan, "tip_size", text="Tip")
- sub.prop(tan, "size_min", text="Minimum")
- sub.prop(tan, "use_blender_units")
- sub = col.column()
- sub.active = (not mat.use_shadeless)
- sub.prop(tan, "use_tangent_shading")
- col.prop(tan, "shape")
+ layout.prop(mat, "use_nodes", icon='NODETREE')
+ layout.separator()
- col = split.column()
- col.label(text="Shading:")
- col.prop(tan, "width_fade")
- ob = context.object
- if ob and ob.type == 'MESH':
- col.prop_search(tan, "uv_layer", ob.data, "uv_textures", text="")
+ if mat.use_nodes:
+ panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL')
else:
- col.prop(tan, "uv_layer", text="")
- col.separator()
- sub = col.column()
- sub.active = (not mat.use_shadeless)
- sub.label("Surface diffuse:")
- sub = col.column()
- sub.prop(tan, "blend_distance", text="Distance")
+ layout.use_property_split = True
+ layout.prop(mat, "diffuse_color", text="Base Color")
+ layout.prop(mat, "metallic")
+ layout.prop(mat, "specular_intensity", text="Specular")
+ layout.prop(mat, "roughness")
-class MATERIAL_PT_options(MaterialButtonsPanel, Panel):
+class EEVEE_MATERIAL_PT_options(MaterialButtonsPanel, Panel):
bl_label = "Options"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ bl_context = "material"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
+ engine = context.engine
+ return context.material and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
- base_mat = context.material
- mat = active_node_mat(base_mat)
-
- split = layout.split()
-
- col = split.column()
- if simple_material(base_mat):
- col.prop(mat, "use_raytrace")
- col.prop(mat, "use_full_oversampling")
- col.prop(mat, "use_sky")
- col.prop(mat, "use_mist")
- if simple_material(base_mat):
- col.prop(mat, "invert_z")
- sub = col.row()
- sub.prop(mat, "offset_z")
- sub.active = mat.use_transparency and mat.transparency_method == 'Z_TRANSPARENCY'
- sub = col.column(align=True)
- sub.label(text="Light Group:")
- sub.prop(mat, "light_group", text="")
- row = sub.row(align=True)
- row.active = bool(mat.light_group)
- row.prop(mat, "use_light_group_exclusive", text="Exclusive")
- row.prop(mat, "use_light_group_local", text="Local")
-
- col = split.column()
- col.prop(mat, "use_face_texture")
- sub = col.column()
- sub.active = mat.use_face_texture
- sub.prop(mat, "use_face_texture_alpha")
- col.separator()
- col.prop(mat, "use_vertex_color_paint")
- col.prop(mat, "use_vertex_color_light")
- col.prop(mat, "use_object_color")
- col.prop(mat, "use_uv_project")
- if simple_material(base_mat):
- col.prop(mat, "pass_index")
-
-
-class MATERIAL_PT_shadow(MaterialButtonsPanel, Panel):
- bl_label = "Shadow"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- base_mat = context.material
- mat = active_node_mat(base_mat)
-
- split = layout.split()
-
- col = split.column()
- col.prop(mat, "use_shadows", text="Receive")
- col.prop(mat, "use_transparent_shadows", text="Receive Transparent")
- col.prop(mat, "use_only_shadow", text="Shadows Only")
- sub = col.column()
- sub.active = mat.use_only_shadow
- sub.prop(mat, "shadow_only_type", text="")
- if not simple_material(base_mat):
- col = split.column()
+ layout.prop(mat, "blend_method")
- col.prop(mat, "use_ray_shadow_bias", text="Auto Ray Bias")
- sub = col.column()
- sub.active = (not mat.use_ray_shadow_bias)
- sub.prop(mat, "shadow_ray_bias", text="Ray Bias")
+ if mat.blend_method != 'OPAQUE':
+ layout.prop(mat, "transparent_shadow_method")
- if simple_material(base_mat):
- col = split.column()
-
- col.prop(mat, "use_cast_shadows", text="Cast")
- col.prop(mat, "use_cast_shadows_only", text="Cast Only")
- col.prop(mat, "use_cast_buffer_shadows")
- sub = col.column()
- sub.active = mat.use_cast_buffer_shadows
- if simple_material(base_mat):
- sub.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
- sub.prop(mat, "shadow_buffer_bias", text="Buffer Bias")
- if simple_material(base_mat):
- col.prop(mat, "use_cast_approximate")
-
-
-class MATERIAL_PT_transp_game(MaterialButtonsPanel, Panel):
- bl_label = "Transparency"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- mat = context.material
-
- if simple_material(mat):
- self.layout.prop(mat, "use_transparency", text="")
-
- def draw(self, context):
- layout = self.layout
- base_mat = context.material
- mat = active_node_mat(base_mat)
-
- layout.active = mat.use_transparency
-
- if simple_material(base_mat):
row = layout.row()
- row.prop(mat, "transparency_method", expand=True)
-
- layout.prop(mat, "alpha")
- layout.prop(mat, "specular_alpha", text="Specular")
-
-
-class VolumeButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "material"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return mat and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
+ row.active = ((mat.blend_method == 'CLIP') or (mat.transparent_shadow_method == 'CLIP'))
+ row.prop(mat, "alpha_threshold")
+ if mat.blend_method not in {'OPAQUE', 'CLIP', 'HASHED'}:
+ layout.prop(mat, "show_transparent_backside")
-class MATERIAL_PT_volume_density(VolumeButtonsPanel, Panel):
- bl_label = "Density"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- vol = context.material.volume # don't use node material
+ layout.prop(mat, "use_screen_refraction")
+ layout.prop(mat, "refraction_depth")
+ layout.prop(mat, "use_screen_subsurface")
row = layout.row()
- row.prop(vol, "density")
- row.prop(vol, "density_scale")
+ row.active = mat.use_screen_subsurface
+ row.prop(mat, "use_sss_translucency")
-class MATERIAL_PT_volume_shading(VolumeButtonsPanel, Panel):
- bl_label = "Shading"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- vol = context.material.volume # don't use node material
-
- split = layout.split()
-
- col = split.column()
- col.prop(vol, "scattering")
- col.prop(vol, "asymmetry")
- col.prop(vol, "transmission_color")
-
- col = split.column()
- sub = col.column(align=True)
- sub.prop(vol, "emission")
- sub.prop(vol, "emission_color", text="")
- sub = col.column(align=True)
- sub.prop(vol, "reflection")
- sub.prop(vol, "reflection_color", text="")
-
-
-class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, Panel):
- bl_label = "Lighting"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- vol = context.material.volume # don't use node material
-
- split = layout.split()
-
- col = split.column()
- col.prop(vol, "light_method", text="")
-
- col = split.column()
-
- if vol.light_method == 'SHADED':
- col.prop(vol, "use_external_shadows")
- col.prop(vol, "use_light_cache")
- sub = col.column()
- sub.active = vol.use_light_cache
- sub.prop(vol, "cache_resolution")
- elif vol.light_method in {'MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'}:
- sub = col.column()
- sub.enabled = True
- sub.active = False
- sub.label("Light Cache Enabled")
- col.prop(vol, "cache_resolution")
-
- sub = col.column(align=True)
- sub.prop(vol, "ms_diffusion")
- sub.prop(vol, "ms_spread")
- sub.prop(vol, "ms_intensity")
-
-
-class MATERIAL_PT_volume_transp(VolumeButtonsPanel, Panel):
- bl_label = "Transparency"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+class MATERIAL_PT_viewport(MaterialButtonsPanel, Panel):
+ bl_label = "Viewport Display"
+ bl_context = "material"
+ bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- mat = context.material
- engine = context.scene.render.engine
- return mat and simple_material(mat) and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
+ return context.material
def draw(self, context):
- layout = self.layout
-
- mat = context.material # don't use node material
-
- layout.row().prop(mat, "transparency_method", expand=True)
-
-
-class MATERIAL_PT_volume_integration(VolumeButtonsPanel, Panel):
- bl_label = "Integration"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- vol = context.material.volume # don't use node material
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Step Calculation:")
- col.prop(vol, "step_method", text="")
- col = col.column(align=True)
- col.prop(vol, "step_size")
-
- col = split.column()
- col.label()
- col.prop(vol, "depth_threshold")
-
-
-class MATERIAL_PT_volume_options(VolumeButtonsPanel, Panel):
- bl_label = "Options"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
mat = context.material
- engine = context.scene.render.engine
- return check_material(mat) and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
- def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
- mat = active_node_mat(context.material)
-
- split = layout.split()
-
- col = split.column()
- if simple_material(context.material):
- col.prop(mat, "use_raytrace")
- col.prop(mat, "use_full_oversampling")
- col.prop(mat, "use_mist")
-
- col = split.column()
- col.label(text="Light Group:")
- col.prop(mat, "light_group", text="")
- row = col.row()
- row.active = bool(mat.light_group)
- row.prop(mat, "use_light_group_exclusive", text="Exclusive")
-
-
-class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- _context_path = "material"
- _property_type = bpy.types.Material
+ col = layout.column()
+ col.prop(mat, "diffuse_color")
+ col.prop(mat, "specular_color")
+ col.prop(mat, "roughness")
classes = (
- MATERIAL_MT_sss_presets,
MATERIAL_MT_specials,
MATERIAL_UL_matslots,
- MATERIAL_PT_context_material,
MATERIAL_PT_preview,
- MATERIAL_PT_pipeline,
- MATERIAL_PT_diffuse,
- MATERIAL_PT_specular,
- MATERIAL_PT_shading,
- MATERIAL_PT_transp,
- MATERIAL_PT_mirror,
- MATERIAL_PT_sss,
- MATERIAL_PT_halo,
- MATERIAL_PT_flare,
- MATERIAL_PT_game_settings,
- MATERIAL_PT_physics,
- MATERIAL_PT_strand,
- MATERIAL_PT_options,
- MATERIAL_PT_shadow,
- MATERIAL_PT_transp_game,
- MATERIAL_PT_volume_density,
- MATERIAL_PT_volume_shading,
- MATERIAL_PT_volume_lighting,
- MATERIAL_PT_volume_transp,
- MATERIAL_PT_volume_integration,
- MATERIAL_PT_volume_options,
MATERIAL_PT_custom_props,
+ EEVEE_MATERIAL_PT_context_material,
+ EEVEE_MATERIAL_PT_surface,
+ EEVEE_MATERIAL_PT_options,
+ MATERIAL_PT_viewport,
)
+
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 50cef9124ab..63b708ae059 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -40,7 +40,7 @@ class OBJECT_PT_context_object(ObjectButtonsPanel, Panel):
layout.template_ID(space, "pin_id")
else:
row = layout.row()
- row.template_ID(context.scene.objects, "active", filter='AVAILABLE')
+ row.template_ID(context.view_layer.objects, "active", filter='AVAILABLE')
class OBJECT_PT_transform(ObjectButtonsPanel, Panel):
@@ -48,150 +48,140 @@ class OBJECT_PT_transform(ObjectButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
ob = context.object
- row = layout.row()
+ col = flow.column()
+ row = col.row(align=True)
+ row.prop(ob, "location")
+ row.use_property_decorate = False
+ row.prop(ob, "lock_location", text="", emboss=False)
- row.column().prop(ob, "location")
if ob.rotation_mode == 'QUATERNION':
- row.column().prop(ob, "rotation_quaternion", text="Rotation")
+ col = flow.column()
+ row = col.row(align=True)
+ row.prop(ob, "rotation_quaternion", text="Rotation")
+ sub = row.column(align=True)
+ sub.use_property_decorate = False
+ sub.prop(ob, "lock_rotation_w", text="", emboss=False)
+ sub.prop(ob, "lock_rotation", text="", emboss=False)
elif ob.rotation_mode == 'AXIS_ANGLE':
# row.column().label(text="Rotation")
#row.column().prop(pchan, "rotation_angle", text="Angle")
#row.column().prop(pchan, "rotation_axis", text="Axis")
- row.column().prop(ob, "rotation_axis_angle", text="Rotation")
+ col = flow.column()
+ row = col.row(align=True)
+ row.prop(ob, "rotation_axis_angle", text="Rotation")
+
+ sub = row.column(align=True)
+ sub.use_property_decorate = False
+ sub.prop(ob, "lock_rotation_w", text="", emboss=False)
+ sub.prop(ob, "lock_rotation", text="", emboss=False)
else:
- row.column().prop(ob, "rotation_euler", text="Rotation")
+ col = flow.column()
+ row = col.row(align=True)
+ row.prop(ob, "rotation_euler", text="Rotation")
+ row.use_property_decorate = False
+ row.prop(ob, "lock_rotation", text="", emboss=False)
+
+ col = flow.column()
+ row = col.row(align=True)
+ row.prop(ob, "scale")
+ row.use_property_decorate = False
+ row.prop(ob, "lock_scale", text="", emboss=False)
- row.column().prop(ob, "scale")
-
- layout.prop(ob, "rotation_mode")
+ row = layout.row(align=True)
+ row.prop(ob, "rotation_mode")
+ row.label(text="", icon='BLANK1')
class OBJECT_PT_delta_transform(ObjectButtonsPanel, Panel):
bl_label = "Delta Transform"
+ bl_parent_id = "OBJECT_PT_transform"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=True, align=False)
ob = context.object
- row = layout.row()
+ col = flow.column()
+ col.prop(ob, "delta_location")
- row.column().prop(ob, "delta_location")
+ col = flow.column()
if ob.rotation_mode == 'QUATERNION':
- row.column().prop(ob, "delta_rotation_quaternion", text="Rotation")
+ col.prop(ob, "delta_rotation_quaternion", text="Rotation")
elif ob.rotation_mode == 'AXIS_ANGLE':
# row.column().label(text="Rotation")
#row.column().prop(pchan, "delta_rotation_angle", text="Angle")
#row.column().prop(pchan, "delta_rotation_axis", text="Axis")
#row.column().prop(ob, "delta_rotation_axis_angle", text="Rotation")
- row.column().label(text="Not for Axis-Angle")
+ col.label(text="Not for Axis-Angle")
else:
- row.column().prop(ob, "delta_rotation_euler", text="Delta Rotation")
-
- row.column().prop(ob, "delta_scale")
-
-
-class OBJECT_PT_transform_locks(ObjectButtonsPanel, Panel):
- bl_label = "Transform Locks"
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
+ col.prop(ob, "delta_rotation_euler", text="Delta Rotation")
- split = layout.split(percentage=0.1)
-
- col = split.column(align=True)
- col.label(text="")
- col.label(text="X:")
- col.label(text="Y:")
- col.label(text="Z:")
-
- split.column().prop(ob, "lock_location", text="Location")
- split.column().prop(ob, "lock_rotation", text="Rotation")
- split.column().prop(ob, "lock_scale", text="Scale")
-
- if ob.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}:
- row = layout.row()
- row.prop(ob, "lock_rotations_4d", text="Lock Rotation")
-
- sub = row.row()
- sub.active = ob.lock_rotations_4d
- sub.prop(ob, "lock_rotation_w", text="W")
+ col = flow.column()
+ col.prop(ob, "delta_scale")
class OBJECT_PT_relations(ObjectButtonsPanel, Panel):
bl_label = "Relations"
+ bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
ob = context.object
- split = layout.split()
-
- col = split.column()
- col.prop(ob, "layers")
- col.separator()
- col.prop(ob, "pass_index")
-
- col = split.column()
- col.label(text="Parent:")
- col.prop(ob, "parent", text="")
-
- sub = col.column()
- sub.prop(ob, "parent_type", text="")
+ col = flow.column()
+ col.prop(ob, "parent")
+ sub = col.row(align=True)
+ sub.prop(ob, "parent_type")
parent = ob.parent
if parent and ob.parent_type == 'BONE' and parent.type == 'ARMATURE':
- sub.prop_search(ob, "parent_bone", parent.data, "bones", text="")
+ sub.prop_search(ob, "parent_bone", parent.data, "bones")
sub.active = (parent is not None)
+ col = flow.column()
+ col.active = (ob.parent is not None)
+ col.prop(ob, "use_slow_parent")
+ sub = col.row(align=True)
+ sub.active = (ob.use_slow_parent)
+ sub.prop(ob, "slow_parent_offset", text="Offset")
-class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
- bl_label = "Relations Extras"
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
-
- split = layout.split()
+ col = flow.column()
+ col.separator()
- if context.scene.render.engine != 'BLENDER_GAME':
- col = split.column()
- col.label(text="Tracking Axes:")
- col.prop(ob, "track_axis", text="Axis")
- col.prop(ob, "up_axis", text="Up Axis")
+ col.prop(ob, "track_axis", text="Tracking Axis")
+ col.prop(ob, "up_axis", text="Up Axis")
- col = split.column()
- col.prop(ob, "use_slow_parent")
- row = col.row()
- row.active = ((ob.parent is not None) and (ob.use_slow_parent))
- row.prop(ob, "slow_parent_offset", text="Offset")
+ col = flow.column()
+ col.separator()
- layout.prop(ob, "use_extra_recalc_object")
- layout.prop(ob, "use_extra_recalc_data")
+ col.prop(ob, "pass_index")
-class GROUP_MT_specials(Menu):
- bl_label = "Group Specials"
+class COLLECTION_MT_specials(Menu):
+ bl_label = "Collection Specials"
def draw(self, context):
layout = self.layout
- layout.operator("object.group_unlink", icon='X')
- layout.operator("object.grouped_select")
+ layout.operator("object.collection_unlink", icon='X')
+ layout.operator("object.collection_objects_select")
layout.operator("object.dupli_offset_from_cursor")
-class OBJECT_PT_groups(ObjectButtonsPanel, Panel):
- bl_label = "Groups"
+class OBJECT_PT_collections(ObjectButtonsPanel, Panel):
+ bl_label = "Collections"
+ bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
@@ -199,42 +189,40 @@ class OBJECT_PT_groups(ObjectButtonsPanel, Panel):
obj = context.object
row = layout.row(align=True)
- if bpy.data.groups:
- row.operator("object.group_link", text="Add to Group")
+ if bpy.data.collections:
+ row.operator("object.collection_link", text="Add to Collection")
else:
- row.operator("object.group_add", text="Add to Group")
- row.operator("object.group_add", text="", icon='ZOOMIN')
+ row.operator("object.collection_add", text="Add to Collection")
+ row.operator("object.collection_add", text="", icon='ZOOMIN')
obj_name = obj.name
- for group in bpy.data.groups:
+ for collection in bpy.data.collections:
# XXX this is slow and stupid!, we need 2 checks, one thats fast
# and another that we can be sure its not a name collision
# from linked library data
- group_objects = group.objects
- if obj_name in group.objects and obj in group_objects[:]:
+ collection_objects = collection.objects
+ if obj_name in collection.objects and obj in collection_objects[:]:
col = layout.column(align=True)
- col.context_pointer_set("group", group)
+ col.context_pointer_set("collection", collection)
row = col.box().row()
- row.prop(group, "name", text="")
- row.operator("object.group_remove", text="", icon='X', emboss=False)
- row.menu("GROUP_MT_specials", icon='DOWNARROW_HLT', text="")
+ row.prop(collection, "name", text="")
+ row.operator("object.collection_remove", text="", icon='X', emboss=False)
+ row.menu("COLLECTION_MT_specials", icon='DOWNARROW_HLT', text="")
- split = col.box().split()
-
- col = split.column()
- col.prop(group, "layers", text="Dupli Visibility")
-
- col = split.column()
- col.prop(group, "dupli_offset", text="")
+ row = col.box().row()
+ row.prop(collection, "dupli_offset", text="")
class OBJECT_PT_display(ObjectButtonsPanel, Panel):
- bl_label = "Display"
+ bl_label = "Viewport Display"
+ bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
obj = context.object
obj_type = obj.type
@@ -243,84 +231,93 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
is_empty_image = (obj_type == 'EMPTY' and obj.empty_draw_type == 'IMAGE')
is_dupli = (obj.dupli_type != 'NONE')
- split = layout.split()
-
- col = split.column()
+ col = flow.column(align=True)
col.prop(obj, "show_name", text="Name")
col.prop(obj, "show_axis", text="Axis")
+
# Makes no sense for cameras, armatures, etc.!
# but these settings do apply to dupli instances
+ col = flow.column(align=True)
if is_geometry or is_dupli:
- col.prop(obj, "show_wire", text="Wire")
+ col.prop(obj, "show_wire", text="Wireframe")
if obj_type == 'MESH' or is_dupli:
col.prop(obj, "show_all_edges")
- col = split.column()
- row = col.row()
- row.prop(obj, "show_bounds", text="Bounds")
- sub = row.row()
+ col = flow.column()
+ col.prop(obj, "show_bounds", text="Bounds")
+ sub = col.column()
sub.active = obj.show_bounds
- sub.prop(obj, "draw_bounds_type", text="")
+ sub.prop(obj, "draw_bounds_type")
+ col = flow.column()
if is_geometry:
col.prop(obj, "show_texture_space", text="Texture Space")
- col.prop(obj, "show_x_ray", text="X-Ray")
- if obj_type == 'MESH' or is_empty_image:
- col.prop(obj, "show_transparent", text="Transparency")
+ col.prop(obj.display, "show_shadows", text="Shadow")
- split = layout.split()
+ col.prop(obj, "show_x_ray", text="X-Ray")
+ # if obj_type == 'MESH' or is_empty_image:
+ # col.prop(obj, "show_transparent", text="Transparency")
- col = split.column()
+ col = flow.column()
if is_wire:
# wire objects only use the max. draw type for duplis
col.active = is_dupli
- col.label(text="Maximum Dupli Draw Type:")
- else:
- col.label(text="Maximum Draw Type:")
- col.prop(obj, "draw_type", text="")
+ col.prop(
+ obj, "draw_type",
+ text="Maximum Draw Type" if is_wire else "Maximum Draw Type",
+ )
- col = split.column()
if is_geometry or is_empty_image:
# Only useful with object having faces/materials...
- col.label(text="Object Color:")
- col.prop(obj, "color", text="")
+ col.prop(obj, "color")
class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
bl_label = "Duplication"
+ bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
ob = context.object
- layout.row().prop(ob, "dupli_type", expand=True)
+ row = layout.row()
+ row.prop(ob, "dupli_type", expand=True)
+
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
if ob.dupli_type == 'FRAMES':
- split = layout.split()
- col = split.column(align=True)
+ col = flow.column(align=True)
col.prop(ob, "dupli_frames_start", text="Start")
col.prop(ob, "dupli_frames_end", text="End")
- col = split.column(align=True)
+ col = flow.column(align=True)
col.prop(ob, "dupli_frames_on", text="On")
col.prop(ob, "dupli_frames_off", text="Off")
- layout.prop(ob, "use_dupli_frames_speed", text="Speed")
+ col = flow.column(align=True)
+ col.prop(ob, "use_dupli_frames_speed", text="Speed")
elif ob.dupli_type == 'VERTS':
layout.prop(ob, "use_dupli_vertices_rotation", text="Rotation")
elif ob.dupli_type == 'FACES':
- row = layout.row()
- row.prop(ob, "use_dupli_faces_scale", text="Scale")
- sub = row.row()
+ col = flow.column()
+ col.prop(ob, "use_dupli_faces_scale", text="Scale")
+ sub = col.column()
sub.active = ob.use_dupli_faces_scale
sub.prop(ob, "dupli_faces_scale", text="Inherit Scale")
- elif ob.dupli_type == 'GROUP':
- layout.prop(ob, "dupli_group", text="Group")
+ elif ob.dupli_type == 'COLLECTION':
+ col = flow.column()
+ col.prop(ob, "dupli_group", text="Collection")
+
+ if ob.dupli_type != 'NONE' or len(ob.particle_systems):
+ col = flow.column(align=True)
+ col.prop(ob, "show_duplicator_for_viewport")
+ col.prop(ob, "show_duplicator_for_render")
from .properties_animviz import (
@@ -362,7 +359,7 @@ class OBJECT_PT_onion_skinning(OnionSkinButtonsPanel): # , Panel): # inherit fr
class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "object"
_property_type = bpy.types.Object
@@ -371,13 +368,11 @@ classes = (
OBJECT_PT_context_object,
OBJECT_PT_transform,
OBJECT_PT_delta_transform,
- OBJECT_PT_transform_locks,
OBJECT_PT_relations,
- OBJECT_PT_relations_extras,
- GROUP_MT_specials,
- OBJECT_PT_groups,
- OBJECT_PT_display,
+ COLLECTION_MT_specials,
+ OBJECT_PT_collections,
OBJECT_PT_duplication,
+ OBJECT_PT_display,
OBJECT_PT_motion_paths,
OBJECT_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index b4049bf7b68..f1e5102f061 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -96,8 +96,8 @@ class VIEW3D_MT_tools_projectpaint_clone(Menu):
def draw(self, context):
layout = self.layout
- for i, tex in enumerate(context.active_object.data.uv_textures):
- props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
+ for i, uv_layer in enumerate(context.active_object.data.uv_layers):
+ props = layout.operator("wm.context_set_int", text=uv_layer.name, translate=False)
props.data_path = "active_object.data.uv_texture_clone_index"
props.value = i
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 14ca6f700f4..05538e71faf 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -21,6 +21,7 @@ import bpy
from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
from bpy.app.translations import pgettext_iface as iface_
+from bl_operators.presets import PresetMenu
from .properties_physics_common import (
point_cache_ui,
@@ -42,7 +43,7 @@ def particle_panel_enabled(context, psys):
def particle_panel_poll(cls, context):
psys = context.particle_system
- engine = context.scene.render.engine
+ engine = context.engine
settings = 0
if psys:
@@ -66,7 +67,7 @@ def particle_get_settings(context):
class PARTICLE_MT_specials(Menu):
bl_label = "Particle Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -82,12 +83,12 @@ class PARTICLE_MT_specials(Menu):
layout.operator("particle.duplicate_particle_system")
-class PARTICLE_MT_hair_dynamics_presets(Menu):
+class PARTICLE_PT_hair_dynamics_presets(PresetMenu):
bl_label = "Hair Dynamics Presets"
preset_subdir = "hair_dynamics"
preset_operator = "script.execute_preset"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- draw = Menu.draw_preset
+ preset_add_operator = "particle.hair_dynamics_preset_add"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
class ParticleButtonsPanel:
@@ -131,20 +132,16 @@ class PARTICLE_UL_particle_systems(bpy.types.UIList):
class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- engine = context.scene.render.engine
+ engine = context.engine
return (context.particle_system or context.object or context.space_data.pin_id) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- if context.scene.render.engine == 'BLENDER_GAME':
- layout.label("Not available in the Game Engine")
- return
-
ob = context.object
psys = context.particle_system
part = 0
@@ -153,7 +150,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
row = layout.row()
row.template_list("PARTICLE_UL_particle_systems", "particle_systems", ob, "particle_systems",
- ob.particle_systems, "active_index", rows=1)
+ ob.particle_systems, "active_index", rows=2)
col = row.column(align=True)
col.operator("object.particle_system_add", icon='ZOOMIN', text="")
@@ -238,7 +235,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
bl_label = "Emission"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -259,67 +256,81 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
psys = context.particle_system
part = particle_get_settings(context)
+ layout.use_property_split = True
+
layout.enabled = particle_panel_enabled(context, psys) and (psys is None or not psys.has_multiple_caches)
- row = layout.row()
- row.active = part.emit_from == 'VERT' or part.distribution != 'GRID'
- row.prop(part, "count")
+ col = layout.column()
+ col.active = part.emit_from == 'VERT' or part.distribution != 'GRID'
+ col.prop(part, "count")
if part.type == 'HAIR':
- row.prop(part, "hair_length")
+ col.prop(part, "hair_length")
if not part.use_advanced_hair:
row = layout.row()
- row.prop(part, "use_modifier_stack")
+ col.prop(part, "use_modifier_stack")
return
if part.type != 'HAIR':
- split = layout.split()
- col = split.column(align=True)
- col.prop(part, "frame_start")
- col.prop(part, "frame_end")
+ col = layout.column()
+
+ sub = col.column(align=True)
+ sub.prop(part, "frame_start", text="Frame Start")
+ sub.prop(part, "frame_end", text="End")
- col = split.column(align=True)
col.prop(part, "lifetime")
- col.prop(part, "lifetime_random", slider=True)
+ col.prop(part, "lifetime_random", slider=True, text="Lifetime Randomness")
- layout.label(text="Emit From:")
- layout.row().prop(part, "emit_from", expand=True)
- row = layout.row()
+class PARTICLE_PT_emission_source(ParticleButtonsPanel, Panel):
+ bl_label = "Source"
+ bl_parent_id = "PARTICLE_PT_emission"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ part = particle_get_settings(context)
+
+ layout.use_property_split = True
+
+ col = layout.column()
+ col.prop(part, "emit_from")
+ col.prop(part, "use_modifier_stack")
+ if part.emit_from == 'FACE' or part.emit_from == 'VOLUME':
+ col.prop(part, "distribution")
+
if part.emit_from == 'VERT':
- row.prop(part, "use_emit_random")
+ col.prop(part, "use_emit_random", text="Random Order")
elif part.distribution == 'GRID':
- row.prop(part, "invert_grid")
- row.prop(part, "hexagonal_grid")
+ col.label(text="Grid")
+ col.prop(part, "invert_grid")
+ col.prop(part, "hexagonal_grid")
else:
- row.prop(part, "use_emit_random")
- row.prop(part, "use_even_distribution")
+ col.prop(part, "use_emit_random")
+ col.prop(part, "use_even_distribution")
if part.emit_from == 'FACE' or part.emit_from == 'VOLUME':
- layout.row().prop(part, "distribution", expand=True)
- row = layout.row()
if part.distribution == 'JIT':
- row.prop(part, "userjit", text="Particles/Face")
- row.prop(part, "jitter_factor", text="Jittering Amount", slider=True)
+ col.prop(part, "userjit", text="Particles/Face")
+ col.prop(part, "jitter_factor", text="Jittering Amount", slider=True)
elif part.distribution == 'GRID':
- row.prop(part, "grid_resolution")
- row.prop(part, "grid_random", text="Random", slider=True)
-
- row = layout.row()
- row.prop(part, "use_modifier_stack")
+ col.prop(part, "grid_resolution")
+ col.prop(part, "grid_random", text="Random", slider=True)
class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
bl_label = "Hair Dynamics"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
psys = context.particle_system
- engine = context.scene.render.engine
+ engine = context.engine
if psys is None:
return False
if psys.settings is None:
@@ -330,12 +341,23 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
psys = context.particle_system
self.layout.prop(psys, "use_hair_dynamics", text="")
+ def draw_header_preset(self, context):
+ psys = context.particle_system
+
+ if not psys.cloth:
+ return
+
+ layout = self.layout
+ layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
+ PARTICLE_PT_hair_dynamics_presets.draw_panel_header(layout)
+
def draw(self, context):
layout = self.layout
psys = context.particle_system
if not psys.cloth:
+ layout.label(text="Hair dynamics disabled")
return
cloth_md = psys.cloth
@@ -344,49 +366,20 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
- row = layout.row(align=True)
- row.menu("PARTICLE_MT_hair_dynamics_presets", text=bpy.types.PARTICLE_MT_hair_dynamics_presets.bl_label)
- row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMIN')
- row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMOUT').remove_active = True
-
- split = layout.column()
-
- col = split.column()
- col.label(text="Structure")
- col.prop(cloth, "mass")
- sub = col.column(align=True)
- subsub = sub.row(align=True)
- subsub.prop(cloth, "bending_stiffness", text="Stiffness")
- subsub.prop(psys.settings, "bending_random", text="Random")
- sub.prop(cloth, "bending_damping", text="Damping")
- # XXX has no noticeable effect with stiff hair structure springs
- #col.prop(cloth, "spring_damping", text="Damping")
-
- split.separator()
-
- col = split.column()
- col.label(text="Volume")
- col.prop(cloth, "air_damping", text="Air Drag")
- col.prop(cloth, "internal_friction", slider=True)
- sub = col.column(align=True)
- sub.prop(cloth, "density_target", text="Density Target")
- sub.prop(cloth, "density_strength", slider=True, text="Strength")
- col.prop(cloth, "voxel_cell_size")
+ layout.use_property_split = True
- split.separator()
+ layout.separator()
- col = split.column()
- col.label(text="Pinning")
- col.prop(cloth, "pin_stiffness", text="Goal Strength")
+ col = layout.column()
+ col.prop(cloth, "quality", text="Quality Steps", slider=True)
+ col.prop(psys.settings, "show_hair_grid", text="Display Hair Grid")
- split.separator()
+ layout.separator()
- col = split.column()
- col.label(text="Quality:")
- col.prop(cloth, "quality", text="Steps", slider=True)
+ col = layout.column()
+ col.prop(cloth, "pin_stiffness", text="Pin Goal Strength")
- row = col.row()
- row.prop(psys.settings, "show_hair_grid", text="HairGrid")
+ layout.separator()
if result:
box = layout.box()
@@ -409,15 +402,80 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
box.label("Error: %.5f .. %.5f (avg. %.5f)" % (result.min_error, result.max_error, result.avg_error))
+class PARTICLE_PT_hair_dynamics_structure(ParticleButtonsPanel, Panel):
+ bl_label = "Structure"
+ bl_parent_id = "PARTICLE_PT_hair_dynamics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.particle_system.cloth is not None
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ cloth_md = psys.cloth
+ cloth = cloth_md.settings
+ result = cloth_md.solver_result
+
+ layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
+
+ layout.use_property_split = True
+
+ col = layout.column()
+ col.prop(cloth, "mass")
+ sub = col.column(align=True)
+ sub.prop(cloth, "bending_stiffness", text="Stiffness")
+ sub.prop(psys.settings, "bending_random", text="Random")
+ col.prop(cloth, "bending_damping", text="Damping")
+ # XXX has no noticeable effect with stiff hair structure springs
+ #col.prop(cloth, "spring_damping", text="Damping")
+
+
+class PARTICLE_PT_hair_dynamics_volume(ParticleButtonsPanel, Panel):
+ bl_label = "Volume"
+ bl_parent_id = "PARTICLE_PT_hair_dynamics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.particle_system.cloth is not None
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ cloth_md = psys.cloth
+ cloth = cloth_md.settings
+ result = cloth_md.solver_result
+
+ layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
+
+ layout.use_property_split = True
+
+ col = layout.column()
+ col.prop(cloth, "air_damping", text="Air Drag")
+ col.prop(cloth, "internal_friction", slider=True)
+ col.prop(cloth, "voxel_cell_size")
+
+ col.separator()
+
+ col.prop(cloth, "density_target", text="Density Target")
+ col.prop(cloth, "density_strength", slider=True, text="Density Strength")
+
+
class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
bl_label = "Cache"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
psys = context.particle_system
- engine = context.scene.render.engine
+ engine = context.engine
if psys is None:
return False
if psys.settings is None:
@@ -442,7 +500,8 @@ class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
bl_label = "Velocity"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -463,37 +522,35 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
part = particle_get_settings(context)
layout.enabled = particle_panel_enabled(context, psys)
+ layout.use_property_split = True
- split = layout.split()
-
- col = split.column()
- col.label(text="Emitter Geometry:")
+ col = layout.column()
col.prop(part, "normal_factor")
sub = col.column(align=True)
- sub.prop(part, "tangent_factor")
- sub.prop(part, "tangent_phase", slider=True)
+ sub.prop(part, "tangent_factor", text="Tangent")
+ sub.prop(part, "tangent_phase", slider=True, text="Tangent Phase")
- col = split.column()
- col.label(text="Emitter Object:")
- col.prop(part, "object_align_factor", text="")
+ col.separator()
+
+ col.prop(part, "object_align_factor")
+
+ col.separator()
- layout.label(text="Other:")
- row = layout.row()
if part.emit_from == 'PARTICLE':
- row.prop(part, "particle_factor")
+ col.prop(part, "particle_factor")
else:
- row.prop(part, "object_factor", slider=True)
- row.prop(part, "factor_random")
+ col.prop(part, "object_factor", slider=True)
+ col.prop(part, "factor_random", text="Randomize")
# if part.type=='REACTOR':
- # sub.prop(part, "reactor_factor")
- # sub.prop(part, "reaction_shape", slider=True)
+ # sub.prop(part, "reactor_factor")
+ # sub.prop(part, "reaction_shape", slider=True)
class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
bl_label = "Rotation"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -526,37 +583,52 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
part = context.space_data.pin_id
layout.enabled = particle_panel_enabled(context, psys) and part.use_rotations
+ layout.use_property_split = True
- layout.label(text="Initial Orientation:")
+ col = layout.column()
- split = layout.split()
+ col.prop(part, "rotation_mode")
+ col.prop(part, "rotation_factor_random", slider=True, text="Randomize")
- col = split.column(align=True)
- col.prop(part, "rotation_mode", text="")
- col.prop(part, "rotation_factor_random", slider=True, text="Random")
+ col.separator()
- col = split.column(align=True)
col.prop(part, "phase_factor", slider=True)
- col.prop(part, "phase_factor_random", text="Random", slider=True)
+ col.prop(part, "phase_factor_random", text="Randomize Phase ", slider=True)
if part.type != 'HAIR':
- layout.label(text="Angular Velocity:")
+ col.prop(part, "use_dynamic_rotation")
- split = layout.split()
- col = split.column(align=True)
- col.prop(part, "angular_velocity_mode", text="")
- sub = col.column(align=True)
- sub.active = part.angular_velocity_mode != 'NONE'
- sub.prop(part, "angular_velocity_factor", text="")
+class PARTICLE_PT_rotation_angular_velocity(ParticleButtonsPanel, Panel):
+ bl_label = "Angular Velocity"
+ bl_parent_id = "PARTICLE_PT_rotation"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- col = split.column()
- col.prop(part, "use_dynamic_rotation")
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ if psys:
+ part = psys.settings
+ else:
+ part = context.space_data.pin_id
+
+ layout.enabled = particle_panel_enabled(context, psys) and part.use_rotations
+ layout.use_property_split = True
+
+ col = layout.column()
+
+ col.prop(part, "angular_velocity_mode", text="Axis")
+ sub = col.column(align=True)
+ sub.active = part.angular_velocity_mode != 'NONE'
+ sub.prop(part, "angular_velocity_factor", text="Amount")
class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
bl_label = "Physics"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -572,127 +644,87 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
psys = context.particle_system
part = particle_get_settings(context)
layout.enabled = particle_panel_enabled(context, psys)
- layout.row().prop(part, "physics_type", expand=True)
+ layout.prop(part, "physics_type")
- row = layout.row()
+ col = layout.column()
if part.physics_type != 'NO':
- col = row.column(align=True)
+ col = col.column()
col.prop(part, "mass")
col.prop(part, "use_multiply_size_mass", text="Multiply mass with size")
- if part.physics_type in {'NEWTON', 'FLUID'}:
- split = layout.split()
+ if part.physics_type == 'FLUID':
+ fluid = part.fluid
- col = split.column()
- col.label(text="Forces:")
- col.prop(part, "brownian_factor")
- col.prop(part, "drag_factor", slider=True)
- col.prop(part, "damping", slider=True)
+ col.label(text="Fluid")
+ col.prop(fluid, "solver")
+ col.prop(fluid, "stiffness", text="Stiffness")
+ col.prop(fluid, "linear_viscosity", text="Viscosity")
+ col.prop(fluid, "buoyancy", text="Buoyancy", slider=True)
- col = split.column()
- col.label(text="Integration:")
- col.prop(part, "integrator", text="")
- col.prop(part, "timestep")
- sub = col.row()
- sub.prop(part, "subframes")
- supports_courant = part.physics_type == 'FLUID'
- subsub = sub.row()
- subsub.enabled = supports_courant
- subsub.prop(part, "use_adaptive_subframes", text="")
- if supports_courant and part.use_adaptive_subframes:
- col.prop(part, "courant_target", text="Threshold")
+ col.label(text="Advanced")
- row = layout.row()
- row.prop(part, "use_size_deflect")
- row.prop(part, "use_die_on_collision")
+ if fluid.solver == 'DDR':
+ sub = col.column()
+ sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion)
+ sub.prop(fluid, "factor_repulsion")
- layout.prop(part, "collision_group")
+ sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity)
+ sub.prop(fluid, "factor_stiff_viscosity")
+
+ sub = col.column()
+ sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius)
+ sub.prop(fluid, "factor_radius")
+
+ sub.prop(fluid, "rest_density", slider=fluid.use_factor_density)
+ sub.prop(fluid, "use_factor_density")
+
+ if fluid.solver == 'CLASSICAL':
+ # With the classical solver, it is possible to calculate the
+ # spacing between particles when the fluid is at rest. This
+ # makes it easier to set stable initial conditions.
+ particle_volume = part.mass / fluid.rest_density
+ spacing = pow(particle_volume, 1.0 / 3.0)
+
+ sub.label(text="Spacing: %g" % spacing)
- if part.physics_type == 'FLUID':
- fluid = part.fluid
-
- split = layout.split()
- sub = split.row()
- sub.prop(fluid, "solver", expand=True)
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Fluid Properties:")
- col.prop(fluid, "stiffness", text="Stiffness")
- col.prop(fluid, "linear_viscosity", text="Viscosity")
- col.prop(fluid, "buoyancy", text="Buoyancy", slider=True)
-
- col = split.column()
- col.label(text="Advanced:")
-
- if fluid.solver == 'DDR':
- sub = col.row()
- sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion)
- sub.prop(fluid, "factor_repulsion", text="")
-
- sub = col.row()
- sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity)
- sub.prop(fluid, "factor_stiff_viscosity", text="")
-
- sub = col.row()
- sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius)
- sub.prop(fluid, "factor_radius", text="")
-
- sub = col.row()
- sub.prop(fluid, "rest_density", slider=fluid.use_factor_density)
- sub.prop(fluid, "use_factor_density", text="")
-
- if fluid.solver == 'CLASSICAL':
- # With the classical solver, it is possible to calculate the
- # spacing between particles when the fluid is at rest. This
- # makes it easier to set stable initial conditions.
- particle_volume = part.mass / fluid.rest_density
- spacing = pow(particle_volume, 1.0 / 3.0)
- sub = col.row()
- sub.label(text="Spacing: %g" % spacing)
-
- elif fluid.solver == 'DDR':
- split = layout.split()
-
- col = split.column()
- col.label(text="Springs:")
- col.prop(fluid, "spring_force", text="Force")
- col.prop(fluid, "use_viscoelastic_springs")
- sub = col.column(align=True)
- sub.active = fluid.use_viscoelastic_springs
- sub.prop(fluid, "yield_ratio", slider=True)
- sub.prop(fluid, "plasticity", slider=True)
-
- col = split.column()
- col.label(text="Advanced:")
- sub = col.row()
- sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length)
- sub.prop(fluid, "factor_rest_length", text="")
- col.label(text="")
- sub = col.column()
- sub.active = fluid.use_viscoelastic_springs
- sub.prop(fluid, "use_initial_rest_length")
- sub.prop(fluid, "spring_frames", text="Frames")
+ elif fluid.solver == 'DDR':
+
+ col.label(text="Springs")
+ col.prop(fluid, "spring_force", text="Force")
+ col.prop(fluid, "use_viscoelastic_springs")
+
+ sub = col.column()
+ sub.active = fluid.use_viscoelastic_springs
+ sub.prop(fluid, "yield_ratio", slider=True)
+ sub.prop(fluid, "plasticity", slider=True)
+
+ col.label(text="Advanced")
+ sub = col.column()
+ sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length)
+ sub.prop(fluid, "factor_rest_length", text="")
+
+ sub = col.column()
+ sub.active = fluid.use_viscoelastic_springs
+ sub.prop(fluid, "use_initial_rest_length")
+ sub.prop(fluid, "spring_frames", text="Frames")
elif part.physics_type == 'KEYED':
- split = layout.split()
- sub = split.column()
- row = layout.row()
- col = row.column()
- col.active = not psys.use_keyed_timing
- col.prop(part, "keyed_loops", text="Loops")
+ sub = col.column()
+ sub.active = not psys.use_keyed_timing
+ sub.prop(part, "keyed_loops", text="Loops")
if psys:
- row.prop(psys, "use_keyed_timing", text="Use Timing")
+ col.prop(psys, "use_keyed_timing", text="Use Timing")
+
+ col.label(text="Keys")
- layout.label(text="Keys:")
elif part.physics_type == 'BOIDS':
boids = part.boids
@@ -790,15 +822,102 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
sub.prop(key, "system", text="System")
+class PARTICLE_PT_physics_deflection(ParticleButtonsPanel, Panel):
+ bl_label = "Deflection"
+ bl_parent_id = "PARTICLE_PT_physics"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.physics_type in {'NEWTON', 'FLUID'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+
+ layout.enabled = particle_panel_enabled(context, psys)
+
+ col = layout.column()
+ col.prop(part, "use_size_deflect")
+ col.prop(part, "use_die_on_collision")
+
+ col.prop(part, "collision_group")
+
+
+class PARTICLE_PT_physics_forces(ParticleButtonsPanel, Panel):
+ bl_label = "Forces"
+ bl_parent_id = "PARTICLE_PT_physics"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.physics_type == 'NEWTON'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+
+ layout.enabled = particle_panel_enabled(context, psys)
+
+ col = layout.column()
+
+ col.prop(part, "brownian_factor")
+ col.prop(part, "drag_factor", slider=True)
+ col.prop(part, "damping", slider=True)
+
+
+class PARTICLE_PT_physics_integration(ParticleButtonsPanel, Panel):
+ bl_label = "Integration"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = "PARTICLE_PT_physics"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.physics_type == 'NEWTON'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+
+ layout.enabled = particle_panel_enabled(context, psys)
+
+ col = layout.column()
+
+ col.prop(part, "integrator")
+ col.prop(part, "timestep")
+ sub = col.row()
+ sub.prop(part, "subframes")
+ supports_courant = part.physics_type == 'FLUID'
+ subsub = sub.row()
+ subsub.enabled = supports_courant
+ subsub.prop(part, "use_adaptive_subframes", text="")
+ if supports_courant and part.use_adaptive_subframes:
+ col.prop(part, "courant_target", text="Threshold")
+
+
class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
bl_label = "Boid Brain"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
psys = context.particle_system
settings = particle_get_settings(context)
- engine = context.scene.render.engine
+ engine = context.engine
if settings is None:
return False
@@ -895,12 +1014,13 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
bl_label = "Render"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
settings = particle_get_settings(context)
- engine = context.scene.render.engine
+ engine = context.engine
if settings is None:
return False
@@ -908,257 +1028,453 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
psys = context.particle_system
part = particle_get_settings(context)
+ layout.prop(part, "render_type", text="Render As")
+
+ if part.type == 'EMITTER' or \
+ (part.render_type in {'OBJECT', 'COLLECTION'} and part.type == 'HAIR'):
+ if part.render_type not in {'NONE'}:
+
+ col = layout.column(align=True)
+ col.prop(part, "particle_size", text="Scale")
+ col.prop(part, "size_random", slider=True, text="Scale Randomness")
+
if psys:
- row = layout.row()
- if part.render_type in {'OBJECT', 'GROUP'}:
- row.enabled = False
- row.prop(part, "material_slot", text="")
- row.prop(psys, "parent")
+ col = layout.column()
+ if part.render_type not in {'OBJECT', 'COLLECTION', 'NONE'}:
+ # col.enabled = False
+ col.prop(part, "material_slot", text="Material")
+ col.prop(psys, "parent", text="Coordinate System")
- split = layout.split()
- col = split.column()
- col.prop(part, "use_render_emitter")
- col.prop(part, "use_parent_particles")
+class PARTICLE_PT_render_extra(ParticleButtonsPanel, Panel):
+ bl_label = "Extra"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- col = split.column()
- col.prop(part, "show_unborn")
- col.prop(part, "use_dead")
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type != 'NONE'
- layout.row().prop(part, "render_type", expand=True)
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
- split = layout.split()
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
- col = split.column()
+ col = layout.column()
- if part.render_type == 'LINE':
- col.prop(part, "line_length_tail")
- col.prop(part, "line_length_head")
+ col = layout.column()
+ col.prop(part, "use_parent_particles", text="Parent Particles")
+ col.prop(part, "show_unborn", text="Unborn")
+ col.prop(part, "use_dead", text="Dead")
- split.prop(part, "use_velocity_length")
- elif part.render_type == 'PATH':
- col.prop(part, "use_strand_primitive")
- sub = col.column()
- sub.active = (part.use_strand_primitive is False)
- sub.prop(part, "use_render_adaptive")
- sub = col.column()
- sub.active = part.use_render_adaptive or part.use_strand_primitive is True
- sub.prop(part, "adaptive_angle")
- sub = col.column()
- sub.active = (part.use_render_adaptive is True and part.use_strand_primitive is False)
- sub.prop(part, "adaptive_pixel")
- col.prop(part, "use_hair_bspline")
- col.prop(part, "render_step", text="Steps")
- col = split.column()
- col.label(text="Timing:")
- col.prop(part, "use_absolute_path_time")
+class PARTICLE_PT_render_line(ParticleButtonsPanel, Panel):
+ bl_label = "Line"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- if part.type == 'HAIR' or psys.point_cache.is_baked:
- col.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time)
- else:
- col.prop(part, "trail_count")
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'LINE'
- col.prop(part, "path_end", text="End", slider=not part.use_absolute_path_time)
- col.prop(part, "length_random", text="Random", slider=True)
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
- row = layout.row()
- col = row.column()
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
- if part.type == 'HAIR' and part.use_strand_primitive is True and part.child_type == 'INTERPOLATED':
- layout.prop(part, "use_simplify")
- if part.use_simplify is True:
- row = layout.row()
- row.prop(part, "simplify_refsize")
- row.prop(part, "simplify_rate")
- row.prop(part, "simplify_transition")
- row = layout.row()
- row.prop(part, "use_simplify_viewport")
- sub = row.row()
- sub.active = part.use_simplify_viewport is True
- sub.prop(part, "simplify_viewport")
+ col = layout.column()
- elif part.render_type == 'OBJECT':
- col.prop(part, "dupli_object")
- sub = col.row()
- sub.prop(part, "use_global_dupli")
- sub.prop(part, "use_rotation_dupli")
- sub.prop(part, "use_scale_dupli")
- elif part.render_type == 'GROUP':
- col.prop(part, "dupli_group")
- split = layout.split()
+ col.separator()
+ sub = col.column(align=True)
+ sub.prop(part, "line_length_tail", text="Length Tail")
+ sub.prop(part, "line_length_head", text="Head")
+ col.prop(part, "use_velocity_length", text="Velocity Length")
- col = split.column()
- col.prop(part, "use_whole_group")
- sub = col.column()
- sub.active = (part.use_whole_group is False)
- sub.prop(part, "use_group_pick_random")
- sub.prop(part, "use_group_count")
- col = split.column()
- sub = col.column()
- sub.active = (part.use_whole_group is False)
- sub.prop(part, "use_global_dupli")
- sub.prop(part, "use_rotation_dupli")
- sub.prop(part, "use_scale_dupli")
+class PARTICLE_PT_render_path(ParticleButtonsPanel, Panel):
+ bl_label = "Path"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- if part.use_group_count and not part.use_whole_group:
- row = layout.row()
- row.template_list("UI_UL_list", "particle_dupli_weights", part, "dupli_weights",
- part, "active_dupliweight_index")
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'PATH'
- col = row.column()
- sub = col.row()
- subsub = sub.column(align=True)
- subsub.operator("particle.dupliob_copy", icon='ZOOMIN', text="")
- subsub.operator("particle.dupliob_remove", icon='ZOOMOUT', text="")
- subsub.operator("particle.dupliob_move_up", icon='TRIA_UP', text="")
- subsub.operator("particle.dupliob_move_down", icon='TRIA_DOWN', text="")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
- weight = part.active_dupliweight
- if weight:
- row = layout.row()
- row.prop(weight, "count")
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
- elif part.render_type == 'BILLBOARD':
- ob = context.object
+ col = layout.column()
- col.label(text="Align:")
+ col.prop(part, "use_strand_primitive")
+ sub = col.column()
+ sub.active = (part.use_strand_primitive is False)
+ sub.prop(part, "use_render_adaptive")
+ sub = col.column()
+ sub.active = part.use_render_adaptive or part.use_strand_primitive is True
+ sub.prop(part, "adaptive_angle")
+ sub = col.column()
+ sub.active = (part.use_render_adaptive is True and part.use_strand_primitive is False)
+ sub.prop(part, "adaptive_pixel")
+ col.prop(part, "use_hair_bspline")
+ col.prop(part, "render_step", text="Steps")
+
+
+class PARTICLE_PT_render_path_timing(ParticleButtonsPanel, Panel):
+ bl_label = "Timing"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- row = layout.row()
- row.prop(part, "billboard_align", expand=True)
- row.prop(part, "lock_billboard", text="Lock")
- row = layout.row()
- row.prop(part, "billboard_object")
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'PATH'
- row = layout.row()
- col = row.column(align=True)
- col.label(text="Tilt:")
- col.prop(part, "billboard_tilt", text="Angle", slider=True)
- col.prop(part, "billboard_tilt_random", text="Random", slider=True)
- col = row.column()
- col.prop(part, "billboard_offset")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
- row = layout.row()
- col = row.column()
- col.prop(part, "billboard_size", text="Scale")
- if part.billboard_align == 'VEL':
- col = row.column(align=True)
- col.label("Velocity Scale:")
- col.prop(part, "billboard_velocity_head", text="Head")
- col.prop(part, "billboard_velocity_tail", text="Tail")
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
- if psys:
- col = layout.column()
- col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_textures")
- col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_textures")
+ col = layout.column()
- split = layout.split(percentage=0.33)
- split.label(text="Split UVs:")
- split.prop(part, "billboard_uv_split", text="Number of splits")
+ col.prop(part, "use_absolute_path_time")
- if psys:
- col = layout.column()
- col.active = part.billboard_uv_split > 1
- col.prop_search(psys, "billboard_split_uv", ob.data, "uv_textures")
+ if part.type == 'HAIR' or psys.point_cache.is_baked:
+ col.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time)
+ else:
+ col.prop(part, "trail_count")
+
+ col.prop(part, "path_end", text="End", slider=not part.use_absolute_path_time)
+ col.prop(part, "length_random", text="Random", slider=True)
+
+
+class PARTICLE_PT_render_object(ParticleButtonsPanel, Panel):
+ bl_label = "Object"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'OBJECT'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
+
+ col = layout.column()
+
+ col.prop(part, "dupli_object", text="Instance Object")
+ sub = col.column()
+ sub.prop(part, "use_global_dupli", text="Global Coordinates")
+ sub.prop(part, "use_rotation_dupli", text="Object Rotation")
+ sub.prop(part, "use_scale_dupli", text="Object Scale")
- row = col.row()
- row.label(text="Animate:")
- row.prop(part, "billboard_animation", text="")
- row.label(text="Offset:")
- row.prop(part, "billboard_offset_split", text="")
- if part.render_type == 'HALO' or part.render_type == 'LINE' or part.render_type == 'BILLBOARD':
+class PARTICLE_PT_render_collection(ParticleButtonsPanel, Panel):
+ bl_label = "Collection"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'COLLECTION'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
+
+ col = layout.column()
+
+ col.prop(part, "dupli_group")
+
+ col.prop(part, "use_whole_group")
+ sub = col.column()
+ sub.active = (part.use_whole_group is False)
+ sub.prop(part, "use_group_pick_random")
+ sub.prop(part, "use_global_dupli", text="Global Coordinates")
+ sub.prop(part, "use_rotation_dupli", text="Object Rotation")
+ sub.prop(part, "use_scale_dupli", text="Object Scale")
+
+
+class PARTICLE_PT_render_collection_use_count(ParticleButtonsPanel, Panel):
+ bl_label = "Use Count"
+ bl_parent_id = "PARTICLE_PT_render_collection"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'COLLECTION'
+
+ def draw_header(self, context):
+ layout = self.layout
+ part = particle_get_settings(context)
+
+ layout.active = not part.use_whole_group
+
+ layout.prop(part, "use_group_count", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
+
+ col = layout.column()
+
+ layout.active = part.use_group_count and not part.use_whole_group
+
+ row = layout.row()
+ row.template_list("UI_UL_list", "particle_dupli_weights", part, "dupli_weights",
+ part, "active_dupliweight_index")
+
+ col = row.column()
+ sub = col.row()
+ subsub = sub.column(align=True)
+ subsub.operator("particle.dupliob_copy", icon='ZOOMIN', text="")
+ subsub.operator("particle.dupliob_remove", icon='ZOOMOUT', text="")
+ subsub.operator("particle.dupliob_move_up", icon='TRIA_UP', text="")
+ subsub.operator("particle.dupliob_move_down", icon='TRIA_DOWN', text="")
+ subsub.separator()
+ subsub.operator("particle.dupliob_refresh", icon='FILE_REFRESH', text="")
+
+ weight = part.active_dupliweight
+ if weight:
row = layout.row()
- col = row.column()
- col.prop(part, "trail_count")
- if part.trail_count > 1:
- col.prop(part, "use_absolute_path_time", text="Length in Frames")
- col = row.column()
- col.prop(part, "path_end", text="Length", slider=not part.use_absolute_path_time)
- col.prop(part, "length_random", text="Random", slider=True)
- else:
- col = row.column()
- col.label(text="")
+ row.prop(weight, "count")
- if part.type == 'EMITTER' or \
- (part.render_type in {'OBJECT', 'GROUP'} and part.type == 'HAIR'):
- row = layout.row(align=True)
- row.prop(part, "particle_size")
- row.prop(part, "size_random", slider=True)
+
+class PARTICLE_PT_render_billboards_alignment(ParticleButtonsPanel, Panel):
+ bl_label = "Billboard Alignment"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'BILLBOARD'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
+
+ col = layout.column()
+
+ col.prop(part, "billboard_align", text="Align To")
+ col.prop(part, "lock_billboard", text="Lock Axis")
+ col.prop(part, "billboard_object")
+
+
+class PARTICLE_PT_render_billboards_tilt(ParticleButtonsPanel, Panel):
+ bl_label = "Billboard Tilt"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'BILLBOARD'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
+
+ col = layout.column()
+
+ sub = col.column(align=True)
+ sub.prop(part, "billboard_tilt", text="Angle", slider=True)
+ sub.prop(part, "billboard_tilt_random", text="Random", slider=True)
+
+ sub = col.column(align=True)
+ sub.prop(part, "billboard_offset")
+ col.prop(part, "billboard_size", text="Scale")
+ if part.billboard_align == 'VEL':
+ col = col.column(align=True)
+ col.prop(part, "billboard_velocity_head", text="Velocity ScaleHead")
+ col.prop(part, "billboard_velocity_tail", text="Tail")
+
+
+class PARTICLE_PT_render_billboards_uv(ParticleButtonsPanel, Panel):
+ bl_label = "Billboard UVs"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type == 'BILLBOARD'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ ob = context.object
+ part = particle_get_settings(context)
+
+ col = layout.column()
+
+ if psys:
+ col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_layers")
+ col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_layers")
+
+ col.prop(part, "billboard_uv_split", text="Split UVs")
+
+ if psys:
+ sub = col.column()
+ sub.active = part.billboard_uv_split > 1
+ sub.prop_search(psys, "billboard_split_uv", ob.data, "uv_layers")
+
+ sub.prop(part, "billboard_animation")
+ sub.prop(part, "billboard_offset_split")
+
+
+class PARTICLE_PT_render_trails(ParticleButtonsPanel, Panel):
+ bl_label = "Trails"
+ bl_parent_id = "PARTICLE_PT_render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.render_type in {'HALO', 'LINE', 'BILLBOARD'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+
+ col = layout.column()
+
+ col.prop(part, "trail_count")
+
+ sub = col.column()
+ sub.active = (part.trail_count > 1)
+ sub.prop(part, "use_absolute_path_time", text="Length in Frames")
+ sub.prop(part, "path_end", text="Length", slider=not part.use_absolute_path_time)
+ sub.prop(part, "length_random", text="Random Length", slider=True)
class PARTICLE_PT_draw(ParticleButtonsPanel, Panel):
- bl_label = "Display"
+ bl_label = "Viewport Display"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
settings = particle_get_settings(context)
- engine = context.scene.render.engine
+ engine = context.engine
if settings is None:
return False
return engine in cls.COMPAT_ENGINES
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
psys = context.particle_system
part = particle_get_settings(context)
- row = layout.row()
- row.prop(part, "draw_method", expand=True)
- row.prop(part, "show_guide_hairs")
+ layout.prop(part, "draw_method", text="Display As")
if part.draw_method == 'NONE' or (part.render_type == 'NONE' and part.draw_method == 'RENDER'):
return
path = (part.render_type == 'PATH' and part.draw_method == 'RENDER') or part.draw_method == 'PATH'
- row = layout.row()
- row.prop(part, "draw_percentage", slider=True)
+ layout.separator()
+
+ col = layout.column()
+ col.prop(part, "draw_color", text="Color")
+ if part.draw_color in {'VELOCITY', 'ACCELERATION'}:
+ col.prop(part, "color_maximum", text="Fade Distance")
+
+ col = layout.column()
+
+ if path:
+ col.prop(part, "draw_step", text="Strand Steps")
+ col.prop(part, "draw_percentage", slider=True, text="Amount")
if part.draw_method != 'RENDER' or part.render_type == 'HALO':
- row.prop(part, "draw_size")
- else:
- row.label(text="")
+ col.prop(part, "draw_size", text="Size")
if part.draw_percentage != 100 and psys is not None:
if part.type == 'HAIR':
if psys.use_hair_dynamics and psys.point_cache.is_baked is False:
- layout.row().label(text="Display percentage makes dynamics inaccurate without baking!")
+ layout.row().label(text="Display percentage makes dynamics inaccurate without baking")
else:
phystype = part.physics_type
if phystype != 'NO' and phystype != 'KEYED' and psys.point_cache.is_baked is False:
- layout.row().label(text="Display percentage makes dynamics inaccurate without baking!")
+ layout.row().label(text="Display percentage makes dynamics inaccurate without baking")
+ else:
+ layout.row().label(text="")
- row = layout.row()
- col = row.column()
+ col = layout.column()
+ col.prop(part, "show_guide_hairs", text="Guide Hairs")
col.prop(part, "show_size")
col.prop(part, "show_velocity")
col.prop(part, "show_number")
if part.physics_type == 'BOIDS':
col.prop(part, "show_health")
- col = row.column(align=True)
- col.label(text="Color:")
- col.prop(part, "draw_color", text="")
- sub = col.row(align=True)
- sub.active = (part.draw_color in {'VELOCITY', 'ACCELERATION'})
- sub.prop(part, "color_maximum", text="Max")
-
- if path:
- col.prop(part, "draw_step")
-
class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
bl_label = "Children"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -1172,37 +1488,91 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
layout.row().prop(part, "child_type", expand=True)
+ layout.use_property_split = True
+
if part.child_type == 'NONE':
return
- row = layout.row()
+ col = layout.column()
- col = row.column(align=True)
- col.prop(part, "child_nbr", text="Display")
- col.prop(part, "rendered_child_count", text="Render")
+ sub = col.column(align=True)
+ sub.prop(part, "child_nbr", text="Display Amount")
+ sub.prop(part, "rendered_child_count", text="Render Amount")
+
+ col.separator()
+
+ col.prop(part, "child_length", slider=True)
+ col.prop(part, "child_length_threshold", slider=True)
+ if psys:
+ col.prop(psys, "child_seed", text="Seed")
+
+ col.separator()
if part.child_type == 'INTERPOLATED':
- col = row.column()
- if psys:
- col.prop(psys, "child_seed", text="Seed")
col.prop(part, "virtual_parents", slider=True)
col.prop(part, "create_long_hair_children")
else:
- col = row.column(align=True)
- col.prop(part, "child_size", text="Size")
- col.prop(part, "child_size_random", text="Random")
+ col.separator()
+ sub = col.column(align=True)
+ sub.prop(part, "child_size", text="Size")
+ sub.prop(part, "child_size_random", text="Randomize Size", slider=True)
- split = layout.split()
+ if part.child_type == 'SIMPLE':
+ col.separator()
+ col.prop(part, "child_radius", text="Radius")
+ col.prop(part, "child_roundness", text="Roundness", slider=True)
+ elif part.virtual_parents > 0.0:
+ sub = col.column(align=True)
+ sub.label(text="Parting not available with virtual parents")
- col = split.column()
- col.label(text="Effects:")
- sub = col.column(align=True)
- if part.child_type == 'SIMPLE':
- sub.prop(part, "twist")
- sub.prop(part, "use_twist_curve")
- if part.use_twist_curve:
- sub.template_curve_mapping(part, "twist_curve")
+class PARTICLE_PT_children_parting(ParticleButtonsPanel, Panel):
+ bl_label = "Parting"
+ bl_parent_id = "PARTICLE_PT_children"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.child_type == 'INTERPOLATED'
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+
+ layout.use_property_split = True
+
+ col = layout.column()
+ col.prop(part, "child_parting_factor", text="Parting", slider=True)
+ col.prop(part, "child_parting_min", text="Min")
+ col.prop(part, "child_parting_max", text="Max")
+
+
+class PARTICLE_PT_children_clumping(ParticleButtonsPanel, Panel):
+ bl_label = "Clumping"
+ bl_parent_id = "PARTICLE_PT_children"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.child_type != 'NONE'
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+
+ layout.use_property_split = True
+
+ col = layout.column()
+
+ sub = col.column()
sub.prop(part, "use_clump_curve")
if part.use_clump_curve:
@@ -1216,28 +1586,33 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
subsub.enabled = part.use_clump_noise
subsub.prop(part, "clump_noise_size")
- sub = col.column(align=True)
- sub.prop(part, "child_length", slider=True)
- sub.prop(part, "child_length_threshold", slider=True)
-
if part.child_type == 'SIMPLE':
- sub = col.column(align=True)
- sub.prop(part, "child_radius", text="Radius")
- sub.prop(part, "child_roundness", text="Roundness", slider=True)
- if psys:
- sub.prop(psys, "child_seed", text="Seed")
- elif part.virtual_parents > 0.0:
- sub = col.column(align=True)
- sub.label(text="Parting not")
- sub.label(text="available with")
- sub.label(text="virtual parents")
- else:
- sub = col.column(align=True)
- sub.prop(part, "child_parting_factor", text="Parting", slider=True)
- sub.prop(part, "child_parting_min", text="Min")
- sub.prop(part, "child_parting_max", text="Max")
+ sub.prop(part, "twist")
+ sub.prop(part, "use_twist_curve")
+ if part.use_twist_curve:
+ sub.template_curve_mapping(part, "twist_curve")
+
+
+class PARTICLE_PT_children_roughness(ParticleButtonsPanel, Panel):
+ bl_label = "Roughness"
+ bl_parent_id = "PARTICLE_PT_children"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.child_type != 'NONE'
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
- col = split.column()
+ layout.use_property_split = True
+
+ col = layout.column()
col.prop(part, "use_roughness_curve")
if part.use_roughness_curve:
@@ -1246,8 +1621,6 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
sub.prop(part, "roughness_1", text="Roughness")
sub.prop(part, "roughness_1_size", text="Size")
else:
- col.label(text="Roughness:")
-
sub = col.column(align=True)
sub.prop(part, "roughness_1", text="Uniform")
sub.prop(part, "roughness_1_size", text="Size")
@@ -1261,31 +1634,55 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
sub.prop(part, "roughness_2_size", text="Size")
sub.prop(part, "roughness_2_threshold", slider=True)
- layout.row().label(text="Kink:")
- layout.row().prop(part, "kink", expand=True)
- split = layout.split()
- split.active = part.kink != 'NO'
+class PARTICLE_PT_children_kink(ParticleButtonsPanel, Panel):
+ bl_label = "Kink"
+ bl_parent_id = "PARTICLE_PT_children"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ part = particle_get_settings(context)
+ return part.child_type != 'NONE'
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ part = particle_get_settings(context)
+
+ layout.use_property_split = True
+
+ col = layout.column()
+
+ col.prop(part, "kink", text="Kink Type")
+ col = layout.column()
+ col.active = part.kink != 'NO'
if part.kink == 'SPIRAL':
- col = split.column()
- sub = col.column(align=True)
- sub.prop(part, "kink_amplitude", text="Radius")
- sub.prop(part, "kink_amplitude_random", text="Random", slider=True)
- sub = col.column(align=True)
+
+ sub = col.column()
+ sub.prop(part, "kink_amplitude", text="Amplitude")
+ sub.prop(part, "kink_amplitude_random", text="Randomize Amplitude", slider=True)
+
+ col.separator()
+
+ sub = col.column()
sub.prop(part, "kink_axis")
- sub.prop(part, "kink_axis_random", text="Random", slider=True)
- col = split.column(align=True)
+ sub.prop(part, "kink_axis_random", text="Randomize Axis", slider=True)
+
+ col.separator()
+
col.prop(part, "kink_frequency", text="Frequency")
col.prop(part, "kink_shape", text="Shape", slider=True)
col.prop(part, "kink_extra_steps", text="Steps")
- else:
- col = split.column()
+
+ elif part.kink in {'CURL', 'RADIAL', 'WAVE', 'BRAID', 'WAVE'}:
sub = col.column(align=True)
sub.prop(part, "kink_amplitude")
sub.prop(part, "kink_amplitude_clump", text="Clump", slider=True)
col.prop(part, "kink_flat", slider=True)
- col = split.column(align=True)
col.prop(part, "kink_frequency")
col.prop(part, "kink_shape", slider=True)
@@ -1293,7 +1690,7 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
bl_label = "Field Weights"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -1314,41 +1711,85 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
class PARTICLE_PT_force_fields(ParticleButtonsPanel, Panel):
bl_label = "Force Field Settings"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
part = particle_get_settings(context)
- row = layout.row()
- row.prop(part, "use_self_effect")
- row.prop(part, "effector_amount", text="Amount")
+ col = layout.column()
+ col.prop(part, "use_self_effect")
+ col.prop(part, "effector_amount", text="Effector Amount")
+
+
+class PARTICLE_PT_force_fields_type1(ParticleButtonsPanel, Panel):
+ bl_label = "Type 1"
+ bl_parent_id = "PARTICLE_PT_force_fields"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ part = particle_get_settings(context)
- split = layout.split(percentage=0.2)
- split.label(text="Type 1:")
- split.prop(part.force_field_1, "type", text="")
+ col = layout.column()
+ col.prop(part.force_field_1, "type", text="Type 1")
basic_force_field_settings_ui(self, context, part.force_field_1)
- if part.force_field_1.type != 'NONE':
- layout.label(text="Falloff:")
- basic_force_field_falloff_ui(self, context, part.force_field_1)
- if part.force_field_1.type != 'NONE':
- layout.label(text="")
- split = layout.split(percentage=0.2)
- split.label(text="Type 2:")
- split.prop(part.force_field_2, "type", text="")
+class PARTICLE_PT_force_fields_type2(ParticleButtonsPanel, Panel):
+ bl_label = "Type 2"
+ bl_parent_id = "PARTICLE_PT_force_fields"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ part = particle_get_settings(context)
+
+ col = layout.column()
+ col.prop(part.force_field_2, "type", text="Type 2")
basic_force_field_settings_ui(self, context, part.force_field_2)
- if part.force_field_2.type != 'NONE':
- layout.label(text="Falloff:")
+
+
+class PARTICLE_PT_force_fields_type1_falloff(ParticleButtonsPanel, Panel):
+ bl_label = "Falloff"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = "PARTICLE_PT_force_fields_type1"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ part = particle_get_settings(context)
+
+ basic_force_field_falloff_ui(self, context, part.force_field_1)
+
+
+class PARTICLE_PT_force_fields_type2_falloff(ParticleButtonsPanel, Panel):
+ bl_label = "Falloff"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = "PARTICLE_PT_force_fields_type2"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ part = particle_get_settings(context)
+
basic_force_field_falloff_ui(self, context, part.force_field_2)
class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
bl_label = "Vertex Groups"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -1358,6 +1799,7 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
psys = context.particle_system
@@ -1417,30 +1859,118 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
# row.prop(psys, "invert_vertex_group_field", text="")
+class PARTICLE_PT_textures(ParticleButtonsPanel, Panel):
+ bl_label = "Textures"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ if context.particle_system is None:
+ return False
+ return particle_panel_poll(cls, context)
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ part = psys.settings
+
+ row = layout.row()
+ row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
+
+ col = row.column(align=True)
+ col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
+ col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
+ col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
+
+ if not part.active_texture:
+ layout.template_ID(part, "active_texture", new="texture.new")
+ else:
+ slot = part.texture_slots[part.active_texture_index]
+ layout.template_ID(slot, "texture", new="texture.new")
+
+
+class PARTICLE_PT_hair_shape(ParticleButtonsPanel, Panel):
+ bl_label = "Hair Shape"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ if context.particle_system is None:
+ return False
+ return particle_panel_poll(cls, context)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ psys = context.particle_system
+ part = psys.settings
+
+ layout.prop(part, "shape", text="Strand Shape")
+
+ col = layout.column(align=True)
+ col.prop(part, "root_radius", text="Radius Root")
+ col.prop(part, "tip_radius", text="Tip")
+
+ col = layout.column()
+ col.prop(part, "radius_scale", text="Radius Scaling")
+ col.prop(part, "use_close_tip")
+
+
class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "particle_system.settings"
_property_type = bpy.types.ParticleSettings
classes = (
PARTICLE_MT_specials,
- PARTICLE_MT_hair_dynamics_presets,
+ PARTICLE_PT_hair_dynamics_presets,
PARTICLE_UL_particle_systems,
PARTICLE_PT_context_particles,
PARTICLE_PT_emission,
+ PARTICLE_PT_emission_source,
PARTICLE_PT_hair_dynamics,
+ PARTICLE_PT_hair_dynamics_structure,
+ PARTICLE_PT_hair_dynamics_volume,
PARTICLE_PT_cache,
PARTICLE_PT_velocity,
PARTICLE_PT_rotation,
+ PARTICLE_PT_rotation_angular_velocity,
PARTICLE_PT_physics,
+ PARTICLE_PT_physics_forces,
+ PARTICLE_PT_physics_deflection,
+ PARTICLE_PT_physics_integration,
PARTICLE_PT_boidbrain,
PARTICLE_PT_render,
+ PARTICLE_PT_render_line,
+ PARTICLE_PT_render_path,
+ PARTICLE_PT_render_path_timing,
+ PARTICLE_PT_render_object,
+ PARTICLE_PT_render_collection,
+ PARTICLE_PT_render_collection_use_count,
+ PARTICLE_PT_render_billboards_tilt,
+ PARTICLE_PT_render_billboards_uv,
+ PARTICLE_PT_render_trails,
+ PARTICLE_PT_render_extra,
PARTICLE_PT_draw,
PARTICLE_PT_children,
+ PARTICLE_PT_children_parting,
+ PARTICLE_PT_children_clumping,
+ PARTICLE_PT_children_roughness,
+ PARTICLE_PT_children_kink,
+ PARTICLE_PT_hair_shape,
PARTICLE_PT_field_weights,
PARTICLE_PT_force_fields,
+ PARTICLE_PT_force_fields_type1,
+ PARTICLE_PT_force_fields_type1_falloff,
+ PARTICLE_PT_force_fields_type2,
+ PARTICLE_PT_force_fields_type2_falloff,
PARTICLE_PT_vertexgroups,
+ PARTICLE_PT_textures,
PARTICLE_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 45cddd3d6b9..2f659af3891 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Menu, Panel
+from bl_operators.presets import PresetMenu
from .properties_physics_common import (
point_cache_ui,
@@ -30,11 +31,11 @@ def cloth_panel_enabled(md):
return md.point_cache.is_baked is False
-class CLOTH_MT_presets(Menu):
+class CLOTH_PT_presets(PresetMenu):
bl_label = "Cloth Presets"
preset_subdir = "cloth"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "cloth.preset_add"
class PhysicButtonsPanel:
@@ -45,13 +46,15 @@ class PhysicButtonsPanel:
@classmethod
def poll(cls, context):
ob = context.object
- rd = context.scene.render
- return (ob and ob.type == 'MESH') and (rd.engine in cls.COMPAT_ENGINES) and (context.cloth)
+ return (ob and ob.type == 'MESH') and (context.engine in cls.COMPAT_ENGINES) and (context.cloth)
class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
bl_label = "Cloth"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw_header_preset(self, context):
+ CLOTH_PT_presets.draw_panel_header(self.layout)
def draw(self, context):
layout = self.layout
@@ -64,14 +67,6 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
split = layout.split(percentage=0.25)
- split.label(text="Presets:")
- sub = split.row(align=True)
- sub.menu("CLOTH_MT_presets", text=bpy.types.CLOTH_MT_presets.bl_label)
- sub.operator("cloth.preset_add", text="", icon='ZOOMIN')
- sub.operator("cloth.preset_add", text="", icon='ZOOMOUT').remove_active = True
-
- split = layout.split(percentage=0.25)
-
split.label(text="Quality:")
split.prop(cloth, "quality", text="Steps")
@@ -131,9 +126,10 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
- bl_label = "Cloth Cache"
+ bl_label = "Cache"
+ bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
md = context.cloth
@@ -141,9 +137,10 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
- bl_label = "Cloth Collision"
+ bl_label = "Collision"
+ bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
cloth = context.cloth.collision_settings
@@ -181,9 +178,10 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
- bl_label = "Cloth Stiffness Scaling"
+ bl_label = "Stiffness Scaling"
+ bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
cloth = context.cloth.settings
@@ -214,9 +212,10 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_sewing(PhysicButtonsPanel, Panel):
- bl_label = "Cloth Sewing Springs"
+ bl_label = "Sewing Springs"
+ bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
cloth = context.cloth.settings
@@ -248,9 +247,10 @@ class PHYSICS_PT_cloth_sewing(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
- bl_label = "Cloth Field Weights"
+ bl_label = "Field Weights"
+ bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
cloth = context.cloth.settings
@@ -258,7 +258,7 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
classes = (
- CLOTH_MT_presets,
+ CLOTH_PT_presets,
PHYSICS_PT_cloth,
PHYSICS_PT_cloth_cache,
PHYSICS_PT_cloth_collision,
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index b821b20a1ae..e071de0108b 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -30,8 +30,7 @@ class PhysicButtonsPanel:
@classmethod
def poll(cls, context):
- rd = context.scene.render
- return (context.object) and rd.engine in cls.COMPAT_ENGINES
+ return (context.object) and context.engine in cls.COMPAT_ENGINES
def physics_add(self, layout, md, name, type, typeicon, toggles):
@@ -57,7 +56,7 @@ def physics_add_special(self, layout, data, name, addop, removeop, typeicon):
class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
obj = context.object
@@ -140,14 +139,16 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
layout.enabled = False
if not cache.use_external or cachetype == 'SMOKE':
- row = layout.row(align=True)
+ col = layout.column(align=True)
+ col.use_property_split = True
if cachetype not in {'PSYS', 'DYNAMIC_PAINT'}:
- row.enabled = enabled
- row.prop(cache, "frame_start")
- row.prop(cache, "frame_end")
+
+ col.enabled = enabled
+ col.prop(cache, "frame_start", text="Simulation Start")
+ col.prop(cache, "frame_end")
if cachetype not in {'SMOKE', 'CLOTH', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
- row.prop(cache, "frame_step")
+ col.prop(cache, "frame_step")
if cachetype != 'SMOKE':
layout.label(text=cache.info)
@@ -207,9 +208,12 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
def effector_weights_ui(self, context, weights, weight_type):
layout = self.layout
+ layout.use_property_split = True
layout.prop(weights, "group")
+ layout.use_property_split = False
+
split = layout.split()
split.prop(weights, "gravity", slider=True)
@@ -240,13 +244,12 @@ def effector_weights_ui(self, context, weights, weight_type):
def basic_force_field_settings_ui(self, context, field):
layout = self.layout
-
- split = layout.split()
+ layout.use_property_split = True
if not field or field.type == 'NONE':
return
- col = split.column()
+ col = layout.column()
if field.type == 'DRAG':
col.prop(field, "linear_drag", text="Linear")
@@ -266,10 +269,10 @@ def basic_force_field_settings_ui(self, context, field):
else:
col.prop(field, "flow")
- col = split.column()
+ col = layout.column()
sub = col.column(align=True)
sub.prop(field, "noise")
- sub.prop(field, "seed")
+ sub.prop(field, "seed", text="Noise Seed")
if field.type == 'TURBULENCE':
col.prop(field, "use_global_coords", text="Global")
elif field.type == 'HARMONIC':
@@ -277,46 +280,33 @@ def basic_force_field_settings_ui(self, context, field):
if field.type == 'FORCE':
col.prop(field, "use_gravity_falloff", text="Gravitation")
- split = layout.split()
-
- col = split.column()
- col.label(text="Effect point:")
- col.prop(field, "apply_to_location")
- col.prop(field, "apply_to_rotation")
-
- col = split.column()
- col.label(text="Collision:")
+ col.prop(field, "apply_to_location", text="Affect Location")
+ col.prop(field, "apply_to_rotation", text="Affect Rotation")
col.prop(field, "use_absorption")
def basic_force_field_falloff_ui(self, context, field):
layout = self.layout
- split = layout.split(percentage=0.35)
-
if not field or field.type == 'NONE':
return
- col = split.column()
- col.prop(field, "z_direction", text="")
+ col = layout.column()
+ col.prop(field, "z_direction")
- col = split.column()
col.prop(field, "falloff_power", text="Power")
split = layout.split()
- col = split.column()
- row = col.row(align=True)
- row.prop(field, "use_min_distance", text="")
- sub = row.row(align=True)
+ split.prop(field, "use_min_distance", text="Min Distance")
+ sub = split.column(align=True)
sub.active = field.use_min_distance
- sub.prop(field, "distance_min", text="Minimum")
+ sub.prop(field, "distance_min", text="")
- col = split.column()
- row = col.row(align=True)
- row.prop(field, "use_max_distance", text="")
- sub = row.row(align=True)
+ split = layout.split()
+ split.prop(field, "use_max_distance", text="Max Distance")
+ sub = split.column(align=True)
sub.active = field.use_max_distance
- sub.prop(field, "distance_max", text="Maximum")
+ sub.prop(field, "distance_max", text="")
classes = (
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index ef426253a69..6a66dafadf0 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -55,13 +55,12 @@ class PhysicButtonsPanel:
@classmethod
def poll(cls, context):
ob = context.object
- rd = context.scene.render
- return (ob and ob.type == 'MESH') and rd.engine in cls.COMPAT_ENGINES and context.dynamic_paint
+ return (ob and ob.type == 'MESH') and context.engine in cls.COMPAT_ENGINES and context.dynamic_paint
class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
bl_label = "Dynamic Paint"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -109,7 +108,6 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
elif md.ui_type == 'BRUSH':
brush = md.brush_settings
- use_shading_nodes = context.scene.render.use_shading_nodes
if brush is None:
layout.operator("dpaint.type_toggle", text="Add Brush").type = 'BRUSH'
@@ -124,27 +122,19 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
col.prop(brush, "paint_wetness", text="Wetness")
col = split.column()
- if not use_shading_nodes:
- sub = col.column()
- sub.active = (brush.paint_source != 'PARTICLE_SYSTEM')
- sub.prop(brush, "use_material")
- if brush.use_material and brush.paint_source != 'PARTICLE_SYSTEM' and not use_shading_nodes:
- col.prop(brush, "material", text="")
- col.prop(brush, "paint_alpha", text="Alpha Factor")
- else:
- col.prop(brush, "paint_color", text="")
- col.prop(brush, "paint_alpha", text="Alpha")
+ col.prop(brush, "paint_color", text="")
+ col.prop(brush, "paint_alpha", text="Alpha")
class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Advanced"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_label = "Advanced"
+ bl_parent_id = "PHYSICS_PT_dynamic_paint"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.dynamic_paint
- rd = context.scene.render
- return md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active and rd.engine in cls.COMPAT_ENGINES
+ return md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active and context.engine in cls.COMPAT_ENGINES
def draw(self, context):
layout = self.layout
@@ -213,20 +203,20 @@ class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Output"
+ bl_label = "Output"
+ bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.dynamic_paint
- rd = context.scene.render
if not (md and md.ui_type == 'CANVAS' and md.canvas_settings):
return 0
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
return (surface and
(not (surface.surface_format == 'VERTEX' and (surface.surface_type in {'DISPLACE', 'WAVE'}))) and
- (rd.engine in cls.COMPAT_ENGINES))
+ (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
layout = self.layout
@@ -276,7 +266,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
# image format outputs
if surface.surface_format == 'IMAGE':
layout.operator("dpaint.bake", text="Bake Image Sequence", icon='MOD_DYNAMICPAINT')
- layout.prop_search(surface, "uv_layer", ob.data, "uv_textures", text="UV Map")
+ layout.prop_search(surface, "uv_layer", ob.data, "uv_layers", text="UV Map")
layout.separator()
layout.prop(surface, "image_output_path", text="")
@@ -307,18 +297,18 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Initial Color"
+ bl_label = "Initial Color"
+ bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.dynamic_paint
- rd = context.scene.render
if not (md and md.ui_type == 'CANVAS' and md.canvas_settings):
return 0
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
- return (surface and surface.surface_type == 'PAINT') and (rd.engine in cls.COMPAT_ENGINES)
+ return (surface and surface.surface_type == 'PAINT') and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -337,25 +327,25 @@ class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
elif surface.init_color_type == 'TEXTURE':
layout.prop(surface, "init_texture")
- layout.prop_search(surface, "init_layername", ob.data, "uv_textures", text="UV Map")
+ layout.prop_search(surface, "init_layername", ob.data, "uv_layers", text="UV Map")
elif surface.init_color_type == 'VERTEX_COLOR':
layout.prop_search(surface, "init_layername", ob.data, "vertex_colors", text="Color Layer")
class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Effects"
+ bl_label = "Effects"
+ bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.dynamic_paint
- rd = context.scene.render
if not (md and md.ui_type == 'CANVAS' and md.canvas_settings):
return False
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
- return (surface and surface.surface_type == 'PAINT') and (rd.engine in cls.COMPAT_ENGINES)
+ return (surface and surface.surface_type == 'PAINT') and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -394,20 +384,20 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Cache"
+ bl_label = "Cache"
+ bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.dynamic_paint
- rd = context.scene.render
return (md and
md.ui_type == 'CANVAS' and
md.canvas_settings and
md.canvas_settings.canvas_surfaces.active and
md.canvas_settings.canvas_surfaces.active.is_cache_user and
- (rd.engine in cls.COMPAT_ENGINES))
+ (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
@@ -417,14 +407,14 @@ class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Source"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_label = "Source"
+ bl_parent_id = "PHYSICS_PT_dynamic_paint"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.dynamic_paint
- rd = context.scene.render
- return md and md.ui_type == 'BRUSH' and md.brush_settings and (rd.engine in cls.COMPAT_ENGINES)
+ return md and md.ui_type == 'BRUSH' and md.brush_settings and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -470,15 +460,15 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Velocity"
+ bl_label = "Velocity"
+ bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.dynamic_paint
- rd = context.scene.render
- return md and md.ui_type == 'BRUSH' and md.brush_settings and (rd.engine in cls.COMPAT_ENGINES)
+ return md and md.ui_type == 'BRUSH' and md.brush_settings and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -507,15 +497,15 @@ class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Waves"
+ bl_label = "Waves"
+ bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.dynamic_paint
- rd = context.scene.render
- return md and md.ui_type == 'BRUSH' and md.brush_settings and (rd.engine in cls.COMPAT_ENGINES)
+ return md and md.ui_type == 'BRUSH' and md.brush_settings and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py
index fb3d1631377..3b01015047f 100644
--- a/release/scripts/startup/bl_ui/properties_physics_field.py
+++ b/release/scripts/startup/bl_ui/properties_physics_field.py
@@ -33,60 +33,50 @@ class PhysicButtonsPanel:
@classmethod
def poll(cls, context):
- rd = context.scene.render
- return (context.object) and (rd.engine in cls.COMPAT_ENGINES)
+ return (context.object) and (context.engine in cls.COMPAT_ENGINES)
class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
bl_label = "Force Fields"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
ob = context.object
- rd = context.scene.render
- return (rd.engine in cls.COMPAT_ENGINES) and (ob.field) and (ob.field.type != 'NONE')
+ if not ob:
+ return False
+ return (context.engine in cls.COMPAT_ENGINES) and (ob.field) and (ob.field.type != 'NONE')
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
ob = context.object
field = ob.field
- split = layout.split(percentage=0.2)
- split.label(text="Type:")
-
- split.prop(field, "type", text="")
+ layout.prop(field, "type")
if field.type not in {'NONE', 'GUIDE', 'TEXTURE'}:
- split = layout.split(percentage=0.2)
- split.label(text="Shape:")
- split.prop(field, "shape", text="")
+ layout.prop(field, "shape", text="Shape")
elif field.type == 'TEXTURE':
- split = layout.split(percentage=0.2)
- split.label(text="Texture:")
- split.row().template_ID(field, "texture", new="texture.new")
-
- split = layout.split()
+ layout.row().template_ID(field, "texture", new="texture.new")
if field.type == 'NONE':
return # nothing to draw
elif field.type == 'GUIDE':
- col = split.column()
+ col = layout.column()
col.prop(field, "guide_minimum")
col.prop(field, "guide_free")
col.prop(field, "falloff_power")
col.prop(field, "use_guide_path_add")
col.prop(field, "use_guide_path_weight")
- col = split.column()
- col.label(text="Clumping:")
+ col.label(text="Clumping")
col.prop(field, "guide_clump_amount")
col.prop(field, "guide_clump_shape")
- row = layout.row()
- row.prop(field, "use_max_distance")
- sub = row.row()
+ col.prop(field, "use_max_distance")
+ sub = col.column()
sub.active = field.use_max_distance
sub.prop(field, "distance_max")
@@ -96,94 +86,96 @@ class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
if field.guide_kink_type != 'NONE':
layout.prop(field, "guide_kink_axis")
- split = layout.split()
-
- col = split.column()
+ col = layout.column()
col.prop(field, "guide_kink_frequency")
col.prop(field, "guide_kink_shape")
-
- col = split.column()
col.prop(field, "guide_kink_amplitude")
elif field.type == 'TEXTURE':
- col = split.column()
+ col = layout.column()
col.prop(field, "strength")
- col.prop(field, "texture_mode", text="")
+ col.prop(field, "texture_mode")
col.prop(field, "texture_nabla")
- col = split.column()
col.prop(field, "use_object_coords")
col.prop(field, "use_2d_force")
elif field.type == 'SMOKE_FLOW':
- col = split.column()
+ col = layout.column()
col.prop(field, "strength")
col.prop(field, "flow")
- col = split.column()
- col.label(text="Domain Object:")
- col.prop(field, "source_object", "")
+ col.prop(field, "source_object")
col.prop(field, "use_smoke_density")
else:
basic_force_field_settings_ui(self, context, field)
- if field.type not in {'NONE', 'GUIDE'}:
- layout.label(text="Falloff:")
- layout.row().prop(field, "falloff_type", expand=True)
+class PHYSICS_PT_field_falloff(PhysicButtonsPanel, Panel):
+ bl_label = "Falloff"
+ bl_parent_id = "PHYSICS_PT_field"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (context.engine in cls.COMPAT_ENGINES) and (ob.field) and (ob.field.type not in {'NONE', 'GUIDE'})
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+ field = ob.field
- basic_force_field_falloff_ui(self, context, field)
+ layout.prop(field, "falloff_type", text="Shape")
- if field.falloff_type == 'CONE':
- layout.separator()
+ basic_force_field_falloff_ui(self, context, field)
- split = layout.split(percentage=0.35)
+ if field.falloff_type == 'CONE':
+ layout.separator()
- col = split.column()
- col.label(text="Angular:")
- col.prop(field, "use_radial_min", text="Use Minimum")
- col.prop(field, "use_radial_max", text="Use Maximum")
+ col = layout.column()
+ col.prop(field, "radial_falloff", text="Power")
- col = split.column()
- col.prop(field, "radial_falloff", text="Power")
+ col.label(text="Angular")
- sub = col.column()
- sub.active = field.use_radial_min
- sub.prop(field, "radial_min", text="Angle")
+ col.prop(field, "use_radial_min", text="Use Min Angle")
+ sub = col.column()
+ sub.active = field.use_radial_min
+ sub.prop(field, "radial_min", text="Min Angle")
- sub = col.column()
- sub.active = field.use_radial_max
- sub.prop(field, "radial_max", text="Angle")
+ col.prop(field, "use_radial_max", text="Use Max Angle")
+ sub = col.column()
+ sub.active = field.use_radial_max
+ sub.prop(field, "radial_max", text="Max Angle")
- elif field.falloff_type == 'TUBE':
- layout.separator()
+ elif field.falloff_type == 'TUBE':
+ layout.separator()
- split = layout.split(percentage=0.35)
+ col = layout.column()
- col = split.column()
- col.label(text="Radial:")
- col.prop(field, "use_radial_min", text="Use Minimum")
- col.prop(field, "use_radial_max", text="Use Maximum")
+ col.prop(field, "radial_falloff", text="Power")
- col = split.column()
- col.prop(field, "radial_falloff", text="Power")
+ col.label(text="Radial")
- sub = col.column()
- sub.active = field.use_radial_min
- sub.prop(field, "radial_min", text="Distance")
+ col.prop(field, "use_radial_min", text="Use Minimum")
+ sub = col.column()
+ sub.active = field.use_radial_min
+ sub.prop(field, "radial_min", text="Distance")
- sub = col.column()
- sub.active = field.use_radial_max
- sub.prop(field, "radial_max", text="Distance")
+ col.prop(field, "use_radial_max", text="Use Maximum")
+ sub = col.column()
+ sub.active = field.use_radial_max
+ sub.prop(field, "radial_max", text="Distance")
class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
bl_label = "Collision"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
ob = context.object
- rd = context.scene.render
- return (ob and ob.type == 'MESH') and (rd.engine in cls.COMPAT_ENGINES) and (context.collision)
+ return (ob and ob.type == 'MESH') and (context.engine in cls.COMPAT_ENGINES) and (context.collision)
def draw(self, context):
layout = self.layout
@@ -191,6 +183,7 @@ class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
md = context.collision
split = layout.split()
+ layout.use_property_split = True
coll = md.settings
@@ -199,39 +192,90 @@ class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
layout.active = settings.use
- split = layout.split()
+ col = layout.column()
+ col.prop(settings, "absorption", text="Force Field Absorption")
+
+
+class PHYSICS_PT_collision_particle(PhysicButtonsPanel, Panel):
+ bl_label = "Particle"
+ bl_parent_id = "PHYSICS_PT_collision"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (ob and ob.type == 'MESH') and (context.engine in cls.COMPAT_ENGINES) and (context.collision)
+
+ def draw(self, context):
+ layout = self.layout
+
+ md = context.collision
- col = split.column()
- col.label(text="Particle:")
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ coll = md.settings
+
+ if coll:
+ settings = context.object.collision
+
+ layout.active = settings.use
+
+ col = flow.column()
col.prop(settings, "permeability", slider=True)
col.prop(settings, "stickiness")
+ col = flow.column()
col.prop(settings, "use_particle_kill")
- col.label(text="Particle Damping:")
- sub = col.column(align=True)
- sub.prop(settings, "damping_factor", text="Factor", slider=True)
- sub.prop(settings, "damping_random", text="Random", slider=True)
- col.label(text="Particle Friction:")
+ col = flow.column()
sub = col.column(align=True)
- sub.prop(settings, "friction_factor", text="Factor", slider=True)
- sub.prop(settings, "friction_random", text="Random", slider=True)
+ sub.prop(settings, "damping_factor", text="Damping", slider=True)
+ sub.prop(settings, "damping_random", text="Randomize", slider=True)
- col = split.column()
- col.label(text="Soft Body and Cloth:")
+ col = flow.column()
sub = col.column(align=True)
- sub.prop(settings, "thickness_outer", text="Outer", slider=True)
- sub.prop(settings, "thickness_inner", text="Inner", slider=True)
+ sub.prop(settings, "friction_factor", text="Friction", slider=True)
+ sub.prop(settings, "friction_random", text="Randomize", slider=True)
+
+
+class PHYSICS_PT_collision_softbody(PhysicButtonsPanel, Panel):
+ bl_label = "Softbody"
+ bl_parent_id = "PHYSICS_PT_collision"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (ob and ob.type == 'MESH') and (context.engine in cls.COMPAT_ENGINES) and (context.collision)
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ md = context.collision
+ coll = md.settings
+
+ if coll:
+ settings = context.object.collision
+
+ layout.active = settings.use
- col.label(text="Soft Body Damping:")
- col.prop(settings, "damping", text="Factor", slider=True)
+ col = flow.column()
+ col.prop(settings, "damping", text="Damping", slider=True)
- col.label(text="Force Fields:")
- col.prop(settings, "absorption", text="Absorption")
+ col = flow.column()
+ col.prop(settings, "thickness_outer", text="Thickness Outer", slider=True)
+ col.prop(settings, "thickness_inner", text="Inner", slider=True)
classes = (
PHYSICS_PT_field,
+ PHYSICS_PT_field_falloff,
PHYSICS_PT_collision,
+ PHYSICS_PT_collision_particle,
+ PHYSICS_PT_collision_softbody,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index ab92370f9ae..94611808059 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -20,13 +20,14 @@
import bpy
from bpy.types import Panel, Menu
from bpy.app.translations import pgettext_iface as iface_
+from bl_operators.presets import PresetMenu
-class FLUID_MT_presets(Menu):
+class FLUID_PT_presets(PresetMenu):
bl_label = "Fluid Presets"
preset_subdir = "fluid"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "fluid.preset_add"
class PhysicButtonsPanel:
@@ -37,13 +38,12 @@ class PhysicButtonsPanel:
@classmethod
def poll(cls, context):
ob = context.object
- rd = context.scene.render
- return (ob and ob.type == 'MESH') and rd.engine in cls.COMPAT_ENGINES and (context.fluid)
+ return (ob and ob.type == 'MESH') and context.engine in cls.COMPAT_ENGINES and (context.fluid)
class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
bl_label = "Fluid"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -204,15 +204,15 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
- bl_label = "Fluid World"
+ bl_label = "World"
+ bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.fluid
- rd = context.scene.render
- return md and md.settings and (md.settings.type == 'DOMAIN') and rd.engine in cls.COMPAT_ENGINES
+ return md and md.settings and (md.settings.type == 'DOMAIN') and context.engine in cls.COMPAT_ENGINES
def draw(self, context):
layout = self.layout
@@ -242,11 +242,7 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
col.prop(fluid, "simulation_scale", text="Meters")
col = split.column()
- col.label(text="Viscosity Presets:")
- sub = col.row(align=True)
- sub.menu("FLUID_MT_presets", text=bpy.types.FLUID_MT_presets.bl_label)
- sub.operator("fluid.preset_add", text="", icon='ZOOMIN')
- sub.operator("fluid.preset_add", text="", icon='ZOOMOUT').remove_active = True
+ FLUID_PT_presets.draw_menu(col, text="Viscosity Presets")
sub = col.column(align=True)
sub.prop(fluid, "viscosity_base", text="Base")
@@ -258,15 +254,15 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, Panel):
- bl_label = "Fluid Boundary"
+ bl_label = "Boundary"
+ bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.fluid
- rd = context.scene.render
- return md and md.settings and (md.settings.type == 'DOMAIN') and rd.engine in cls.COMPAT_ENGINES
+ return md and md.settings and (md.settings.type == 'DOMAIN') and context.engine in cls.COMPAT_ENGINES
def draw(self, context):
layout = self.layout
@@ -289,15 +285,15 @@ class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, Panel):
class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel):
- bl_label = "Fluid Particles"
+ bl_label = "Particles"
+ bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.fluid
- rd = context.scene.render
- return md and md.settings and (md.settings.type == 'DOMAIN') and rd.engine in cls.COMPAT_ENGINES
+ return md and md.settings and (md.settings.type == 'DOMAIN') and context.engine in cls.COMPAT_ENGINES
def draw(self, context):
layout = self.layout
@@ -310,7 +306,7 @@ class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel):
classes = (
- FLUID_MT_presets,
+ FLUID_PT_presets,
PHYSICS_PT_fluid,
PHYSICS_PT_domain_gravity,
PHYSICS_PT_domain_boundary,
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
index 847df2e1fd7..db59665e21d 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
@@ -29,13 +29,13 @@ class PHYSICS_PT_rigidbody_panel:
class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel):
bl_label = "Rigid Body"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
obj = context.object
return (obj and obj.rigid_body and
- (context.scene.render.engine in cls.COMPAT_ENGINES))
+ (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
layout = self.layout
@@ -55,14 +55,15 @@ class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel):
class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
- bl_label = "Rigid Body Collisions"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_label = "Collisions"
+ bl_parent_id = 'PHYSICS_PT_rigid_body'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
obj = context.object
return (obj and obj.rigid_body and
- (context.scene.render.engine in cls.COMPAT_ENGINES))
+ (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
layout = self.layout
@@ -99,16 +100,17 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
- bl_label = "Rigid Body Dynamics"
- bl_default_closed = True
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_label = "Dynamics"
+ bl_parent_id = 'PHYSICS_PT_rigid_body'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
obj = context.object
return (obj and obj.rigid_body and
obj.rigid_body.type == 'ACTIVE' and
- (context.scene.render.engine in cls.COMPAT_ENGINES))
+ (context.engine in cls.COMPAT_ENGINES))
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
index 84a4cbb4b68..aca989fd0ba 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
@@ -29,13 +29,12 @@ class PHYSICS_PT_rigidbody_constraint_panel:
class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Rigid Body Constraint"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
ob = context.object
- rd = context.scene.render
- return (ob and ob.rigid_body_constraint and rd.engine in cls.COMPAT_ENGINES)
+ return (ob and ob.rigid_body_constraint and context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index 9489fb71e15..acbaecbda4c 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -34,13 +34,12 @@ class PhysicButtonsPanel:
@classmethod
def poll(cls, context):
ob = context.object
- rd = context.scene.render
- return (ob and ob.type == 'MESH') and (rd.engine in cls.COMPAT_ENGINES) and (context.smoke)
+ return (ob and ob.type == 'MESH') and (context.engine in cls.COMPAT_ENGINES) and (context.smoke)
class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
bl_label = "Smoke"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -136,9 +135,10 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
- bl_label = "Smoke Flow Advanced"
+ bl_label = "Advanced"
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -160,7 +160,7 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
sub.label(text="Mapping:")
sub.prop(flow, "texture_map_type", expand=False, text="")
if flow.texture_map_type == 'UV':
- sub.prop_search(flow, "uv_layer", ob.data, "uv_textures", text="")
+ sub.prop_search(flow, "uv_layer", ob.data, "uv_layers", text="")
if flow.texture_map_type == 'AUTO':
sub.prop(flow, "texture_size")
sub.prop(flow, "texture_offset")
@@ -171,9 +171,10 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel):
- bl_label = "Smoke Flames"
+ bl_label = "Flames"
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -201,9 +202,10 @@ class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
- bl_label = "Smoke Adaptive Domain"
+ bl_label = "Adaptive Domain"
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -235,15 +237,15 @@ class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
- bl_label = "Smoke High Resolution"
+ bl_label = "High Resolution"
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.smoke
- rd = context.scene.render
- return md and (md.smoke_type == 'DOMAIN') and (rd.engine in cls.COMPAT_ENGINES)
+ return md and (md.smoke_type == 'DOMAIN') and (context.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
md = context.smoke.domain_settings
@@ -275,15 +277,15 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
- bl_label = "Smoke Groups"
+ bl_label = "Groups"
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.smoke
- rd = context.scene.render
- return md and (md.smoke_type == 'DOMAIN') and (rd.engine in cls.COMPAT_ENGINES)
+ return md and (md.smoke_type == 'DOMAIN') and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -304,15 +306,15 @@ class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
- bl_label = "Smoke Cache"
+ bl_label = "Cache"
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.smoke
- rd = context.scene.render
- return md and (md.smoke_type == 'DOMAIN') and (rd.engine in cls.COMPAT_ENGINES)
+ return md and (md.smoke_type == 'DOMAIN') and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -341,30 +343,30 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel):
- bl_label = "Smoke Field Weights"
+ bl_label = "Field Weights"
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
md = context.smoke
- rd = context.scene.render
- return md and (md.smoke_type == 'DOMAIN') and (rd.engine in cls.COMPAT_ENGINES)
+ return md and (md.smoke_type == 'DOMAIN') and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
domain = context.smoke.domain_settings
effector_weights_ui(self, context, domain.effector_weights, 'SMOKE')
-class PHYSICS_PT_smoke_display_settings(PhysicButtonsPanel, Panel):
- bl_label = "Smoke Display Settings"
+class PHYSICS_PT_smoke_viewport_display(PhysicButtonsPanel, Panel):
+ bl_label = "Viewport Display"
+ bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
md = context.smoke
- rd = context.scene.render
- return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine)
+ return md and (md.smoke_type == 'DOMAIN')
def draw(self, context):
domain = context.smoke.domain_settings
@@ -395,23 +397,53 @@ class PHYSICS_PT_smoke_display_settings(PhysicButtonsPanel, Panel):
row.enabled = do_full_slicing or not do_axis_slicing
row.prop(domain, "slice_per_voxel")
- layout.separator()
- layout.label(text="Debug:")
- layout.prop(domain, "draw_velocity")
- col = layout.column()
- col.enabled = domain.draw_velocity
- col.prop(domain, "vector_draw_type")
- col.prop(domain, "vector_scale")
- layout.separator()
- layout.label(text="Color Mapping:")
- layout.prop(domain, "use_color_ramp")
+class PHYSICS_PT_smoke_viewport_display_color(PhysicButtonsPanel, Panel):
+ bl_label = "Color Mapping"
+ bl_parent_id = 'PHYSICS_PT_smoke_viewport_display'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ md = context.smoke
+ return md and (md.smoke_type == 'DOMAIN')
+
+ def draw_header(self, context):
+ md = context.smoke.domain_settings
+
+ self.layout.prop(md, "use_color_ramp", text="")
+
+ def draw(self, context):
+ domain = context.smoke.domain_settings
+ layout = self.layout
+
col = layout.column()
col.enabled = domain.use_color_ramp
col.prop(domain, "coba_field")
col.template_color_ramp(domain, "color_ramp", expand=True)
+class PHYSICS_PT_smoke_viewport_display_debug(PhysicButtonsPanel, Panel):
+ bl_label = "Debug"
+ bl_parent_id = 'PHYSICS_PT_smoke_viewport_display'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ md = context.smoke
+ return md and (md.smoke_type == 'DOMAIN')
+
+ def draw(self, context):
+ domain = context.smoke.domain_settings
+ layout = self.layout
+
+ layout.prop(domain, "draw_velocity")
+ col = layout.column()
+ col.enabled = domain.draw_velocity
+ col.prop(domain, "vector_draw_type")
+ col.prop(domain, "vector_scale")
+
+
classes = (
PHYSICS_PT_smoke,
PHYSICS_PT_smoke_flow_advanced,
@@ -421,7 +453,9 @@ classes = (
PHYSICS_PT_smoke_groups,
PHYSICS_PT_smoke_cache,
PHYSICS_PT_smoke_field_weights,
- PHYSICS_PT_smoke_display_settings,
+ PHYSICS_PT_smoke_viewport_display,
+ PHYSICS_PT_smoke_viewport_display_color,
+ PHYSICS_PT_smoke_viewport_display_debug,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py
index 8f193427441..68db165875e 100644
--- a/release/scripts/startup/bl_ui/properties_physics_softbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py
@@ -41,13 +41,12 @@ class PhysicButtonsPanel:
@classmethod
def poll(cls, context):
ob = context.object
- rd = context.scene.render
- return ob and ob.type in COMPAT_OB_TYPES and rd.engine in cls.COMPAT_ENGINES and context.soft_body
+ return ob and ob.type in COMPAT_OB_TYPES and context.engine in cls.COMPAT_ENGINES and context.soft_body
class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
bl_label = "Soft Body"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -75,9 +74,10 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel):
- bl_label = "Soft Body Cache"
+ bl_label = "Cache"
+ bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
md = context.soft_body
@@ -85,9 +85,10 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel):
class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, Panel):
- bl_label = "Soft Body Goal"
+ bl_label = "Goal"
+ bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -125,9 +126,10 @@ class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, Panel):
class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, Panel):
- bl_label = "Soft Body Edges"
+ bl_label = "Edges"
+ bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -175,9 +177,10 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, Panel):
class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, Panel):
- bl_label = "Soft Body Self Collision"
+ bl_label = "Self Collision"
+ bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -204,9 +207,10 @@ class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, Panel):
class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, Panel):
- bl_label = "Soft Body Solver"
+ bl_label = "Solver"
+ bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -237,9 +241,10 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, Panel):
class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel):
- bl_label = "Soft Body Field Weights"
+ bl_label = "Field Weights"
+ bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
md = context.soft_body
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index bd5d926d4cd..a7cfee5ed8f 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -19,21 +19,21 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
+from bl_operators.presets import PresetMenu
-class RENDER_MT_presets(Menu):
+class RENDER_PT_presets(PresetMenu):
bl_label = "Render Presets"
preset_subdir = "render"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "render.preset_add"
-class RENDER_MT_ffmpeg_presets(Menu):
+class RENDER_PT_ffmpeg_presets(PresetMenu):
bl_label = "FFMPEG Presets"
preset_subdir = "ffmpeg"
preset_operator = "script.python_file_run"
- draw = Menu.draw_preset
class RENDER_MT_framerate_presets(Menu):
@@ -51,39 +51,42 @@ class RenderButtonsPanel:
@classmethod
def poll(cls, context):
- scene = context.scene
- return scene and (scene.render.engine in cls.COMPAT_ENGINES)
+ return (context.engine in cls.COMPAT_ENGINES)
-class RENDER_PT_render(RenderButtonsPanel, Panel):
- bl_label = "Render"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+class RENDER_PT_context(Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "render"
+ bl_options = {'HIDE_HEADER'}
+ bl_label = ""
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- rd = context.scene.render
-
- row = layout.row(align=True)
- row.operator("render.render", text="Render", icon='RENDER_STILL')
- row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True
- row.operator("sound.mixdown", text="Audio", icon='PLAY_AUDIO')
-
- split = layout.split(percentage=0.33)
+ scene = context.scene
+ rd = scene.render
- split.label(text="Display:")
- row = split.row(align=True)
- row.prop(rd, "display_mode", text="")
- row.prop(rd, "use_lock_interface", icon_only=True)
+ if rd.has_multiple_engines:
+ layout.prop(rd, "engine", text="Render Engine")
class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
bl_label = "Dimensions"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_frame_rate_args_prev = None
_preset_class = None
+ def draw_header_preset(self, context):
+ RENDER_PT_presets.draw_panel_header(self.layout)
+
@staticmethod
def _draw_framerate_label(*args):
# avoids re-creating text string each draw
@@ -127,237 +130,89 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
scene = context.scene
rd = scene.render
- row = layout.row(align=True)
- row.menu("RENDER_MT_presets", text=bpy.types.RENDER_MT_presets.bl_label)
- row.operator("render.preset_add", text="", icon='ZOOMIN')
- row.operator("render.preset_add", text="", icon='ZOOMOUT').remove_active = True
+ col = layout.column(align=True)
+ col.prop(rd, "resolution_x", text="Resolution X")
+ col.prop(rd, "resolution_y", text="Y")
+ col.prop(rd, "resolution_percentage", text="%")
- split = layout.split()
+ col = layout.column(align=True)
+ col.prop(rd, "pixel_aspect_x", text="Aspect X")
+ col.prop(rd, "pixel_aspect_y", text="Y")
- col = split.column()
+ col = layout.column(align=True)
+ col.prop(rd, "use_border", text="Border")
sub = col.column(align=True)
- sub.label(text="Resolution:")
- sub.prop(rd, "resolution_x", text="X")
- sub.prop(rd, "resolution_y", text="Y")
- sub.prop(rd, "resolution_percentage", text="")
-
- sub.label(text="Aspect Ratio:")
- sub.prop(rd, "pixel_aspect_x", text="X")
- sub.prop(rd, "pixel_aspect_y", text="Y")
-
- row = col.row()
- row.prop(rd, "use_border", text="Border")
- sub = row.row()
sub.active = rd.use_border
sub.prop(rd, "use_crop_to_border", text="Crop")
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Frame Range:")
- sub.prop(scene, "frame_start")
- sub.prop(scene, "frame_end")
- sub.prop(scene, "frame_step")
-
- sub.label(text="Frame Rate:")
-
- self.draw_framerate(sub, rd)
-
- subrow = sub.row(align=True)
- subrow.label(text="Time Remapping:")
- subrow = sub.row(align=True)
- subrow.prop(rd, "frame_map_old", text="Old")
- subrow.prop(rd, "frame_map_new", text="New")
-
-
-class RENDER_PT_antialiasing(RenderButtonsPanel, Panel):
- bl_label = "Anti-Aliasing"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw_header(self, context):
- rd = context.scene.render
-
- self.layout.prop(rd, "use_antialiasing", text="")
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render
- layout.active = rd.use_antialiasing
-
- split = layout.split()
-
- col = split.column()
- col.row().prop(rd, "antialiasing_samples", expand=True)
- sub = col.row()
- sub.prop(rd, "use_full_sample")
-
- col = split.column()
- col.prop(rd, "pixel_filter_type", text="")
- col.prop(rd, "filter_size", text="Size")
-
-
-class RENDER_PT_motion_blur(RenderButtonsPanel, Panel):
- bl_label = "Sampled Motion Blur"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return not rd.use_full_sample and (rd.engine in cls.COMPAT_ENGINES)
+ col = layout.column(align=True)
+ col.prop(scene, "frame_start", text="Frame Start")
+ col.prop(scene, "frame_end", text="End")
+ col.prop(scene, "frame_step", text="Step")
- def draw_header(self, context):
- rd = context.scene.render
+ col = layout.split(percentage=0.5)
+ col.alignment = 'RIGHT'
+ col.label(text="Frame Rate")
+ self.draw_framerate(col, rd)
- self.layout.prop(rd, "use_motion_blur", text="")
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render
- layout.active = rd.use_motion_blur
- row = layout.row()
- row.prop(rd, "motion_blur_samples")
- row.prop(rd, "motion_blur_shutter")
-
-
-class RENDER_PT_shading(RenderButtonsPanel, Panel):
- bl_label = "Shading"
+class RENDER_PT_frame_remapping(RenderButtonsPanel, Panel):
+ bl_label = "Time Remapping"
+ bl_parent_id = "RENDER_PT_dimensions"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
rd = context.scene.render
- split = layout.split()
-
- col = split.column()
- col.prop(rd, "use_textures", text="Textures")
- col.prop(rd, "use_shadows", text="Shadows")
- col.prop(rd, "use_sss", text="Subsurface Scattering")
- col.prop(rd, "use_envmaps", text="Environment Map")
-
- col = split.column()
- col.prop(rd, "use_raytrace", text="Ray Tracing")
- col.prop(rd, "alpha_mode", text="Alpha")
- col.prop(rd, "use_world_space_shading", text="World Space Shading")
-
-
-class RENDER_PT_performance(RenderButtonsPanel, Panel):
- bl_label = "Performance"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render
-
- split = layout.split()
-
- col = split.column(align=True)
- col.label(text="Threads:")
- col.row(align=True).prop(rd, "threads_mode", expand=True)
- sub = col.column(align=True)
- sub.enabled = rd.threads_mode == 'FIXED'
- sub.prop(rd, "threads")
-
- col.label(text="Tile Size:")
- col.prop(rd, "tile_x", text="X")
- col.prop(rd, "tile_y", text="Y")
-
- col.separator()
- col.prop(rd, "preview_start_resolution")
- col.prop(rd, "preview_pixel_size", text="")
-
- col = split.column()
- col.label(text="Memory:")
- sub = col.column()
- sub.enabled = not rd.use_full_sample
- sub.prop(rd, "use_save_buffers")
- sub = col.column()
- sub.active = rd.use_compositing
- sub.prop(rd, "use_free_image_textures")
- sub = col.column()
- sub.active = rd.use_raytrace
- sub.label(text="Acceleration Structure:")
- sub.prop(rd, "raytrace_method", text="")
- if rd.raytrace_method == 'OCTREE':
- sub.prop(rd, "octree_resolution", text="Resolution")
- else:
- sub.prop(rd, "use_instances", text="Instances")
- sub.prop(rd, "use_local_coords", text="Local Coordinates")
+ col = layout.column(align=True)
+ col.prop(rd, "frame_map_old", text="Old")
+ col.prop(rd, "frame_map_new", text="New")
class RENDER_PT_post_processing(RenderButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
rd = context.scene.render
- split = layout.split()
-
- col = split.column()
+ col = layout.column(align=True)
col.prop(rd, "use_compositing")
col.prop(rd, "use_sequencer")
- split.prop(rd, "dither_intensity", text="Dither", slider=True)
-
- layout.separator()
-
- split = layout.split()
-
- col = split.column()
- col.prop(rd, "use_fields", text="Fields")
- sub = col.column()
- sub.active = rd.use_fields
- sub.row().prop(rd, "field_order", expand=True)
- sub.prop(rd, "use_fields_still", text="Still")
-
- col = split.column()
- col.prop(rd, "use_edge_enhance")
- sub = col.column()
- sub.active = rd.use_edge_enhance
- sub.prop(rd, "edge_threshold", text="Threshold", slider=True)
- sub.prop(rd, "edge_color", text="")
+ col.prop(rd, "dither_intensity", text="Dither", slider=True)
class RENDER_PT_stamp(RenderButtonsPanel, Panel):
bl_label = "Metadata"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
rd = context.scene.render
- layout.prop(rd, "use_stamp")
- col = layout.column()
- col.active = rd.use_stamp
- row = col.row()
- row.prop(rd, "stamp_font_size", text="Font Size")
- row.prop(rd, "use_stamp_labels", text="Draw Labels")
-
- row = col.row()
- row.column().prop(rd, "stamp_foreground", slider=True)
- row.column().prop(rd, "stamp_background", slider=True)
-
- layout.label("Enabled Metadata")
split = layout.split()
- col = split.column()
+ col = split.column(align=True)
col.prop(rd, "use_stamp_time", text="Time")
col.prop(rd, "use_stamp_date", text="Date")
col.prop(rd, "use_stamp_render_time", text="RenderTime")
@@ -365,7 +220,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
col.prop(rd, "use_stamp_scene", text="Scene")
col.prop(rd, "use_stamp_memory", text="Memory")
- col = split.column()
+ col = split.column(align=True)
col.prop(rd, "use_stamp_camera", text="Camera")
col.prop(rd, "use_stamp_lens", text="Lens")
col.prop(rd, "use_stamp_filename", text="Filename")
@@ -373,22 +228,50 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
col.prop(rd, "use_stamp_marker", text="Marker")
col.prop(rd, "use_stamp_sequencer_strip", text="Seq. Strip")
- row = layout.split(percentage=0.2)
+ if rd.use_sequencer:
+ col.prop(rd, "use_stamp_strip_meta", text="Sequence Strip")
+
+ row = layout.split(percentage=0.3)
row.prop(rd, "use_stamp_note", text="Note")
sub = row.row()
sub.active = rd.use_stamp_note
sub.prop(rd, "stamp_note_text", text="")
- if rd.use_sequencer:
- layout.label("Sequencer:")
- layout.prop(rd, "use_stamp_strip_meta")
+
+
+class RENDER_PT_stamp_burn(RenderButtonsPanel, Panel):
+ bl_label = "Burn Into Image"
+ bl_parent_id = "RENDER_PT_stamp"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+
+ self.layout.prop(rd, "use_stamp", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+
+ layout.use_property_split = True
+
+ col = layout.column()
+ col.active = rd.use_stamp
+ col.prop(rd, "stamp_font_size", text="Font Size")
+ col.prop(rd, "use_stamp_labels", text="Draw Labels")
+ col.column().prop(rd, "stamp_foreground", slider=True)
+ col.column().prop(rd, "stamp_background", slider=True)
class RENDER_PT_output(RenderButtonsPanel, Panel):
bl_label = "Output"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = False
+ layout.use_property_decorate = False # No animation.
rd = context.scene.render
image_settings = rd.image_settings
@@ -396,17 +279,17 @@ class RENDER_PT_output(RenderButtonsPanel, Panel):
layout.prop(rd, "filepath", text="")
- split = layout.split()
+ layout.use_property_split = True
- col = split.column()
- col.active = not rd.is_movie_format
- col.prop(rd, "use_overwrite")
- col.prop(rd, "use_placeholder")
-
- col = split.column()
+ col = layout.column(align=True)
+ sub = col.column(align=True)
+ sub.active = not rd.is_movie_format
+ sub.prop(rd, "use_overwrite")
+ sub.prop(rd, "use_placeholder")
col.prop(rd, "use_file_extension")
col.prop(rd, "use_render_cache")
+ layout.use_property_split = False
layout.template_image_settings(image_settings, color_management=False)
if rd.use_multiview:
layout.template_image_views(image_settings)
@@ -415,7 +298,10 @@ class RENDER_PT_output(RenderButtonsPanel, Panel):
class RENDER_PT_encoding(RenderButtonsPanel, Panel):
bl_label = "Encoding"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw_header_preset(self, context):
+ RENDER_PT_ffmpeg_presets.draw_panel_header(self.layout)
@classmethod
def poll(cls, context):
@@ -428,8 +314,6 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
rd = context.scene.render
ffmpeg = rd.ffmpeg
- layout.menu("RENDER_MT_ffmpeg_presets", text="Presets")
-
split = layout.split()
split.prop(rd.ffmpeg, "format")
split.prop(ffmpeg, "use_autosplit")
@@ -494,92 +378,452 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
col.prop(ffmpeg, "packetsize", text="Packet Size")
-class RENDER_PT_bake(RenderButtonsPanel, Panel):
- bl_label = "Bake"
+class RENDER_UL_renderviews(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ view = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if view.name in {"left", "right"}:
+ layout.label(view.name, icon_value=icon + (not view.use))
+ else:
+ layout.prop(view, "name", text="", index=index, icon_value=icon, emboss=False)
+ layout.prop(view, "use", text="", index=index)
+
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon + (not view.use))
+
+
+class RENDER_PT_stereoscopy(RenderButtonsPanel, Panel):
+ bl_label = "Stereoscopy"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+ self.layout.prop(rd, "use_multiview", text="")
def draw(self, context):
layout = self.layout
- rd = context.scene.render
+ scene = context.scene
+ rd = scene.render
+ rv = rd.views.active
- layout.operator("object.bake_image", icon='RENDER_STILL')
+ layout.active = rd.use_multiview
+ basic_stereo = rd.views_format == 'STEREO_3D'
- layout.prop(rd, "bake_type")
+ row = layout.row()
+ row.prop(rd, "views_format", expand=True)
- multires_bake = False
- if rd.bake_type in ['NORMALS', 'DISPLACEMENT', 'DERIVATIVE', 'AO']:
- layout.prop(rd, "use_bake_multires")
- multires_bake = rd.use_bake_multires
+ if basic_stereo:
+ row = layout.row()
+ row.template_list("RENDER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
- if not multires_bake:
- if rd.bake_type == 'NORMALS':
- layout.prop(rd, "bake_normal_space")
- elif rd.bake_type in {'DISPLACEMENT', 'AO'}:
- layout.prop(rd, "use_bake_normalize")
+ row = layout.row()
+ row.label(text="File Suffix:")
+ row.prop(rv, "file_suffix", text="")
- # col.prop(rd, "bake_aa_mode")
- # col.prop(rd, "use_bake_antialiasing")
+ else:
+ row = layout.row()
+ row.template_list("RENDER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
- layout.separator()
+ col = row.column(align=True)
+ col.operator("scene.render_view_add", icon='ZOOMIN', text="")
+ col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
- split = layout.split()
+ row = layout.row()
+ row.label(text="Camera Suffix:")
+ row.prop(rv, "camera_suffix", text="")
- col = split.column()
- col.prop(rd, "use_bake_to_vertex_color")
- sub = col.column()
- sub.active = not rd.use_bake_to_vertex_color
- sub.prop(rd, "use_bake_clear")
- sub.prop(rd, "bake_margin")
- sub.prop(rd, "bake_quad_split", text="Split")
- col = split.column()
- col.prop(rd, "use_bake_selected_to_active")
- sub = col.column()
- sub.active = rd.use_bake_selected_to_active
- sub.prop(rd, "bake_distance")
- sub.prop(rd, "bake_bias")
+class RENDER_PT_eevee_ambient_occlusion(RenderButtonsPanel, Panel):
+ bl_label = "Ambient Occlusion"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ scene = context.scene
+ props = scene.eevee
+ self.layout.prop(props, "use_gtao", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ scene = context.scene
+ props = scene.eevee
+
+ layout.active = props.use_gtao
+ col = layout.column()
+ col.prop(props, "use_gtao_bent_normals")
+ col.prop(props, "use_gtao_bounce")
+ col.prop(props, "gtao_distance")
+ col.prop(props, "gtao_factor")
+ col.prop(props, "gtao_quality")
+
+
+class RENDER_PT_eevee_motion_blur(RenderButtonsPanel, Panel):
+ bl_label = "Motion Blur"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ scene = context.scene
+ props = scene.eevee
+ self.layout.prop(props, "use_motion_blur", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ scene = context.scene
+ props = scene.eevee
+
+ layout.active = props.use_motion_blur
+ col = layout.column()
+ col.prop(props, "motion_blur_samples")
+ col.prop(props, "motion_blur_shutter")
+
+
+class RENDER_PT_eevee_depth_of_field(RenderButtonsPanel, Panel):
+ bl_label = "Depth of Field"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ scene = context.scene
+ props = scene.eevee
+ self.layout.prop(props, "use_dof", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ scene = context.scene
+ props = scene.eevee
+
+ layout.active = props.use_dof
+ col = layout.column()
+ col.prop(props, "bokeh_max_size")
+ col.prop(props, "bokeh_threshold")
+
+
+class RENDER_PT_eevee_bloom(RenderButtonsPanel, Panel):
+ bl_label = "Bloom"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ scene = context.scene
+ props = scene.eevee
+ self.layout.prop(props, "use_bloom", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ props = scene.eevee
+
+ layout.active = props.use_bloom
+ col = layout.column()
+ col.prop(props, "bloom_threshold")
+ col.prop(props, "bloom_knee")
+ col.prop(props, "bloom_radius")
+ col.prop(props, "bloom_color")
+ col.prop(props, "bloom_intensity")
+ col.prop(props, "bloom_clamp")
+
+
+class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel):
+ bl_label = "Volumetric"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ scene = context.scene
+ props = scene.eevee
+ self.layout.prop(props, "use_volumetric", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ props = scene.eevee
+
+ layout.active = props.use_volumetric
+ col = layout.column()
+ sub = col.column(align=True)
+ sub.prop(props, "volumetric_start")
+ sub.prop(props, "volumetric_end")
+ col.prop(props, "volumetric_tile_size")
+ col.separator()
+ col.prop(props, "volumetric_samples")
+ sub.prop(props, "volumetric_sample_distribution")
+ col.separator()
+ col.prop(props, "use_volumetric_lights")
+
+ sub = col.column()
+ sub.active = props.use_volumetric_lights
+ sub.prop(props, "volumetric_light_clamp", text="Light Clamping")
+ col.separator()
+ col.prop(props, "use_volumetric_shadows")
+ sub = col.column()
+ sub.active = props.use_volumetric_shadows
+ sub.prop(props, "volumetric_shadow_samples", text="Shadow Samples")
+ col.separator()
+ col.prop(props, "use_volumetric_colored_transmittance")
+
+
+class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel):
+ bl_label = "Subsurface Scattering"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ scene = context.scene
+ props = scene.eevee
+ self.layout.prop(props, "use_sss", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ props = scene.eevee
+
+ layout.active = props.use_sss
+
+ col = layout.column()
+ col.prop(props, "sss_samples")
+ col.prop(props, "sss_jitter_threshold")
+ col.prop(props, "use_sss_separate_albedo")
+
+
+class RENDER_PT_eevee_screen_space_reflections(RenderButtonsPanel, Panel):
+ bl_label = "Screen Space Reflections"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ scene = context.scene
+ props = scene.eevee
+ self.layout.prop(props, "use_ssr", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ props = scene.eevee
+
+ col = layout.column()
+ col.active = props.use_ssr
+ col.prop(props, "use_ssr_refraction", text="Refraction")
+ col.prop(props, "use_ssr_halfres")
+ col.prop(props, "ssr_quality")
+ col.prop(props, "ssr_max_roughness")
+ col.prop(props, "ssr_thickness")
+ col.prop(props, "ssr_border_fade")
+ col.prop(props, "ssr_firefly_fac")
+
+
+class RENDER_PT_eevee_shadows(RenderButtonsPanel, Panel):
+ bl_label = "Shadows"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ props = scene.eevee
+
+ col = layout.column()
+ col.prop(props, "shadow_method")
+ col.prop(props, "shadow_cube_size", text="Cube Size")
+ col.prop(props, "shadow_cascade_size", text="Cascade Size")
+ col.prop(props, "use_shadow_high_bitdepth")
+
+
+class RENDER_PT_eevee_sampling(RenderButtonsPanel, Panel):
+ bl_label = "Sampling"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ scene = context.scene
+ props = scene.eevee
+
+ col = layout.column()
+ col.prop(props, "taa_samples")
+ col.prop(props, "taa_render_samples")
+ col.prop(props, "use_taa_reprojection")
+
+
+class RENDER_PT_eevee_indirect_lighting(RenderButtonsPanel, Panel):
+ bl_label = "Indirect Lighting"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ scene = context.scene
+ props = scene.eevee
+
+ col = layout.column()
+ col.operator("scene.light_cache_bake", text="Bake Indirect Lighting", icon='RENDER_STILL')
+ col.operator("scene.light_cache_bake", text="Bake Cubemap Only", icon='LIGHTPROBE_CUBEMAP').subset = "CUBEMAPS"
+ col.operator("scene.light_cache_free", text="Free Lighting Cache")
+
+ cache_info = scene.eevee.gi_cache_info
+ if cache_info:
+ col.label(text=cache_info)
+
+ col.prop(props, "gi_auto_bake")
+
+ col.prop(props, "gi_diffuse_bounces")
+ col.prop(props, "gi_cubemap_resolution")
+ col.prop(props, "gi_visibility_resolution", text="Diffuse Occlusion")
+
+ layout.use_property_split = False
+ row = layout.split(percentage=0.5)
+ row.alignment = 'RIGHT'
+ row.label("Cubemap Display")
+
+ sub = row.row(align=True)
+ sub.prop(props, "gi_cubemap_draw_size", text="Size")
+ if props.gi_show_cubemaps:
+ sub.prop(props, "gi_show_cubemaps", text="", toggle=True, icon='HIDE_OFF')
else:
- split = layout.split()
+ sub.prop(props, "gi_show_cubemaps", text="", toggle=True, icon='HIDE_ON')
- col = split.column()
- col.prop(rd, "use_bake_clear")
- col.prop(rd, "bake_margin")
+ row = layout.split(percentage=0.5)
+ row.alignment = 'RIGHT'
+ row.label("Irradiance Display")
- if rd.bake_type == 'DISPLACEMENT':
- col = split.column()
- col.prop(rd, "use_bake_lores_mesh")
+ sub = row.row(align=True)
+ sub.prop(props, "gi_irradiance_draw_size", text="Size")
+ if props.gi_show_irradiance:
+ sub.prop(props, "gi_show_irradiance", text="", toggle=True, icon='HIDE_OFF')
+ else:
+ sub.prop(props, "gi_show_irradiance", text="", toggle=True, icon='HIDE_ON')
- if rd.bake_type == 'AO':
- col = split.column()
- col.prop(rd, "bake_bias")
- col.prop(rd, "bake_samples")
- if rd.bake_type == 'DERIVATIVE':
- row = layout.row()
- row.prop(rd, "use_bake_user_scale", text="")
+class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
+ bl_label = "Film"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
- sub = row.column()
- sub.active = rd.use_bake_user_scale
- sub.prop(rd, "bake_user_scale", text="User Scale")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ rd = scene.render
+
+ col = layout.column()
+ col.prop(rd, "filter_size")
+ col.prop(rd, "alpha_mode", text="Alpha")
+
+
+class RENDER_PT_hair(RenderButtonsPanel, Panel):
+ bl_label = "Hair"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ scene = context.scene
+ rd = scene.render
+
+ row = layout.row()
+ row.prop(rd, "hair_type", expand=True)
+
+ layout.use_property_split = True
+ layout.prop(rd, "hair_subdiv")
classes = (
- RENDER_MT_presets,
- RENDER_MT_ffmpeg_presets,
+ RENDER_PT_presets,
+ RENDER_PT_ffmpeg_presets,
RENDER_MT_framerate_presets,
- RENDER_PT_render,
+ RENDER_PT_context,
RENDER_PT_dimensions,
- RENDER_PT_antialiasing,
- RENDER_PT_motion_blur,
- RENDER_PT_shading,
- RENDER_PT_performance,
+ RENDER_PT_frame_remapping,
RENDER_PT_post_processing,
- RENDER_PT_stamp,
RENDER_PT_output,
RENDER_PT_encoding,
- RENDER_PT_bake,
+ RENDER_PT_stamp,
+ RENDER_PT_stamp_burn,
+ RENDER_UL_renderviews,
+ RENDER_PT_stereoscopy,
+ RENDER_PT_hair,
+ RENDER_PT_eevee_sampling,
+ RENDER_PT_eevee_film,
+ RENDER_PT_eevee_shadows,
+ RENDER_PT_eevee_indirect_lighting,
+ RENDER_PT_eevee_subsurface_scattering,
+ RENDER_PT_eevee_screen_space_reflections,
+ RENDER_PT_eevee_ambient_occlusion,
+ RENDER_PT_eevee_volumetric,
+ RENDER_PT_eevee_motion_blur,
+ RENDER_PT_eevee_depth_of_field,
+ RENDER_PT_eevee_bloom,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py
deleted file mode 100644
index 084bc387822..00000000000
--- a/release/scripts/startup/bl_ui/properties_render_layer.py
+++ /dev/null
@@ -1,242 +0,0 @@
-# ##### 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.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-import bpy
-from bpy.types import Panel, UIList
-
-
-class RenderLayerButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "render_layer"
- # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return scene and (scene.render.engine in cls.COMPAT_ENGINES)
-
-
-class RENDERLAYER_UL_renderlayers(UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.SceneRenderLayer)
- layer = item
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.prop(layer, "name", text="", icon_value=icon, emboss=False)
- layout.prop(layer, "use", text="", index=index)
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label("", icon_value=icon)
-
-
-class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
- bl_label = "Layer List"
- bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
-
- if rd.engine == 'BLENDER_GAME':
- layout.label("Not available in the Game Engine")
- return
-
- row = layout.row()
- col = row.column()
- col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
-
- col = row.column()
- sub = col.column(align=True)
- sub.operator("scene.render_layer_add", icon='ZOOMIN', text="")
- sub.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
- col.prop(rd, "use_single_layer", icon_only=True)
-
-
-class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel):
- bl_label = "Layer"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
- rl = rd.layers.active
-
- split = layout.split()
-
- col = split.column()
- col.prop(scene, "layers", text="Scene")
- col.label(text="")
- col.prop(rl, "light_override", text="Lights")
- col.prop(rl, "material_override", text="Material")
-
- col = split.column()
- col.prop(rl, "layers", text="Layer")
- col.prop(rl, "layers_zmask", text="Mask Layer")
-
- layout.separator()
- layout.label(text="Include:")
-
- split = layout.split()
-
- col = split.column()
- col.prop(rl, "use_zmask")
- row = col.row()
- row.prop(rl, "invert_zmask", text="Negate")
- row.active = rl.use_zmask
- col.prop(rl, "use_all_z")
-
- col = split.column()
- col.prop(rl, "use_solid")
- col.prop(rl, "use_halo")
- col.prop(rl, "use_ztransp")
-
- col = split.column()
- col.prop(rl, "use_sky")
- col.prop(rl, "use_edge_enhance")
- col.prop(rl, "use_strand")
- if bpy.app.build_options.freestyle:
- row = col.row()
- row.prop(rl, "use_freestyle")
- row.active = rd.use_freestyle
-
-
-class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel):
- bl_label = "Passes"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @staticmethod
- def draw_pass_type_buttons(box, rl, pass_type):
- # property names
- use_pass_type = "use_pass_" + pass_type
- exclude_pass_type = "exclude_" + pass_type
- # draw pass type buttons
- row = box.row()
- row.prop(rl, use_pass_type)
- row.prop(rl, exclude_pass_type, text="")
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
- rl = rd.layers.active
-
- split = layout.split()
-
- col = split.column()
- col.prop(rl, "use_pass_combined")
- col.prop(rl, "use_pass_z")
- col.prop(rl, "use_pass_vector")
- col.prop(rl, "use_pass_normal")
- col.prop(rl, "use_pass_uv")
- col.prop(rl, "use_pass_mist")
- col.prop(rl, "use_pass_object_index")
- col.prop(rl, "use_pass_material_index")
- col.prop(rl, "use_pass_color")
-
- col = split.column()
- col.prop(rl, "use_pass_diffuse")
- self.draw_pass_type_buttons(col, rl, "specular")
- self.draw_pass_type_buttons(col, rl, "shadow")
- self.draw_pass_type_buttons(col, rl, "emit")
- self.draw_pass_type_buttons(col, rl, "ambient_occlusion")
- self.draw_pass_type_buttons(col, rl, "environment")
- self.draw_pass_type_buttons(col, rl, "indirect")
- self.draw_pass_type_buttons(col, rl, "reflection")
- self.draw_pass_type_buttons(col, rl, "refraction")
-
-
-class RENDERLAYER_UL_renderviews(UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.SceneRenderView)
- view = item
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- if view.name in {'left', 'right'}:
- layout.label(view.name, icon_value=icon + (not view.use))
- else:
- layout.prop(view, "name", text="", index=index, icon_value=icon, emboss=False)
- layout.prop(view, "use", text="", index=index)
-
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label("", icon_value=icon + (not view.use))
-
-
-class RENDERLAYER_PT_views(RenderLayerButtonsPanel, Panel):
- bl_label = "Views"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw_header(self, context):
- rd = context.scene.render
- self.layout.prop(rd, "use_multiview", text="")
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
- rv = rd.views.active
-
- layout.active = rd.use_multiview
- basic_stereo = rd.views_format == 'STEREO_3D'
-
- row = layout.row()
- row.prop(rd, "views_format", expand=True)
-
- if basic_stereo:
- row = layout.row()
- row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
-
- row = layout.row()
- row.label(text="File Suffix:")
- row.prop(rv, "file_suffix", text="")
-
- else:
- row = layout.row()
- row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
-
- col = row.column(align=True)
- col.operator("scene.render_view_add", icon='ZOOMIN', text="")
- col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
-
- row = layout.row()
- row.label(text="Camera Suffix:")
- row.prop(rv, "camera_suffix", text="")
-
-
-classes = (
- RENDERLAYER_UL_renderlayers,
- RENDERLAYER_PT_layers,
- RENDERLAYER_PT_layer_options,
- RENDERLAYER_PT_layer_passes,
- RENDERLAYER_UL_renderviews,
- RENDERLAYER_PT_views,
-)
-
-if __name__ == "__main__": # only for live edit.
- from bpy.utils import register_class
- for cls in classes:
- register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 9b1f98ec1a4..d0fce0a2582 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -25,6 +25,7 @@ from bpy.types import (
)
from rna_prop_ui import PropertyPanel
+from bl_operators.presets import PresetMenu
from .properties_physics_common import (
point_cache_ui,
@@ -32,12 +33,12 @@ from .properties_physics_common import (
)
-class SCENE_MT_units_length_presets(Menu):
+class SCENE_PT_units_length_presets(PresetMenu):
"""Unit of measure for properties that use length values"""
bl_label = "Unit Presets"
preset_subdir = "units_length"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "scene.units_length_preset_add"
class SCENE_UL_keying_set_paths(UIList):
@@ -60,56 +61,47 @@ class SceneButtonsPanel:
@classmethod
def poll(cls, context):
- rd = context.scene.render
- return context.scene and (rd.engine in cls.COMPAT_ENGINES)
+ return (context.engine in cls.COMPAT_ENGINES)
class SCENE_PT_scene(SceneButtonsPanel, Panel):
bl_label = "Scene"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
-
+ layout.use_property_split = True
scene = context.scene
layout.prop(scene, "camera")
- layout.prop(scene, "background_set", text="Background")
- if context.scene.render.engine != 'BLENDER_GAME':
- layout.prop(scene, "active_clip", text="Active Clip")
+ layout.prop(scene, "background_set")
+ layout.prop(scene, "active_clip")
class SCENE_PT_unit(SceneButtonsPanel, Panel):
bl_label = "Units"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw_header_preset(self, context):
+ SCENE_PT_units_length_presets.draw_panel_header(self.layout)
def draw(self, context):
layout = self.layout
unit = context.scene.unit_settings
- row = layout.row(align=True)
- row.menu("SCENE_MT_units_length_presets", text=SCENE_MT_units_length_presets.bl_label)
- row.operator("scene.units_length_preset_add", text="", icon='ZOOMIN')
- row.operator("scene.units_length_preset_add", text="", icon='ZOOMOUT').remove_active = True
+ layout.use_property_split = True
- layout.separator()
+ col = layout.column()
+ col.prop(unit, "system")
- split = layout.split(percentage=0.35)
- split.label("Length:")
- split.prop(unit, "system", text="")
- split = layout.split(percentage=0.35)
- split.label("Angle:")
- split.prop(unit, "system_rotation", text="")
+ col = layout.column()
+ col.prop(unit, "system_rotation")
col = layout.column()
col.enabled = unit.system != 'NONE'
- split = col.split(percentage=0.35)
- split.label("Unit Scale:")
- split.prop(unit, "scale_length", text="")
- split = col.split(percentage=0.35)
- split.row()
- split.prop(unit, "use_separate")
+ col.prop(unit, "scale_length")
+ col.prop(unit, "use_separate")
class SceneKeyingSetsPanel:
@@ -167,7 +159,8 @@ class SceneKeyingSetsPanel:
class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
bl_label = "Keying Sets"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -200,7 +193,8 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
bl_label = "Active Keying Set"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ bl_parent_id = "SCENE_PT_keying_sets"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -257,84 +251,115 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
class SCENE_PT_color_management(SceneButtonsPanel, Panel):
bl_label = "Color Management"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
scene = context.scene
+ view = scene.view_settings
col = layout.column()
- col.label(text="Display:")
col.prop(scene.display_settings, "display_device")
- col = layout.column()
col.separator()
- col.label(text="Render:")
- col.template_colormanaged_view_settings(scene, "view_settings")
col = layout.column()
+ col.prop(view, "view_transform")
+ col.prop(view, "exposure")
+ col.prop(view, "gamma")
+ col.prop(view, "look")
+
col.separator()
- col.label(text="Sequencer:")
- col.prop(scene.sequencer_colorspace_settings, "name")
+
+ col.prop(scene.sequencer_colorspace_settings, "name", text="Sequencer")
+
+
+class SCENE_PT_color_management_curves(SceneButtonsPanel, Panel):
+ bl_label = "Use Curves"
+ bl_parent_id = "SCENE_PT_color_management"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw_header(self, context):
+
+ scene = context.scene
+ view = scene.view_settings
+
+ self.layout.prop(view, "use_curve_mapping", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ view = scene.view_settings
+
+ layout.use_property_split = False
+ layout.enabled = view.use_curve_mapping
+
+ layout.template_curve_mapping(view, "curve_mapping", levels=True)
class SCENE_PT_audio(SceneButtonsPanel, Panel):
bl_label = "Audio"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
scene = context.scene
rd = context.scene.render
ffmpeg = rd.ffmpeg
layout.prop(scene, "audio_volume")
- layout.operator("sound.bake_animation")
- split = layout.split()
+ col = layout.column()
+ col.prop(scene, "audio_distance_model")
+
+ col.prop(ffmpeg, "audio_channels")
+ col.prop(ffmpeg, "audio_mixrate", text="Sample Rate")
- col = split.column()
- col.label("Distance Model:")
- col.prop(scene, "audio_distance_model", text="")
- sub = col.column(align=True)
- sub.prop(scene, "audio_doppler_speed", text="Speed")
- sub.prop(scene, "audio_doppler_factor", text="Doppler")
+ layout.separator()
+
+ col = layout.column(align=True)
+ col.prop(scene, "audio_doppler_speed", text="Doppler Speed")
+ col.prop(scene, "audio_doppler_factor", text="Doppler Factor")
+
+ layout.separator()
- col = split.column()
- col.label("Format:")
- col.prop(ffmpeg, "audio_channels", text="")
- col.prop(ffmpeg, "audio_mixrate", text="Rate")
+ layout.operator("sound.bake_animation")
class SCENE_PT_physics(SceneButtonsPanel, Panel):
bl_label = "Gravity"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
self.layout.prop(context.scene, "use_gravity", text="")
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
scene = context.scene
layout.active = scene.use_gravity
- layout.prop(scene, "gravity", text="")
+ layout.prop(scene, "gravity")
class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
bl_label = "Rigid Body World"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- scene = context.scene
- rd = scene.render
- return scene and (rd.engine in cls.COMPAT_ENGINES)
+ return (context.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
scene = context.scene
@@ -344,6 +369,7 @@ class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
scene = context.scene
@@ -361,27 +387,25 @@ class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
col.prop(rbw, "group")
col.prop(rbw, "constraints")
- split = col.split()
-
- col = split.column()
+ col = col.column()
col.prop(rbw, "time_scale", text="Speed")
col.prop(rbw, "use_split_impulse")
- col = split.column()
+ col = col.column()
col.prop(rbw, "steps_per_second", text="Steps Per Second")
col.prop(rbw, "solver_iterations", text="Solver Iterations")
class SCENE_PT_rigid_body_cache(SceneButtonsPanel, Panel):
- bl_label = "Rigid Body Cache"
+ bl_label = "Cache"
+ bl_parent_id = "SCENE_PT_rigid_body_world"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- rd = context.scene.render
scene = context.scene
- return scene and scene.rigidbody_world and (rd.engine in cls.COMPAT_ENGINES)
+ return scene and scene.rigidbody_world and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
scene = context.scene
@@ -391,15 +415,15 @@ class SCENE_PT_rigid_body_cache(SceneButtonsPanel, Panel):
class SCENE_PT_rigid_body_field_weights(SceneButtonsPanel, Panel):
- bl_label = "Rigid Body Field Weights"
+ bl_label = "Field Weights"
+ bl_parent_id = "SCENE_PT_rigid_body_world"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- rd = context.scene.render
scene = context.scene
- return scene and scene.rigidbody_world and (rd.engine in cls.COMPAT_ENGINES)
+ return scene and scene.rigidbody_world and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
scene = context.scene
@@ -410,7 +434,8 @@ class SCENE_PT_rigid_body_field_weights(SceneButtonsPanel, Panel):
class SCENE_PT_simplify(SceneButtonsPanel, Panel):
bl_label = "Simplify"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw_header(self, context):
rd = context.scene.render
@@ -419,46 +444,66 @@ class SCENE_PT_simplify(SceneButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+
+class SCENE_PT_simplify_viewport(SceneButtonsPanel, Panel):
+ bl_label = "Viewport"
+ bl_parent_id = "SCENE_PT_simplify"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
rd = context.scene.render
layout.active = rd.use_simplify
- split = layout.split()
+ col = layout.column()
+ col.prop(rd, "simplify_subdivision", text="Max Subdivision")
+ col.prop(rd, "simplify_child_particles", text="Max Child Particles")
+
+
+class SCENE_PT_simplify_render(SceneButtonsPanel, Panel):
+ bl_label = "Render"
+ bl_parent_id = "SCENE_PT_simplify"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- col = split.column()
- col.label(text="Viewport:")
- col.prop(rd, "simplify_subdivision", text="Subdivision")
- col.prop(rd, "simplify_child_particles", text="Child Particles")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ rd = context.scene.render
- col = split.column()
- col.label(text="Render:")
- col.prop(rd, "simplify_subdivision_render", text="Subdivision")
- col.prop(rd, "simplify_child_particles_render", text="Child Particles")
- col.prop(rd, "simplify_shadow_samples", text="Shadow Samples")
- col.prop(rd, "simplify_ao_sss", text="AO and SSS")
- col.prop(rd, "use_simplify_triangulate")
+ layout.active = rd.use_simplify
+
+ col = layout.column()
+ col.prop(rd, "simplify_subdivision_render", text="Max Subdivision")
+ col.prop(rd, "simplify_child_particles_render", text="Max Child Particles")
class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "scene"
_property_type = bpy.types.Scene
classes = (
- SCENE_MT_units_length_presets,
+ SCENE_PT_units_length_presets,
SCENE_UL_keying_set_paths,
SCENE_PT_scene,
SCENE_PT_unit,
SCENE_PT_keying_sets,
SCENE_PT_keying_set_paths,
SCENE_PT_color_management,
+ SCENE_PT_color_management_curves,
SCENE_PT_audio,
SCENE_PT_physics,
SCENE_PT_rigid_body_world,
SCENE_PT_rigid_body_cache,
SCENE_PT_rigid_body_field_weights,
SCENE_PT_simplify,
+ SCENE_PT_simplify_viewport,
+ SCENE_PT_simplify_render,
SCENE_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 018f3df6f0d..b08b47fbe77 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -23,12 +23,9 @@ from bpy.types import Menu, Panel, UIList
from bpy.types import (
Brush,
FreestyleLineStyle,
- Lamp,
- Material,
Object,
ParticleSettings,
Texture,
- World,
)
from rna_prop_ui import PropertyPanel
@@ -38,7 +35,7 @@ from .properties_paint_common import brush_texture_settings
class TEXTURE_MT_specials(Menu):
bl_label = "Texture Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context):
layout = self.layout
@@ -47,22 +44,9 @@ class TEXTURE_MT_specials(Menu):
layout.operator("texture.slot_paste", icon='PASTEDOWN')
-class TEXTURE_MT_envmap_specials(Menu):
- bl_label = "Environment Map Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("texture.envmap_save", icon='IMAGEFILE')
- layout.operator("texture.envmap_clear", icon='FILE_REFRESH')
- layout.operator("texture.envmap_clear_all", icon='FILE_REFRESH')
-
-
class TEXTURE_UL_texslots(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.MaterialTextureSlot)
ma = data
slot = item
tex = slot.texture if slot else None
@@ -71,29 +55,12 @@ class TEXTURE_UL_texslots(UIList):
layout.prop(tex, "name", text="", emboss=False, icon_value=icon)
else:
layout.label(text="", icon_value=icon)
- if tex and isinstance(item, bpy.types.MaterialTextureSlot):
- layout.prop(ma, "use_textures", text="", index=index)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
-from .properties_material import active_node_mat
-
-
def context_tex_datablock(context):
- idblock = context.material
- if idblock:
- return active_node_mat(idblock)
-
- idblock = context.lamp
- if idblock:
- return idblock
-
- idblock = context.world
- if idblock:
- return idblock
-
idblock = context.brush
if idblock:
return idblock
@@ -108,129 +75,20 @@ def context_tex_datablock(context):
return idblock
-def id_tex_datablock(bid):
- if isinstance(bid, Object):
- if bid.type == 'LAMP':
- return bid.data
- return bid.active_material
-
- return bid
-
-
class TextureButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "texture"
- @classmethod
- def poll(cls, context):
- tex = context.texture
- return tex and (tex.type != 'NONE' or tex.use_nodes) and (context.scene.render.engine in cls.COMPAT_ENGINES)
-
-class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
- bl_label = ""
- bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
+ bl_label = "Preview"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- engine = context.scene.render.engine
- # if not (hasattr(context, "texture_slot") or hasattr(context, "texture_node")):
- # return False
- return ((context.material or
- context.world or
- context.lamp or
- context.texture or
- context.line_style or
- context.particle_system or
- isinstance(context.space_data.pin_id, ParticleSettings) or
- context.texture_user) and
- (engine in cls.COMPAT_ENGINES))
-
- def draw(self, context):
- layout = self.layout
-
- slot = getattr(context, "texture_slot", None)
- node = getattr(context, "texture_node", None)
- space = context.space_data
tex = context.texture
- idblock = context_tex_datablock(context)
- pin_id = space.pin_id
-
- space.use_limited_texture_context = True
-
- if space.use_pin_id and not isinstance(pin_id, Texture):
- idblock = id_tex_datablock(pin_id)
- pin_id = None
-
- if not space.use_pin_id:
- layout.row().prop(space, "texture_context", expand=True)
- pin_id = None
-
- if space.texture_context == 'OTHER':
- if not pin_id:
- layout.template_texture_user()
- user = context.texture_user
- if user or pin_id:
- layout.separator()
-
- row = layout.row()
-
- if pin_id:
- row.template_ID(space, "pin_id")
- else:
- propname = context.texture_user_property.identifier
- row.template_ID(user, propname, new="texture.new")
-
- if tex:
- split = layout.split(percentage=0.2)
- if tex.use_nodes:
- if slot:
- split.label(text="Output:")
- split.prop(slot, "output_node", text="")
- else:
- split.label(text="Type:")
- split.prop(tex, "type", text="")
- return
-
- tex_collection = (pin_id is None) and (node is None) and (not isinstance(idblock, Brush))
-
- if tex_collection:
- row = layout.row()
-
- row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots",
- idblock, "active_texture_index", rows=2)
-
- col = row.column(align=True)
- col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
- col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
- col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
-
- if tex_collection:
- layout.template_ID(idblock, "active_texture", new="texture.new")
- elif node:
- layout.template_ID(node, "texture", new="texture.new")
- elif idblock:
- layout.template_ID(idblock, "texture", new="texture.new")
-
- if pin_id:
- layout.template_ID(space, "pin_id")
-
- if tex:
- split = layout.split(percentage=0.2)
- if tex.use_nodes:
- if slot:
- split.label(text="Output:")
- split.prop(slot, "output_node", text="")
- else:
- split.label(text="Type:")
- split.prop(tex, "type", text="")
-
-
-class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
- bl_label = "Preview"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ return tex and (tex.type != 'NONE' or tex.use_nodes) and (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -245,58 +103,100 @@ class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
layout.template_preview(tex, slot=slot)
# Show Alpha Button for Brush Textures, see #29502
- if context.space_data.texture_context == 'BRUSH':
+ idblock = context_tex_datablock(context)
+ if isinstance(idblock, Brush):
layout.prop(tex, "use_preview_alpha")
-class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
- bl_label = "Colors"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+class TEXTURE_PT_context(TextureButtonsPanel, Panel):
+ bl_label = ""
+ bl_context = "texture"
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
tex = context.texture
+ space = context.space_data
+ pin_id = space.pin_id
+ use_pin_id = space.use_pin_id
+ user = context.texture_user
- layout.prop(tex, "use_color_ramp", text="Ramp")
- if tex.use_color_ramp:
- layout.template_color_ramp(tex, "color_ramp", expand=True)
+ if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
+ pin_id = None
- split = layout.split()
+ if not pin_id:
+ layout.template_texture_user()
- col = split.column()
- col.label(text="RGB Multiply:")
- sub = col.column(align=True)
- sub.prop(tex, "factor_red", text="R")
- sub.prop(tex, "factor_green", text="G")
- sub.prop(tex, "factor_blue", text="B")
+ if user or pin_id:
+ layout.separator()
- col = split.column()
- col.label(text="Adjust:")
- col.prop(tex, "intensity")
- col.prop(tex, "contrast")
- col.prop(tex, "saturation")
+ split = layout.split(percentage=0.65)
+ col = split.column()
- col = layout.column()
- col.prop(tex, "use_clamp", text="Clamp")
+ if pin_id:
+ col.template_ID(space, "pin_id")
+ else:
+ propname = context.texture_user_property.identifier
+ col.template_ID(user, propname, new="texture.new")
-# Texture Slot Panels #
+ if tex:
+ split = layout.split(percentage=0.2)
+ split.label(text="Type:")
+ split.prop(tex, "type", text="")
-class TextureSlotPanel(TextureButtonsPanel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+class TEXTURE_PT_node(TextureButtonsPanel, Panel):
+ bl_label = "Node"
+ bl_context = "texture"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- if not hasattr(context, "texture_slot"):
- return False
+ node = context.texture_node
+ return node and (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ node = context.texture_node
+ ntree = node.id_data
+ layout.template_node_view(ntree, node, None)
+
+
+class TEXTURE_PT_node_mapping(TextureButtonsPanel, Panel):
+ bl_label = "Mapping"
+ bl_context = "texture"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- engine = context.scene.render.engine
- return TextureButtonsPanel.poll(cls, context) and (engine in cls.COMPAT_ENGINES)
+ @classmethod
+ def poll(cls, context):
+ node = context.texture_node
+ # TODO(sergey): perform a faster/nicer check?
+ return node and hasattr(node, 'texture_mapping') and (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ node = context.texture_node
-# Texture Type Panels #
+ mapping = node.texture_mapping
+
+ layout.prop(mapping, "vector_type", expand=True)
+
+ row = layout.row()
+
+ row.column().prop(mapping, "translation")
+ row.column().prop(mapping, "rotation")
+ row.column().prop(mapping, "scale")
+
+ layout.label(text="Projection:")
+
+ row = layout.row()
+ row.prop(mapping, "mapping_x", text="")
+ row.prop(mapping, "mapping_y", text="")
+ row.prop(mapping, "mapping_z", text="")
class TextureTypePanel(TextureButtonsPanel):
@@ -304,14 +204,14 @@ class TextureTypePanel(TextureButtonsPanel):
@classmethod
def poll(cls, context):
tex = context.texture
- engine = context.scene.render.engine
+ engine = context.engine
return tex and ((tex.type == cls.tex_type and not tex.use_nodes) and (engine in cls.COMPAT_ENGINES))
class TEXTURE_PT_clouds(TextureTypePanel, Panel):
bl_label = "Clouds"
tex_type = 'CLOUDS'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -335,7 +235,7 @@ class TEXTURE_PT_clouds(TextureTypePanel, Panel):
class TEXTURE_PT_wood(TextureTypePanel, Panel):
bl_label = "Wood"
tex_type = 'WOOD'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -364,7 +264,7 @@ class TEXTURE_PT_wood(TextureTypePanel, Panel):
class TEXTURE_PT_marble(TextureTypePanel, Panel):
bl_label = "Marble"
tex_type = 'MARBLE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -391,7 +291,7 @@ class TEXTURE_PT_marble(TextureTypePanel, Panel):
class TEXTURE_PT_magic(TextureTypePanel, Panel):
bl_label = "Magic"
tex_type = 'MAGIC'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -406,7 +306,7 @@ class TEXTURE_PT_magic(TextureTypePanel, Panel):
class TEXTURE_PT_blend(TextureTypePanel, Panel):
bl_label = "Blend"
tex_type = 'BLEND'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -424,7 +324,7 @@ class TEXTURE_PT_blend(TextureTypePanel, Panel):
class TEXTURE_PT_stucci(TextureTypePanel, Panel):
bl_label = "Stucci"
tex_type = 'STUCCI'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -444,221 +344,137 @@ class TEXTURE_PT_stucci(TextureTypePanel, Panel):
class TEXTURE_PT_image(TextureTypePanel, Panel):
bl_label = "Image"
tex_type = 'IMAGE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
tex = context.texture
-
layout.template_image(tex, "image", tex.image_user)
def texture_filter_common(tex, layout):
- layout.label(text="Filter:")
- layout.prop(tex, "filter_type", text="")
+ layout.prop(tex, "filter_type", text="Filter Type")
if tex.use_mipmap and tex.filter_type in {'AREA', 'EWA', 'FELINE'}:
if tex.filter_type == 'FELINE':
- layout.prop(tex, "filter_probes", text="Probes")
+ layout.prop(tex, "filter_lightprobes", text="Light Probes")
else:
layout.prop(tex, "filter_eccentricity", text="Eccentricity")
- layout.prop(tex, "filter_size")
- layout.prop(tex, "use_filter_size_min")
+ layout.prop(tex, "filter_size", text="Size")
+ layout.prop(tex, "use_filter_size_min", text="Minimum Size")
class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
- bl_label = "Image Sampling"
+ bl_label = "Sampling"
bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = 'TEXTURE_PT_image'
tex_type = 'IMAGE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
- if context.scene.render.engine == 'BLENDER_GAME':
- self.draw_bge(context)
- else:
- self.draw_bi(context)
-
- def draw_bi(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
idblock = context_tex_datablock(context)
tex = context.texture
slot = getattr(context, "texture_slot", None)
- split = layout.split()
+ col = flow.column()
+ col.prop(tex, "use_flip_axis", text="Flip X/Y Axis")
+ col.prop(tex, "use_interpolation")
- col = split.column()
- col.label(text="Alpha:")
- row = col.row()
- row.active = bool(tex.image and tex.image.use_alpha)
- row.prop(tex, "use_alpha", text="Use")
- col.prop(tex, "use_calculate_alpha", text="Calculate")
- col.prop(tex, "invert_alpha", text="Invert")
col.separator()
- col.prop(tex, "use_flip_axis", text="Flip X/Y Axis")
- col = split.column()
+ col = flow.column()
+ col.prop(tex, "use_mipmap")
+ sub = col.column()
+ sub.active = tex.use_mipmap
+ sub.prop(tex, "use_mipmap_gauss", text="Gaussian Filter")
- # Only for Material based textures, not for Lamp/World...
- if slot and isinstance(idblock, Material):
- col.prop(tex, "use_normal_map")
- row = col.row()
- row.active = tex.use_normal_map
- row.prop(slot, "normal_map_space", text="")
+ col.separator()
- row = col.row()
- row.active = not tex.use_normal_map
- row.prop(tex, "use_derivative_map")
+ col = flow.column()
+ texture_filter_common(tex, col)
- col.prop(tex, "use_mipmap")
- row = col.row()
- row.active = tex.use_mipmap
- row.prop(tex, "use_mipmap_gauss")
- col.prop(tex, "use_interpolation")
- texture_filter_common(tex, col)
+class TEXTURE_PT_image_alpha(TextureTypePanel, Panel):
+ bl_label = "Alpha"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = 'TEXTURE_PT_image'
+ tex_type = 'IMAGE'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- def draw_bge(self, context):
+ def draw_header(self, context):
+ tex = context.texture
+ self.layout.prop(tex, "use_alpha", text="")
+
+ def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
- idblock = context_tex_datablock(context)
tex = context.texture
- slot = getattr(context, "texture_slot", None)
- split = layout.split()
-
- col = split.column()
- col.label(text="Alpha:")
+ col = layout.column()
+ col.active = bool(tex.image and tex.image.use_alpha)
col.prop(tex, "use_calculate_alpha", text="Calculate")
col.prop(tex, "invert_alpha", text="Invert")
- col = split.column()
-
- # Only for Material based textures, not for Lamp/World...
- if slot and isinstance(idblock, Material):
- col.prop(tex, "use_normal_map")
- row = col.row()
- row.active = tex.use_normal_map
- row.prop(slot, "normal_map_space", text="")
-
- row = col.row()
- row.active = not tex.use_normal_map
- row.prop(tex, "use_derivative_map")
-
class TEXTURE_PT_image_mapping(TextureTypePanel, Panel):
- bl_label = "Image Mapping"
+ bl_label = "Mapping"
bl_options = {'DEFAULT_CLOSED'}
+ bl_parent_id = 'TEXTURE_PT_image'
tex_type = 'IMAGE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
tex = context.texture
- layout.prop(tex, "extension")
-
- split = layout.split()
+ col = flow.column()
+ col.prop(tex, "extension")
if tex.extension == 'REPEAT':
- col = split.column(align=True)
- col.label(text="Repeat:")
- col.prop(tex, "repeat_x", text="X")
- col.prop(tex, "repeat_y", text="Y")
-
- col = split.column(align=True)
- col.label(text="Mirror:")
- row = col.row(align=True)
- row.prop(tex, "use_mirror_x", text="X")
- row.active = (tex.repeat_x > 1)
- row = col.row(align=True)
- row.prop(tex, "use_mirror_y", text="Y")
- row.active = (tex.repeat_y > 1)
- layout.separator()
+ sub = col.column(align=True)
+ sub.prop(tex, "repeat_x", text="Repeat X")
+ sub.prop(tex, "repeat_y", text="Y")
- elif tex.extension == 'CHECKER':
- col = split.column(align=True)
- row = col.row(align=True)
- row.prop(tex, "use_checker_even", text="Even")
- row.prop(tex, "use_checker_odd", text="Odd")
+ sub = col.column()
+ sub.prop(tex, "use_mirror_x", text="Mirror X")
+ sub.active = (tex.repeat_x > 1)
- col = split.column()
- col.prop(tex, "checker_distance", text="Distance")
+ sub = col.column()
+ sub.prop(tex, "use_mirror_y", text="Y")
+ sub.active = (tex.repeat_y > 1)
- layout.separator()
+ elif tex.extension == 'CHECKER':
+ col = layout.column(align=True)
+ col.prop(tex, "use_checker_even", text="Even")
+ col.prop(tex, "use_checker_odd", text="Odd")
- split = layout.split()
+ col = layout.column()
+ col.prop(tex, "checker_distance", text="Distance")
- col = split.column(align=True)
+ col = flow.column()
+ sub = col.column(align=True)
# col.prop(tex, "crop_rectangle")
- col.label(text="Crop Minimum:")
- col.prop(tex, "crop_min_x", text="X")
- col.prop(tex, "crop_min_y", text="Y")
-
- col = split.column(align=True)
- col.label(text="Crop Maximum:")
- col.prop(tex, "crop_max_x", text="X")
- col.prop(tex, "crop_max_y", text="Y")
-
-
-class TEXTURE_PT_envmap(TextureTypePanel, Panel):
- bl_label = "Environment Map"
- tex_type = 'ENVIRONMENT_MAP'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- tex = context.texture
- env = tex.environment_map
-
- row = layout.row()
- row.prop(env, "source", expand=True)
- row.menu("TEXTURE_MT_envmap_specials", icon='DOWNARROW_HLT', text="")
-
- if env.source == 'IMAGE_FILE':
- layout.template_ID(tex, "image", open="image.open")
- layout.template_image(tex, "image", tex.image_user, compact=True)
- else:
- layout.prop(env, "mapping")
- if env.mapping == 'PLANE':
- layout.prop(env, "zoom")
- layout.prop(env, "viewpoint_object")
-
- split = layout.split()
+ sub.prop(tex, "crop_min_x", text="Crop Minimum X")
+ sub.prop(tex, "crop_min_y", text="Y")
- col = split.column()
- col.prop(env, "layers_ignore")
- col.prop(env, "resolution")
- col.prop(env, "depth")
-
- col = split.column(align=True)
-
- col.label(text="Clipping:")
- col.prop(env, "clip_start", text="Start")
- col.prop(env, "clip_end", text="End")
-
-
-class TEXTURE_PT_envmap_sampling(TextureTypePanel, Panel):
- bl_label = "Environment Map Sampling"
- bl_options = {'DEFAULT_CLOSED'}
- tex_type = 'ENVIRONMENT_MAP'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- tex = context.texture
-
- texture_filter_common(tex, layout)
+ sub = col.column(align=True)
+ sub.prop(tex, "crop_max_x", text="Crop Maximum X")
+ sub.prop(tex, "crop_max_y", text="Y")
class TEXTURE_PT_musgrave(TextureTypePanel, Panel):
bl_label = "Musgrave"
tex_type = 'MUSGRAVE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -694,7 +510,7 @@ class TEXTURE_PT_musgrave(TextureTypePanel, Panel):
class TEXTURE_PT_voronoi(TextureTypePanel, Panel):
bl_label = "Voronoi"
tex_type = 'VORONOI'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -730,7 +546,7 @@ class TEXTURE_PT_voronoi(TextureTypePanel, Panel):
class TEXTURE_PT_distortednoise(TextureTypePanel, Panel):
bl_label = "Distorted Noise"
tex_type = 'DISTORTED_NOISE'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -749,180 +565,20 @@ class TEXTURE_PT_distortednoise(TextureTypePanel, Panel):
split.prop(tex, "nabla")
-class TEXTURE_PT_voxeldata(TextureButtonsPanel, Panel):
- bl_label = "Voxel Data"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- tex = context.texture
- engine = context.scene.render.engine
- return tex and (tex.type == 'VOXEL_DATA' and (engine in cls.COMPAT_ENGINES))
-
- def draw(self, context):
- layout = self.layout
-
- tex = context.texture
- vd = tex.voxel_data
-
- layout.prop(vd, "file_format")
- if vd.file_format in {'BLENDER_VOXEL', 'RAW_8BIT'}:
- layout.prop(vd, "filepath")
- if vd.file_format == 'RAW_8BIT':
- layout.prop(vd, "resolution")
- elif vd.file_format == 'SMOKE':
- layout.prop(vd, "domain_object")
- layout.prop(vd, "smoke_data_type")
- elif vd.file_format == 'HAIR':
- layout.prop(vd, "domain_object")
- layout.prop(vd, "hair_data_type")
- elif vd.file_format == 'IMAGE_SEQUENCE':
- layout.template_ID(tex, "image", open="image.open")
- layout.template_image(tex, "image", tex.image_user, compact=True)
- # layout.prop(vd, "frame_duration")
-
- if vd.file_format in {'BLENDER_VOXEL', 'RAW_8BIT'}:
- layout.prop(vd, "use_still_frame")
- row = layout.row()
- row.active = vd.use_still_frame
- row.prop(vd, "still_frame")
-
- layout.prop(vd, "interpolation")
- layout.prop(vd, "extension")
- layout.prop(vd, "intensity")
-
-
-class TEXTURE_PT_pointdensity(TextureButtonsPanel, Panel):
- bl_label = "Point Density"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- tex = context.texture
- engine = context.scene.render.engine
- return tex and (tex.type == 'POINT_DENSITY' and (engine in cls.COMPAT_ENGINES))
-
- def draw(self, context):
- layout = self.layout
-
- tex = context.texture
- pd = tex.point_density
-
- layout.row().prop(pd, "point_source", expand=True)
-
- split = layout.split()
-
- col = split.column()
- if pd.point_source == 'PARTICLE_SYSTEM':
- col.label(text="Object:")
- col.prop(pd, "object", text="")
-
- sub = col.column()
- sub.enabled = bool(pd.object)
- if pd.object:
- sub.label(text="System:")
- sub.prop_search(pd, "particle_system", pd.object, "particle_systems", text="")
- sub.label(text="Cache:")
- sub.prop(pd, "particle_cache_space", text="")
- else:
- col.label(text="Object:")
- col.prop(pd, "object", text="")
- col.label(text="Cache:")
- col.prop(pd, "vertex_cache_space", text="")
-
- col.separator()
-
- col.label(text="Color Source:")
- if pd.point_source == 'PARTICLE_SYSTEM':
- col.prop(pd, "particle_color_source", text="")
- if pd.particle_color_source in {'PARTICLE_SPEED', 'PARTICLE_VELOCITY'}:
- col.prop(pd, "speed_scale")
- if pd.particle_color_source in {'PARTICLE_SPEED', 'PARTICLE_AGE'}:
- layout.template_color_ramp(pd, "color_ramp", expand=True)
- else:
- col.prop(pd, "vertex_color_source", text="")
- if pd.vertex_color_source == 'VERTEX_COLOR':
- if pd.object and pd.object.data:
- col.prop_search(pd, "vertex_attribute_name", pd.object.data, "vertex_colors", text="")
- if pd.vertex_color_source == 'VERTEX_WEIGHT':
- if pd.object:
- col.prop_search(pd, "vertex_attribute_name", pd.object, "vertex_groups", text="")
- layout.template_color_ramp(pd, "color_ramp", expand=True)
-
- col = split.column()
- col.label()
- col.prop(pd, "radius")
- col.label(text="Falloff:")
- col.prop(pd, "falloff", text="")
- if pd.falloff == 'SOFT':
- col.prop(pd, "falloff_soft")
- if pd.falloff == 'PARTICLE_VELOCITY':
- col.prop(pd, "falloff_speed_scale")
-
- col.prop(pd, "use_falloff_curve")
-
- if pd.use_falloff_curve:
- col = layout.column()
- col.label(text="Falloff Curve")
- col.template_curve_mapping(pd, "falloff_curve", brush=False)
-
-
-class TEXTURE_PT_pointdensity_turbulence(TextureButtonsPanel, Panel):
- bl_label = "Turbulence"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+class TextureSlotPanel(TextureButtonsPanel):
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- tex = context.texture
- engine = context.scene.render.engine
- return tex and (tex.type == 'POINT_DENSITY' and (engine in cls.COMPAT_ENGINES))
-
- def draw_header(self, context):
- pd = context.texture.point_density
-
- self.layout.prop(pd, "use_turbulence", text="")
-
- def draw(self, context):
- layout = self.layout
-
- tex = context.texture
- pd = tex.point_density
- layout.active = pd.use_turbulence
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Influence:")
- col.prop(pd, "turbulence_influence", text="")
- col.label(text="Noise Basis:")
- col.prop(pd, "noise_basis", text="")
-
- col = split.column()
- col.label()
- col.prop(pd, "turbulence_scale")
- col.prop(pd, "turbulence_depth")
- col.prop(pd, "turbulence_strength")
-
-
-class TEXTURE_PT_ocean(TextureTypePanel, Panel):
- bl_label = "Ocean"
- tex_type = 'OCEAN'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- tex = context.texture
- ot = tex.ocean
+ if not hasattr(context, "texture_slot"):
+ return False
- col = layout.column()
- col.prop(ot, "ocean_object")
- col.prop(ot, "output")
+ return (context.engine in cls.COMPAT_ENGINES)
class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
bl_label = "Mapping"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -933,7 +589,7 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
if not getattr(context, "texture_slot", None):
return False
- engine = context.scene.render.engine
+ engine = context.engine
return (engine in cls.COMPAT_ENGINES)
def draw(self, context):
@@ -963,7 +619,7 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
split.label(text="Map:")
ob = context.object
if ob and ob.type == 'MESH':
- split.prop_search(tex, "uv_layer", ob.data, "uv_textures", text="")
+ split.prop_search(tex, "uv_layer", ob.data, "uv_layers", text="")
else:
split.prop(tex, "uv_layer", text="")
@@ -993,31 +649,6 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
row.prop(tex, "mapping_y", text="")
row.prop(tex, "mapping_z", text="")
- elif isinstance(idblock, Material):
- split = layout.split(percentage=0.3)
- split.label(text="Projection:")
- split.prop(tex, "mapping", text="")
-
- split = layout.split()
-
- col = split.column()
- if tex.texture_coords in {'ORCO', 'UV'}:
- col.prop(tex, "use_from_dupli")
- if (idblock.type == 'VOLUME' and tex.texture_coords == 'ORCO'):
- col.prop(tex, "use_map_to_bounds")
- elif tex.texture_coords == 'OBJECT':
- col.prop(tex, "use_from_original")
- if (idblock.type == 'VOLUME'):
- col.prop(tex, "use_map_to_bounds")
- else:
- col.label()
-
- col = split.column()
- row = col.row()
- row.prop(tex, "mapping_x", text="")
- row.prop(tex, "mapping_y", text="")
- row.prop(tex, "mapping_z", text="")
-
row = layout.row()
row.column().prop(tex, "offset")
row.column().prop(tex, "scale")
@@ -1025,7 +656,7 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
class TEXTURE_PT_influence(TextureSlotPanel, Panel):
bl_label = "Influence"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -1036,7 +667,7 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
if not getattr(context, "texture_slot", None):
return False
- engine = context.scene.render.engine
+ engine = context.engine
return (engine in cls.COMPAT_ENGINES)
def draw(self, context):
@@ -1055,101 +686,7 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
sub.prop(tex, factor, text=name, slider=True)
return sub # XXX, temp. use_map_normal needs to override.
- if isinstance(idblock, Material):
- if idblock.type in {'SURFACE', 'WIRE'}:
- split = layout.split()
-
- col = split.column()
- col.label(text="Diffuse:")
- factor_but(col, "use_map_diffuse", "diffuse_factor", "Intensity")
- factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
- factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
- factor_but(col, "use_map_translucency", "translucency_factor", "Translucency")
-
- col.label(text="Specular:")
- factor_but(col, "use_map_specular", "specular_factor", "Intensity")
- factor_but(col, "use_map_color_spec", "specular_color_factor", "Color")
- factor_but(col, "use_map_hardness", "hardness_factor", "Hardness")
-
- col = split.column()
- col.label(text="Shading:")
- factor_but(col, "use_map_ambient", "ambient_factor", "Ambient")
- factor_but(col, "use_map_emit", "emit_factor", "Emit")
- factor_but(col, "use_map_mirror", "mirror_factor", "Mirror")
- factor_but(col, "use_map_raymir", "raymir_factor", "Ray Mirror")
-
- col.label(text="Geometry:")
- # XXX replace 'or' when displacement is fixed to not rely on normal influence value.
- sub_tmp = factor_but(col, "use_map_normal", "normal_factor", "Normal")
- sub_tmp.active = (tex.use_map_normal or tex.use_map_displacement)
- # END XXX
-
- factor_but(col, "use_map_warp", "warp_factor", "Warp")
- factor_but(col, "use_map_displacement", "displacement_factor", "Displace")
-
- # ~ sub = col.column()
- # ~ sub.active = tex.use_map_translucency or tex.map_emit or tex.map_alpha or tex.map_raymir or tex.map_hardness or tex.map_ambient or tex.map_specularity or tex.map_reflection or tex.map_mirror
- #~ sub.prop(tex, "default_value", text="Amount", slider=True)
- elif idblock.type == 'HALO':
- layout.label(text="Halo:")
-
- split = layout.split()
-
- col = split.column()
- factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
- factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
-
- col = split.column()
- factor_but(col, "use_map_raymir", "raymir_factor", "Size")
- factor_but(col, "use_map_hardness", "hardness_factor", "Hardness")
- factor_but(col, "use_map_translucency", "translucency_factor", "Add")
- elif idblock.type == 'VOLUME':
- layout.label(text="Volume:")
-
- split = layout.split()
-
- col = split.column()
- factor_but(col, "use_map_density", "density_factor", "Density")
- factor_but(col, "use_map_emission", "emission_factor", "Emission")
- factor_but(col, "use_map_scatter", "scattering_factor", "Scattering")
- factor_but(col, "use_map_reflect", "reflection_factor", "Reflection")
-
- col = split.column()
- col.label(text=" ")
- factor_but(col, "use_map_color_emission", "emission_color_factor", "Emission Color")
- factor_but(col, "use_map_color_transmission", "transmission_color_factor", "Transmission Color")
- factor_but(col, "use_map_color_reflection", "reflection_color_factor", "Reflection Color")
-
- layout.label(text="Geometry:")
-
- split = layout.split()
-
- col = split.column()
- factor_but(col, "use_map_warp", "warp_factor", "Warp")
-
- col = split.column()
- factor_but(col, "use_map_displacement", "displacement_factor", "Displace")
-
- elif isinstance(idblock, Lamp):
- split = layout.split()
-
- col = split.column()
- factor_but(col, "use_map_color", "color_factor", "Color")
-
- col = split.column()
- factor_but(col, "use_map_shadow", "shadow_factor", "Shadow")
-
- elif isinstance(idblock, World):
- split = layout.split()
-
- col = split.column()
- factor_but(col, "use_map_blend", "blend_factor", "Blend")
- factor_but(col, "use_map_horizon", "horizon_factor", "Horizon")
-
- col = split.column()
- factor_but(col, "use_map_zenith_up", "zenith_up_factor", "Zenith Up")
- factor_but(col, "use_map_zenith_down", "zenith_down_factor", "Zenith Down")
- elif isinstance(idblock, ParticleSettings):
+ if isinstance(idblock, ParticleSettings):
split = layout.split()
col = split.column()
@@ -1203,48 +740,59 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
col.prop(tex, "invert", text="Negative")
col.prop(tex, "use_stencil")
- if isinstance(idblock, (Material, World)):
- col.prop(tex, "default_value", text="DVar", slider=True)
- if isinstance(idblock, Material):
- layout.label(text="Bump Mapping:")
+class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
+ bl_label = "Colors"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
- # only show bump settings if activated but not for normal-map images
- row = layout.row()
+ @classmethod
+ def poll(cls, context):
+ tex = context.texture
+ return tex and (tex.type != 'NONE' or tex.use_nodes) and (context.engine in cls.COMPAT_ENGINES)
- sub = row.row()
- sub.active = (
- (tex.use_map_normal or tex.use_map_warp) and
- not (tex.texture.type == 'IMAGE' and
- (tex.texture.use_normal_map or tex.texture.use_derivative_map))
- )
- sub.prop(tex, "bump_method", text="Method")
-
- # the space setting is supported for: derivative-maps + bump-maps
- # (DEFAULT,BEST_QUALITY), not for normal-maps
- sub = row.row()
- sub.active = (
- (tex.use_map_normal or tex.use_map_warp) and
- not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and
- ((tex.bump_method in {'BUMP_LOW_QUALITY', 'BUMP_MEDIUM_QUALITY', 'BUMP_BEST_QUALITY'}) or
- (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map))
- )
- sub.prop(tex, "bump_objectspace", text="Space")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ tex = context.texture
+
+ col = layout.column()
+ sub = col.column(align=True)
+ sub.prop(tex, "factor_red", text="Multiply R")
+ sub.prop(tex, "factor_green", text="G")
+ sub.prop(tex, "factor_blue", text="B")
+
+ col.prop(tex, "intensity")
+ col.prop(tex, "contrast")
+ col.prop(tex, "saturation")
+
+ col.prop(tex, "use_clamp", text="Clamp")
+ col.prop(tex, "use_color_ramp", text="Ramp")
+ if tex.use_color_ramp:
+ layout.use_property_split = False
+ layout.template_color_ramp(tex, "color_ramp", expand=True)
class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "texture"
_property_type = Texture
+ @classmethod
+ def poll(cls, context):
+ return context.texture and (context.engine in cls.COMPAT_ENGINES)
+
classes = (
TEXTURE_MT_specials,
- TEXTURE_MT_envmap_specials,
TEXTURE_UL_texslots,
- TEXTURE_PT_context_texture,
TEXTURE_PT_preview,
- TEXTURE_PT_colors,
+ TEXTURE_PT_context,
+ TEXTURE_PT_node,
+ TEXTURE_PT_node_mapping,
+ TEXTURE_PT_mapping,
+ TEXTURE_PT_influence,
TEXTURE_PT_clouds,
TEXTURE_PT_wood,
TEXTURE_PT_marble,
@@ -1252,19 +800,13 @@ classes = (
TEXTURE_PT_blend,
TEXTURE_PT_stucci,
TEXTURE_PT_image,
+ TEXTURE_PT_image_alpha,
TEXTURE_PT_image_sampling,
TEXTURE_PT_image_mapping,
- TEXTURE_PT_envmap,
- TEXTURE_PT_envmap_sampling,
TEXTURE_PT_musgrave,
TEXTURE_PT_voronoi,
TEXTURE_PT_distortednoise,
- TEXTURE_PT_voxeldata,
- TEXTURE_PT_pointdensity,
- TEXTURE_PT_pointdensity_turbulence,
- TEXTURE_PT_ocean,
- TEXTURE_PT_mapping,
- TEXTURE_PT_influence,
+ TEXTURE_PT_colors,
TEXTURE_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
new file mode 100644
index 00000000000..05dc15216a2
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -0,0 +1,82 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Panel, UIList
+
+
+class ViewLayerButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "view_layer"
+ # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
+
+ @classmethod
+ def poll(cls, context):
+ return (context.engine in cls.COMPAT_ENGINES)
+
+
+class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel):
+ bl_label = "View Layer"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ rd = scene.render
+ layer = bpy.context.view_layer
+
+ layout.prop(layer, "use", text="Use for Rendering")
+ layout.prop(rd, "use_single_layer", text="Render Single Layer")
+
+
+class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel):
+ bl_label = "Passes"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ scene = context.scene
+ rd = scene.render
+ view_layer = context.view_layer
+
+ col = layout.column()
+ col.prop(view_layer, "use_pass_combined")
+ col.prop(view_layer, "use_pass_z")
+ col.prop(view_layer, "use_pass_mist")
+ col.prop(view_layer, "use_pass_normal")
+ col.prop(view_layer, "use_pass_ambient_occlusion")
+ col.prop(view_layer, "use_pass_subsurface_direct", text="Subsurface Direct")
+ col.prop(view_layer, "use_pass_subsurface_color", text="Subsurface Color")
+
+
+classes = (
+ VIEWLAYER_PT_layer,
+ VIEWLAYER_PT_eevee_layer_passes,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index 107c31567b3..52a769fd223 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -20,6 +20,7 @@
import bpy
from bpy.types import Panel
from rna_prop_ui import PropertyPanel
+from bpy_extras.node_utils import find_node_input
class WorldButtonsPanel:
@@ -30,18 +31,17 @@ class WorldButtonsPanel:
@classmethod
def poll(cls, context):
- return (context.world and context.scene.render.engine in cls.COMPAT_ENGINES)
+ return (context.world and context.engine in cls.COMPAT_ENGINES)
class WORLD_PT_context_world(WorldButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- rd = context.scene.render
- return rd.engine in cls.COMPAT_ENGINES
+ return (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -50,215 +50,84 @@ class WORLD_PT_context_world(WorldButtonsPanel, Panel):
world = context.world
space = context.space_data
- texture_count = world and len(world.texture_slots.keys())
-
split = layout.split(percentage=0.85)
if scene:
split.template_ID(scene, "world", new="world.new")
elif world:
split.template_ID(space, "pin_id")
- if texture_count:
- split.label(text=str(texture_count), icon='TEXTURE')
-
-class WORLD_PT_preview(WorldButtonsPanel, Panel):
- bl_label = "Preview"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+class EEVEE_WORLD_PT_mist(WorldButtonsPanel, Panel):
+ bl_label = "Mist Pass"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
- rd = context.scene.render
- return (context.world) and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- self.layout.template_preview(context.world)
+ engine = context.engine
+ if context.world and (engine in cls.COMPAT_ENGINES):
+ for view_layer in context.scene.view_layers:
+ if view_layer.use_pass_mist:
+ return True
-
-class WORLD_PT_world(WorldButtonsPanel, Panel):
- bl_label = "World"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ return False
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
world = context.world
- row = layout.row()
- row.prop(world, "use_sky_paper")
- row.prop(world, "use_sky_blend")
- row.prop(world, "use_sky_real")
-
- row = layout.row()
- row.column().prop(world, "horizon_color")
- col = row.column()
- col.prop(world, "zenith_color")
- col.active = world.use_sky_blend
- row.column().prop(world, "ambient_color")
-
- row = layout.row()
- row.prop(world, "exposure")
- row.prop(world, "color_range")
-
-
-class WORLD_PT_ambient_occlusion(WorldButtonsPanel, Panel):
- bl_label = "Ambient Occlusion"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw_header(self, context):
- light = context.world.light_settings
- self.layout.prop(light, "use_ambient_occlusion", text="")
-
- def draw(self, context):
- layout = self.layout
-
- light = context.world.light_settings
-
- layout.active = light.use_ambient_occlusion
-
- split = layout.split()
- split.prop(light, "ao_factor", text="Factor")
- split.prop(light, "ao_blend_type", text="")
-
-
-class WORLD_PT_environment_lighting(WorldButtonsPanel, Panel):
- bl_label = "Environment Lighting"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw_header(self, context):
- light = context.world.light_settings
- self.layout.prop(light, "use_environment_light", text="")
-
- def draw(self, context):
- layout = self.layout
-
- light = context.world.light_settings
-
- layout.active = light.use_environment_light
-
- split = layout.split()
- split.prop(light, "environment_energy", text="Energy")
- split.prop(light, "environment_color", text="")
-
-
-class WORLD_PT_indirect_lighting(WorldButtonsPanel, Panel):
- bl_label = "Indirect Lighting"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw_header(self, context):
- light = context.world.light_settings
- self.layout.prop(light, "use_indirect_light", text="")
-
- def draw(self, context):
- layout = self.layout
-
- light = context.world.light_settings
-
- layout.active = light.use_indirect_light and light.gather_method == 'APPROXIMATE'
-
- split = layout.split()
- split.prop(light, "indirect_factor", text="Factor")
- split.prop(light, "indirect_bounces", text="Bounces")
-
- if light.gather_method == 'RAYTRACE':
- layout.label(text="Only works with Approximate gather method")
-
-
-class WORLD_PT_gather(WorldButtonsPanel, Panel):
- bl_label = "Gather"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- light = context.world.light_settings
-
- layout.active = light.use_ambient_occlusion or light.use_environment_light or light.use_indirect_light
-
- layout.row().prop(light, "gather_method", expand=True)
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Attenuation:")
- if light.gather_method == 'RAYTRACE':
- col.prop(light, "distance")
- col.prop(light, "use_falloff")
- sub = col.row()
- sub.active = light.use_falloff
- sub.prop(light, "falloff_strength", text="Strength")
-
- if light.gather_method == 'RAYTRACE':
- col = split.column()
-
- col.label(text="Sampling:")
- col.prop(light, "sample_method", text="")
-
- sub = col.column()
- sub.prop(light, "samples")
-
- if light.sample_method == 'ADAPTIVE_QMC':
- sub.prop(light, "threshold")
- sub.prop(light, "adapt_to_speed", slider=True)
- elif light.sample_method == 'CONSTANT_JITTERED':
- sub.prop(light, "bias")
-
- if light.gather_method == 'APPROXIMATE':
- col = split.column()
+ layout.prop(world.mist_settings, "start")
+ layout.prop(world.mist_settings, "depth")
+ layout.prop(world.mist_settings, "falloff")
- col.label(text="Sampling:")
- col.prop(light, "passes")
- col.prop(light, "error_threshold", text="Error")
- col.prop(light, "use_cache")
- col.prop(light, "correction")
+class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+ _context_path = "world"
+ _property_type = bpy.types.World
-class WORLD_PT_mist(WorldButtonsPanel, Panel):
- bl_label = "Mist"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
- def draw_header(self, context):
- world = context.world
+class EEVEE_WORLD_PT_surface(WorldButtonsPanel, Panel):
+ bl_label = "Surface"
+ bl_context = "world"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
- self.layout.prop(world.mist_settings, "use_mist", text="")
+ @classmethod
+ def poll(cls, context):
+ engine = context.engine
+ return context.world and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
world = context.world
- layout.active = world.mist_settings.use_mist
+ layout.prop(world, "use_nodes", icon='NODETREE')
+ layout.separator()
- split = layout.split()
+ if world.use_nodes:
+ ntree = world.node_tree
+ node = ntree.get_output_node('EEVEE')
- col = split.column()
- col.prop(world.mist_settings, "intensity")
- col.prop(world.mist_settings, "start")
-
- col = split.column()
- col.prop(world.mist_settings, "depth")
- col.prop(world.mist_settings, "height")
-
- layout.prop(world.mist_settings, "falloff")
-
-
-class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- _context_path = "world"
- _property_type = bpy.types.World
+ if node:
+ input = find_node_input(node, 'Surface')
+ if input:
+ layout.template_node_view(ntree, node, input)
+ else:
+ layout.label(text="Incompatible output node")
+ else:
+ layout.label(text="No output node")
+ else:
+ layout.prop(world, "horizon_color", text="Color")
classes = (
WORLD_PT_context_world,
- WORLD_PT_preview,
- WORLD_PT_world,
- WORLD_PT_ambient_occlusion,
- WORLD_PT_environment_lighting,
- WORLD_PT_indirect_lighting,
- WORLD_PT_gather,
- WORLD_PT_mist,
WORLD_PT_custom_props,
+ EEVEE_WORLD_PT_surface,
+ EEVEE_WORLD_PT_mist,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index f8d9ae3ef9f..23c3e97ac9a 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -21,6 +21,7 @@
import bpy
from bpy.types import Panel, Header, Menu, UIList
from bpy.app.translations import pgettext_iface as iface_
+from bl_operators.presets import PresetMenu
from .properties_grease_pencil_common import (
GreasePencilDrawingToolsPanel,
GreasePencilStrokeEditPanel,
@@ -57,21 +58,20 @@ class CLIP_HT_header(Header):
sc = context.space_data
clip = sc.clip
- row = layout.row(align=True)
- row.template_header()
-
CLIP_MT_tracking_editor_menus.draw_collapsible(context, layout)
+ layout.separator_spacer()
+
row = layout.row()
row.template_ID(sc, "clip", open="clip.open")
+ layout.separator_spacer()
+
if clip:
tracking = clip.tracking
active_object = tracking.objects.active
if sc.view == 'CLIP':
- layout.prop(sc, "mode", text="")
- layout.prop(sc, "view", text="", expand=True)
layout.prop(sc, "pivot_point", text="", icon_only=True)
r = active_object.reconstruction
@@ -80,8 +80,6 @@ class CLIP_HT_header(Header):
layout.label(text="Solve error: %.4f" %
(r.average_error))
elif sc.view == 'GRAPH':
- layout.prop(sc, "view", text="", expand=True)
-
row = layout.row(align=True)
row.prop(sc, "show_graph_only_selected", text="")
row.prop(sc, "show_graph_hidden", text="")
@@ -103,7 +101,6 @@ class CLIP_HT_header(Header):
text="Filters")
elif sc.view == 'DOPESHEET':
dopesheet = tracking.dopesheet
- layout.prop(sc, "view", text="", expand=True)
row = layout.row(align=True)
row.prop(dopesheet, "show_only_selected", text="")
@@ -113,8 +110,6 @@ class CLIP_HT_header(Header):
row.prop(dopesheet, "sort_method", text="")
row.prop(dopesheet, "use_invert_sort",
text="Invert", toggle=True)
- else:
- layout.prop(sc, "view", text="", expand=True)
def _draw_masking(self, context):
layout = self.layout
@@ -123,35 +118,40 @@ class CLIP_HT_header(Header):
sc = context.space_data
clip = sc.clip
- row = layout.row(align=True)
- row.template_header()
-
CLIP_MT_masking_editor_menus.draw_collapsible(context, layout)
+ layout.separator_spacer()
+
row = layout.row()
row.template_ID(sc, "clip", open="clip.open")
- if clip:
- layout.prop(sc, "mode", text="")
+ layout.separator_spacer()
+ if clip:
row = layout.row()
row.template_ID(sc, "mask", new="mask.new")
+ layout.separator_spacer()
+
layout.prop(sc, "pivot_point", text="", icon_only=True)
row = layout.row(align=True)
- row.prop(toolsettings, "use_proportional_edit_mask",
- text="", icon_only=True)
- if toolsettings.use_proportional_edit_mask:
- row.prop(toolsettings, "proportional_edit_falloff",
- text="", icon_only=True)
+ row.prop(toolsettings, "use_proportional_edit_mask", text="", icon_only=True)
+ sub = row.row(align=True)
+ sub.active = toolsettings.use_proportional_edit_mask
+ sub.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
def draw(self, context):
layout = self.layout
sc = context.space_data
+ row = layout.row(align=True)
+ row.template_header()
+
+ layout.prop(sc, "mode", text="")
if sc.mode == 'TRACKING':
+ layout.prop(sc, "view", text="")
self._draw_tracking(context)
else:
self._draw_masking(context)
@@ -284,6 +284,9 @@ class CLIP_PT_tracking_settings(CLIP_PT_tracking_panel, Panel):
bl_label = "Tracking Settings"
bl_category = "Track"
+ def draw_header_preset(self, context):
+ CLIP_PT_tracking_settings_presets.draw_panel_header(self.layout)
+
def draw(self, context):
sc = context.space_data
@@ -293,14 +296,6 @@ class CLIP_PT_tracking_settings(CLIP_PT_tracking_panel, Panel):
col = layout.column()
row = col.row(align=True)
- label = CLIP_MT_tracking_settings_presets.bl_label
- row.menu('CLIP_MT_tracking_settings_presets', text=label)
- row.operator("clip.tracking_settings_preset_add",
- text="", icon='ZOOMIN')
- row.operator("clip.tracking_settings_preset_add",
- text="", icon='ZOOMOUT').remove_active = True
-
- row = col.row(align=True)
row.prop(settings, "use_default_red_channel",
text="R", toggle=True)
row.prop(settings, "use_default_green_channel",
@@ -632,12 +627,8 @@ class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
layout.separator()
row = layout.row(align=True)
- label = bpy.types.CLIP_MT_track_color_presets.bl_label
- row.menu('CLIP_MT_track_color_presets', text=label)
+ CLIP_PT_track_color_presets.draw_menu(row, 'Color Presets')
row.menu('CLIP_MT_track_color_specials', text="", icon='DOWNARROW_HLT')
- row.operator("clip.track_color_preset_add", text="", icon='ZOOMIN')
- row.operator("clip.track_color_preset_add",
- text="", icon='ZOOMOUT').remove_active = True
row = layout.row()
row.prop(act_track, "use_custom_color")
@@ -727,19 +718,15 @@ class CLIP_PT_tracking_camera(Panel):
return False
+ def draw_header_preset(self, context):
+ CLIP_PT_camera_presets.draw_panel_header(self.layout)
+
def draw(self, context):
layout = self.layout
sc = context.space_data
clip = sc.clip
- row = layout.row(align=True)
- label = bpy.types.CLIP_MT_camera_presets.bl_label
- row.menu('CLIP_MT_camera_presets', text=label)
- row.operator("clip.camera_preset_add", text="", icon='ZOOMIN')
- row.operator("clip.camera_preset_add", text="",
- icon='ZOOMOUT').remove_active = True
-
col = layout.column(align=True)
col.label(text="Sensor:")
col.prop(clip.tracking.camera, "sensor_width", text="Width")
@@ -1245,9 +1232,8 @@ class CLIP_MT_view(Menu):
layout.prop(sc, "show_locked_time")
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+
+ layout.menu("INFO_MT_area")
class CLIP_MT_clip(Menu):
@@ -1439,28 +1425,28 @@ class CLIP_MT_tracking_specials(Menu):
text="Unlock Tracks").action = 'UNLOCK'
-class CLIP_MT_camera_presets(Menu):
+class CLIP_PT_camera_presets(PresetMenu):
"""Predefined tracking camera intrinsics"""
bl_label = "Camera Presets"
preset_subdir = "tracking_camera"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "clip.camera_preset_add"
-class CLIP_MT_track_color_presets(Menu):
+class CLIP_PT_track_color_presets(PresetMenu):
"""Predefined track color"""
bl_label = "Color Presets"
preset_subdir = "tracking_track_color"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "clip.track_color_preset_add"
-class CLIP_MT_tracking_settings_presets(Menu):
+class CLIP_PT_tracking_settings_presets(PresetMenu):
"""Predefined tracking settings"""
bl_label = "Tracking Presets"
preset_subdir = "tracking_settings"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "clip.tracking_settings_preset_add"
class CLIP_MT_track_color_specials(Menu):
@@ -1544,9 +1530,9 @@ classes = (
CLIP_MT_select,
CLIP_MT_select_grouped,
CLIP_MT_tracking_specials,
- CLIP_MT_camera_presets,
- CLIP_MT_track_color_presets,
- CLIP_MT_tracking_settings_presets,
+ CLIP_PT_camera_presets,
+ CLIP_PT_track_color_presets,
+ CLIP_PT_tracking_settings_presets,
CLIP_MT_track_color_specials,
CLIP_MT_stabilize_2d_specials,
CLIP_MT_stabilize_2d_rotation_specials,
diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py
index e6f96d989c7..dd5ab03fcba 100644
--- a/release/scripts/startup/bl_ui/space_console.py
+++ b/release/scripts/startup/bl_ui/space_console.py
@@ -69,9 +69,7 @@ class CONSOLE_MT_console(Menu):
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class CONSOLE_MT_language(Menu):
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 731032bafa8..efd5e195fb8 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -19,11 +19,12 @@
# <pep8 compliant>
import bpy
-from bpy.types import Header, Menu
+from bpy.types import Header, Menu, Panel
+from .space_time import *
#######################################
-# DopeSheet Filtering
+# DopeSheet Filtering - Header Buttons
# used for DopeSheet, NLA, and Graph Editors
def dopesheet_filter(layout, context, genericFiltersOnly=False):
@@ -40,68 +41,153 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
row.prop(dopesheet, "show_only_errors", text="")
if not genericFiltersOnly:
- if bpy.data.groups:
+ if bpy.data.collections:
row = layout.row(align=True)
- row.prop(dopesheet, "show_only_group_objects", text="")
- if dopesheet.show_only_group_objects:
- row.prop(dopesheet, "filter_group", text="")
+ row.prop(dopesheet, "filter_collection", text="")
if not is_nla:
row = layout.row(align=True)
- row.prop(dopesheet, "show_only_matching_fcurves", text="")
- if dopesheet.show_only_matching_fcurves:
- row.prop(dopesheet, "filter_fcurve_name", text="")
- row.prop(dopesheet, "use_multi_word_filter", text="")
+ row.prop(dopesheet, "filter_fcurve_name", text="")
else:
row = layout.row(align=True)
- row.prop(dopesheet, "use_filter_text", text="")
- if dopesheet.use_filter_text:
+ row.prop(dopesheet, "filter_text", text="")
+
+#######################################
+# Dopesheet Filtering Popovers
+
+# Generic Layout - Used as base for filtering popovers used in all animation editors
+# Used for DopeSheet, NLA, and Graph Editors
+
+
+class DopesheetFilterPopoverBase:
+ bl_region_type = 'HEADER'
+ bl_label = "Filters"
+
+ # Generic = Affects all datatypes
+ # XXX: Perhaps we want these to stay in the header instead, for easy/fast access
+ @classmethod
+ def draw_generic_filters(cls, context, layout):
+ dopesheet = context.space_data.dopesheet
+ is_nla = context.area.type == 'NLA_EDITOR'
+
+ col = layout.column(align=True)
+ col.prop(dopesheet, "show_only_selected", icon='NONE')
+ col.prop(dopesheet, "show_hidden", icon='NONE')
+
+ if is_nla:
+ col.prop(dopesheet, "show_missing_nla", icon='NONE')
+ else: # graph and dopesheet editors - F-Curves and drivers only
+ col.prop(dopesheet, "show_only_errors", icon='NONE')
+
+ # Name/Membership Filters
+ # XXX: Perhaps these should just stay in the headers (exclusively)?
+ @classmethod
+ def draw_search_filters(cls, context, layout, generic_filters_only=False):
+ dopesheet = context.space_data.dopesheet
+ is_nla = context.area.type == 'NLA_EDITOR'
+
+ col = layout.column(align=True)
+ col.label("With Name:")
+ if not is_nla:
+ row = col.row(align=True)
+ row.prop(dopesheet, "filter_fcurve_name", text="")
+ else:
+ row = col.row(align=True)
row.prop(dopesheet, "filter_text", text="")
- row.prop(dopesheet, "use_multi_word_filter", text="")
- if not genericFiltersOnly:
- row = layout.row(align=True)
- row.prop(dopesheet, "show_datablock_filters", text="Filters")
-
- if dopesheet.show_datablock_filters:
- row.prop(dopesheet, "show_scenes", text="")
- row.prop(dopesheet, "show_worlds", text="")
- row.prop(dopesheet, "show_nodes", text="")
-
- row.prop(dopesheet, "show_transforms", text="")
-
- if bpy.data.meshes:
- row.prop(dopesheet, "show_meshes", text="")
- if bpy.data.shape_keys:
- row.prop(dopesheet, "show_shapekeys", text="")
- if bpy.data.meshes:
- row.prop(dopesheet, "show_modifiers", text="")
- if bpy.data.materials:
- row.prop(dopesheet, "show_materials", text="")
- if bpy.data.lamps:
- row.prop(dopesheet, "show_lamps", text="")
- if bpy.data.textures:
- row.prop(dopesheet, "show_textures", text="")
- if bpy.data.cameras:
- row.prop(dopesheet, "show_cameras", text="")
- if bpy.data.curves:
- row.prop(dopesheet, "show_curves", text="")
- if bpy.data.metaballs:
- row.prop(dopesheet, "show_metaballs", text="")
- if bpy.data.lattices:
- row.prop(dopesheet, "show_lattices", text="")
- if bpy.data.armatures:
- row.prop(dopesheet, "show_armatures", text="")
- if bpy.data.particles:
- row.prop(dopesheet, "show_particles", text="")
- if bpy.data.speakers:
- row.prop(dopesheet, "show_speakers", text="")
- if bpy.data.linestyles:
- row.prop(dopesheet, "show_linestyles", text="")
- if bpy.data.grease_pencil:
- row.prop(dopesheet, "show_gpencil", text="")
-
- layout.prop(dopesheet, "use_datablock_sort", text="")
+ if (not generic_filters_only) and (bpy.data.collections):
+ col = layout.column(align=True)
+ col.label("In Collection:")
+ col.prop(dopesheet, "filter_collection", text="")
+
+ # Standard = Present in all panels
+ @classmethod
+ def draw_standard_filters(cls, context, layout):
+ dopesheet = context.space_data.dopesheet
+
+ # Object Data Filters
+ layout.label("Include Sub-Object Data:")
+ split = layout.split()
+
+ # TODO: Add per-channel/axis convenience toggles?
+ col = split.column()
+ col.prop(dopesheet, "show_transforms", text="Transforms")
+
+ col = split.column()
+ col.prop(dopesheet, "show_modifiers", text="Modifiers")
+
+ layout.separator()
+
+ # datablock filters
+ layout.label("Include From Types:")
+ flow = layout.grid_flow(row_major=True, columns=2, even_rows=False, align=False)
+
+ flow.prop(dopesheet, "show_scenes", text="Scenes")
+ flow.prop(dopesheet, "show_worlds", text="Worlds")
+ flow.prop(dopesheet, "show_nodes", text="Node Trees")
+
+ if bpy.data.armatures:
+ flow.prop(dopesheet, "show_armatures", text="Armatures")
+ if bpy.data.cameras:
+ flow.prop(dopesheet, "show_cameras", text="Cameras")
+ if bpy.data.grease_pencil:
+ flow.prop(dopesheet, "show_gpencil", text="Grease Pencil Objects")
+ if bpy.data.lights:
+ flow.prop(dopesheet, "show_lights", text="Lights")
+ if bpy.data.materials:
+ flow.prop(dopesheet, "show_materials", text="Materials")
+ if bpy.data.textures:
+ flow.prop(dopesheet, "show_textures", text="Textures")
+ if bpy.data.meshes:
+ flow.prop(dopesheet, "show_meshes", text="Meshes")
+ if bpy.data.shape_keys:
+ flow.prop(dopesheet, "show_shapekeys", text="Shape Keys")
+ if bpy.data.curves:
+ flow.prop(dopesheet, "show_curves", text="Curves")
+ if bpy.data.particles:
+ flow.prop(dopesheet, "show_particles", text="Particles")
+ if bpy.data.lattices:
+ flow.prop(dopesheet, "show_lattices", text="Lattices")
+ if bpy.data.linestyles:
+ flow.prop(dopesheet, "show_linestyles", text="Line Styles")
+ if bpy.data.metaballs:
+ flow.prop(dopesheet, "show_metaballs", text="Metas")
+ if bpy.data.speakers:
+ flow.prop(dopesheet, "show_speakers", text="Speakers")
+
+ layout.separator()
+
+ # performance-related options (users will mostly have these enabled)
+ col = layout.column(align=True)
+ col.label("Options:")
+ col.prop(dopesheet, "use_datablock_sort", icon='NONE')
+
+
+# Popover for Dopesheet Editor(s) - Dopesheet, Action, Shapekey, GPencil, Mask, etc.
+class DOPESHEET_PT_filters(DopesheetFilterPopoverBase, Panel):
+ bl_space_type = 'DOPESHEET_EDITOR'
+ bl_region_type = 'HEADER'
+ bl_label = "Filters"
+
+ def draw(self, context):
+ layout = self.layout
+
+ dopesheet = context.space_data.dopesheet
+ ds_mode = context.space_data.mode
+
+ layout.prop(dopesheet, "show_summary", text="Summary")
+
+ DopesheetFilterPopoverBase.draw_generic_filters(context, layout)
+
+ if ds_mode in {'DOPESHEET', 'ACTION', 'GPENCIL'}:
+ layout.separator()
+ generic_filters_only = ds_mode != 'DOPESHEET'
+ DopesheetFilterPopoverBase.draw_search_filters(context, layout,
+ generic_filters_only=generic_filters_only)
+
+ if ds_mode == 'DOPESHEET':
+ layout.separator()
+ DopesheetFilterPopoverBase.draw_standard_filters(context, layout)
#######################################
@@ -114,27 +200,49 @@ class DOPESHEET_HT_header(Header):
layout = self.layout
st = context.space_data
- toolsettings = context.tool_settings
row = layout.row(align=True)
row.template_header()
- DOPESHEET_MT_editor_menus.draw_collapsible(context, layout)
+ if st.mode == 'TIMELINE':
+ TIME_MT_editor_menus.draw_collapsible(context, layout)
+ TIME_HT_editor_buttons.draw_header(context, layout)
+ else:
+ layout.prop(st, "ui_mode", text="")
- layout.prop(st, "mode", text="")
+ DOPESHEET_MT_editor_menus.draw_collapsible(context, layout)
+ DOPESHEET_HT_editor_buttons.draw_header(context, layout)
+
+
+# Header for "normal" dopesheet editor modes (e.g. Dope Sheet, Action, Shape Keys, etc.)
+class DOPESHEET_HT_editor_buttons(Header):
+ bl_idname = "DOPESHEET_HT_editor_buttons"
+ bl_space_type = 'DOPESHEET_EDITOR'
+ bl_label = ""
+
+ def draw(self, context):
+ pass
+
+ @staticmethod
+ def draw_header(context, layout):
+ st = context.space_data
+ toolsettings = context.tool_settings
if st.mode in {'ACTION', 'SHAPEKEY'}:
+ # TODO: These buttons need some tidying up - Probably by using a popover, and bypassing the template_id() here
row = layout.row(align=True)
row.operator("action.layer_prev", text="", icon='TRIA_DOWN')
row.operator("action.layer_next", text="", icon='TRIA_UP')
- layout.template_ID(st, "action", new="action.new", unlink="action.unlink")
-
row = layout.row(align=True)
row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN')
row.operator("action.stash", text="Stash", icon='FREEZE')
- layout.prop(st.dopesheet, "show_summary", text="Summary")
+ layout.separator_spacer()
+
+ layout.template_ID(st, "action", new="action.new", unlink="action.unlink")
+
+ layout.separator_spacer()
if st.mode == 'DOPESHEET':
dopesheet_filter(layout, context)
@@ -152,26 +260,28 @@ class DOPESHEET_HT_header(Header):
row.prop(st.dopesheet, "show_hidden", text="")
row = layout.row(align=True)
- row.prop(st.dopesheet, "use_filter_text", text="")
- if st.dopesheet.use_filter_text:
- row.prop(st.dopesheet, "filter_text", text="")
- row.prop(st.dopesheet, "use_multi_word_filter", text="")
+ row.prop(st.dopesheet, "filter_text", text="")
- row = layout.row(align=True)
- row.prop(toolsettings, "use_proportional_action",
- text="", icon_only=True)
- if toolsettings.use_proportional_action:
- row.prop(toolsettings, "proportional_edit_falloff",
- text="", icon_only=True)
+ layout.popover(
+ panel="DOPESHEET_PT_filters",
+ text="",
+ icon='FILTER',
+ )
# Grease Pencil mode doesn't need snapping, as it's frame-aligned only
if st.mode != 'GPENCIL':
layout.prop(st, "auto_snap", text="")
row = layout.row(align=True)
+ row.prop(toolsettings, "use_proportional_action", text="", icon_only=True)
+ sub = row.row(align=True)
+ sub.active = toolsettings.use_proportional_action
+ sub.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
+
+ row = layout.row(align=True)
row.operator("action.copy", text="", icon='COPYDOWN')
row.operator("action.paste", text="", icon='PASTEDOWN')
- if st.mode not in ('GPENCIL', 'MASK'):
+ if st.mode not in {'GPENCIL', 'MASK'}:
row.operator("action.paste", text="", icon='PASTEFLIPDOWN').flipped = True
@@ -212,6 +322,10 @@ class DOPESHEET_MT_view(Menu):
layout.operator("action.properties", icon='MENU_PANEL')
layout.separator()
+ layout.prop(st.dopesheet, "use_multi_word_filter", text="Multi-word Match Search")
+
+ layout.separator()
+
layout.prop(st, "use_realtime_update")
layout.prop(st, "show_frame_indicator")
layout.prop(st, "show_sliders")
@@ -233,9 +347,7 @@ class DOPESHEET_MT_view(Menu):
layout.operator("action.view_frame")
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class DOPESHEET_MT_select(Menu):
@@ -244,9 +356,9 @@ class DOPESHEET_MT_select(Menu):
def draw(self, context):
layout = self.layout
- # This is a bit misleading as the operator's default text is "Select All" while it actually *toggles* All/None
- layout.operator("action.select_all_toggle").invert = False
- layout.operator("action.select_all_toggle", text="Invert Selection").invert = True
+ layout.operator("action.select_all", text="All").action = 'SELECT'
+ layout.operator("action.select_all", text="None").action = 'DESELECT'
+ layout.operator("action.select_all", text="Invert").action = 'INVERT'
layout.separator()
layout.operator("action.select_border").axis_range = False
@@ -449,8 +561,69 @@ class DOPESHEET_MT_delete(Menu):
layout.operator("action.clean", text="Clean Channels").channels = True
+class DOPESHEET_MT_specials(Menu):
+ bl_label = "Dope Sheet Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("action.copy", text="Copy")
+ layout.operator("action.paste", text="Paste")
+ layout.operator("action.paste", text="Paste Flipped").flipped = True
+
+ layout.separator()
+
+ layout.operator_menu_enum("action.handle_type", "type", text="Handle Type")
+ layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode")
+ layout.operator_menu_enum("action.easing_type", "type", text="Easing Type")
+
+ layout.separator()
+
+ layout.operator("action.keyframe_insert").type = 'SEL'
+ layout.operator("action.duplicate_move")
+ layout.operator("action.delete")
+
+ layout.separator()
+
+ layout.operator_menu_enum("action.mirror", "type", text="Mirror")
+ layout.operator_menu_enum("action.snap", "type", text="Snap")
+
+
+class DOPESHEET_MT_channel_specials(Menu):
+ bl_label = "Dope Sheet Channel Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE'
+ layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE'
+ layout.separator()
+ layout.operator("anim.channels_setting_enable", text="Protect Channels").type = 'PROTECT'
+ layout.operator("anim.channels_setting_disable", text="Unprotect Channels").type = 'PROTECT'
+
+ layout.separator()
+ layout.operator("anim.channels_group")
+ layout.operator("anim.channels_ungroup")
+
+ layout.separator()
+ layout.operator("anim.channels_editable_toggle")
+ layout.operator_menu_enum("action.extrapolation_type", "type", text="Extrapolation Mode")
+
+ layout.separator()
+ layout.operator("anim.channels_expand")
+ layout.operator("anim.channels_collapse")
+
+ layout.separator()
+ layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
+
+ layout.separator()
+
+ layout.operator("anim.channels_delete")
+
+
classes = (
DOPESHEET_HT_header,
+ DOPESHEET_HT_editor_buttons,
DOPESHEET_MT_editor_menus,
DOPESHEET_MT_view,
DOPESHEET_MT_select,
@@ -461,6 +634,9 @@ classes = (
DOPESHEET_MT_gpencil_channel,
DOPESHEET_MT_gpencil_frame,
DOPESHEET_MT_delete,
+ DOPESHEET_MT_specials,
+ DOPESHEET_MT_channel_specials,
+ DOPESHEET_PT_filters,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index 2d45d11b423..9d903829bbb 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Header, Panel, Menu
+from bpy.types import Header, Panel, Menu, UIList
class FILEBROWSER_HT_header(Header):
@@ -33,8 +33,7 @@ class FILEBROWSER_HT_header(Header):
if st.active_operator is None:
layout.template_header()
- row = layout.row()
- row.separator()
+ layout.menu("FILEBROWSER_MT_view")
row = layout.row(align=True)
row.operator("file.previous", text="", icon='BACK')
@@ -42,10 +41,8 @@ class FILEBROWSER_HT_header(Header):
row.operator("file.parent", text="", icon='FILE_PARENT')
row.operator("file.refresh", text="", icon='FILE_REFRESH')
- layout.separator()
layout.operator_context = 'EXEC_DEFAULT'
layout.operator("file.directory_new", icon='NEWFOLDER', text="")
- layout.separator()
layout.operator_context = 'INVOKE_DEFAULT'
@@ -53,20 +50,17 @@ class FILEBROWSER_HT_header(Header):
if params:
is_lib_browser = params.use_library_browsing
- layout.prop(params, "recursion_level", text="")
-
layout.prop(params, "display_type", expand=True, text="")
-
- layout.prop(params, "display_size", text="")
-
layout.prop(params, "sort_method", expand=True, text="")
-
layout.prop(params, "show_hidden", text="", icon='FILE_HIDDEN')
+
+ layout.separator_spacer()
+
+ if params:
layout.prop(params, "use_filter", text="", icon='FILTER')
row = layout.row(align=True)
row.active = params.use_filter
-
row.prop(params, "use_filter_folder", text="")
if params.filter_glob:
@@ -95,7 +89,7 @@ class FILEBROWSER_HT_header(Header):
layout.template_running_jobs()
-class FILEBROWSER_UL_dir(bpy.types.UIList):
+class FILEBROWSER_UL_dir(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
direntry = item
# space = context.space_data
@@ -248,6 +242,22 @@ class FILEBROWSER_PT_advanced_filter(Panel):
col.prop(params, "filter_id")
+class FILEBROWSER_MT_view(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+ st = context.space_data
+ params = st.params
+
+ layout.prop_menu_enum(params, "display_size")
+ layout.prop_menu_enum(params, "recursion_level")
+
+ layout.separator()
+
+ layout.menu("INFO_MT_area")
+
+
classes = (
FILEBROWSER_HT_header,
FILEBROWSER_UL_dir,
@@ -257,6 +267,7 @@ classes = (
FILEBROWSER_PT_bookmarks,
FILEBROWSER_PT_recent_folders,
FILEBROWSER_PT_advanced_filter,
+ FILEBROWSER_MT_view,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 5ed58a57e47..eacfb364130 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -19,15 +19,17 @@
# <pep8 compliant>
import bpy
-from bpy.types import Header, Menu
+from bpy.types import Header, Menu, Panel
+from .space_dopesheet import (
+ DopesheetFilterPopoverBase,
+ dopesheet_filter,
+)
class GRAPH_HT_header(Header):
bl_space_type = 'GRAPH_EDITOR'
def draw(self, context):
- from .space_dopesheet import dopesheet_filter
-
layout = self.layout
toolsettings = context.tool_settings
@@ -36,11 +38,10 @@ class GRAPH_HT_header(Header):
row = layout.row(align=True)
row.template_header()
- GRAPH_MT_editor_menus.draw_collapsible(context, layout)
-
- layout.prop(st, "mode", text="")
+ # Now a exposed as a sub-space type
+ # layout.prop(st, "mode", text="")
- dopesheet_filter(layout, context)
+ GRAPH_MT_editor_menus.draw_collapsible(context, layout)
row = layout.row(align=True)
row.prop(st, "use_normalization", icon='NORMALIZE_FCURVES', text="Normalize", toggle=True)
@@ -48,15 +49,30 @@ class GRAPH_HT_header(Header):
sub.active = st.use_normalization
sub.prop(st, "use_auto_normalization", icon='FILE_REFRESH', text="", toggle=True)
+ layout.separator_spacer()
+
+ dopesheet_filter(layout, context)
+
row = layout.row(align=True)
+ if st.has_ghost_curves:
+ row.operator("graph.ghost_curves_clear", text="", icon='GHOST_DISABLED')
+ else:
+ row.operator("graph.ghost_curves_create", text="", icon='GHOST_ENABLED')
- row.prop(toolsettings, "use_proportional_fcurve",
- text="", icon_only=True)
- if toolsettings.use_proportional_fcurve:
- row.prop(toolsettings, "proportional_edit_falloff",
- text="", icon_only=True)
+ layout.popover(
+ panel="GRAPH_PT_filters",
+ text="",
+ icon='FILTER',
+ )
layout.prop(st, "auto_snap", text="")
+
+ row = layout.row(align=True)
+ row.prop(toolsettings, "use_proportional_fcurve", text="", icon_only=True)
+ sub = row.row(align=True)
+ sub.active = toolsettings.use_proportional_fcurve
+ sub.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
+
layout.prop(st, "pivot_point", icon_only=True)
row = layout.row(align=True)
@@ -64,11 +80,20 @@ class GRAPH_HT_header(Header):
row.operator("graph.paste", text="", icon='PASTEDOWN')
row.operator("graph.paste", text="", icon='PASTEFLIPDOWN').flipped = True
- row = layout.row(align=True)
- if st.has_ghost_curves:
- row.operator("graph.ghost_curves_clear", text="", icon='GHOST_DISABLED')
- else:
- row.operator("graph.ghost_curves_create", text="", icon='GHOST_ENABLED')
+
+class GRAPH_PT_filters(DopesheetFilterPopoverBase, Panel):
+ bl_space_type = 'GRAPH_EDITOR'
+ bl_region_type = 'HEADER'
+ bl_label = "Filters"
+
+ def draw(self, context):
+ layout = self.layout
+
+ DopesheetFilterPopoverBase.draw_generic_filters(context, layout)
+ layout.separator()
+ DopesheetFilterPopoverBase.draw_search_filters(context, layout)
+ layout.separator()
+ DopesheetFilterPopoverBase.draw_standard_filters(context, layout)
class GRAPH_MT_editor_menus(Menu):
@@ -129,9 +154,7 @@ class GRAPH_MT_view(Menu):
layout.operator("graph.view_frame")
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class GRAPH_MT_select(Menu):
@@ -140,11 +163,12 @@ class GRAPH_MT_select(Menu):
def draw(self, context):
layout = self.layout
- # This is a bit misleading as the operator's default text is "Select All" while it actually *toggles* All/None
- layout.operator("graph.select_all_toggle").invert = False
- layout.operator("graph.select_all_toggle", text="Invert Selection").invert = True
+ layout.operator("graph.select_all", text="All").action = 'SELECT'
+ layout.operator("graph.select_all", text="None").action = 'DESELECT'
+ layout.operator("graph.select_all", text="Invert").action = 'INVERT'
layout.separator()
+
props = layout.operator("graph.select_border")
props.axis_range = False
props.include_handles = False
@@ -302,6 +326,75 @@ class GRAPH_MT_delete(Menu):
layout.operator("graph.clean", text="Clean Channels").channels = True
+class GRAPH_MT_specials(Menu):
+ bl_label = "F-Curve Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("graph.copy", text="Copy")
+ layout.operator("graph.paste", text="Paste")
+ layout.operator("graph.paste", text="Paste Flipped").flipped = True
+
+ layout.separator()
+
+ layout.operator_menu_enum("graph.handle_type", "type", text="Handle Type")
+ layout.operator_menu_enum("graph.interpolation_type", "type", text="Interpolation Mode")
+ layout.operator_menu_enum("graph.easing_type", "type", text="Easing Type")
+
+ layout.separator()
+
+ layout.operator("graph.keyframe_insert").type = 'SEL'
+ layout.operator("graph.duplicate_move")
+ layout.operator("graph.delete")
+
+ layout.separator()
+
+ layout.operator_menu_enum("graph.mirror", "type", text="Mirror")
+ layout.operator_menu_enum("graph.snap", "type", text="Snap")
+
+
+class GRAPH_MT_channel_specials(Menu):
+ bl_label = "F-Curve Channel Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+ st = context.space_data
+
+ layout.separator()
+ layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE'
+ layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE'
+ layout.separator()
+ layout.operator("anim.channels_setting_enable", text="Protect Channels").type = 'PROTECT'
+ layout.operator("anim.channels_setting_disable", text="Unprotect Channels").type = 'PROTECT'
+
+ layout.separator()
+ layout.operator("anim.channels_group")
+ layout.operator("anim.channels_ungroup")
+
+ layout.separator()
+ layout.operator("anim.channels_editable_toggle")
+ layout.operator_menu_enum("graph.extrapolation_type", "type", text="Extrapolation Mode")
+
+ layout.separator()
+ layout.operator("graph.hide", text="Hide Selected Curves").unselected = False
+ layout.operator("graph.hide", text="Hide Unselected Curves").unselected = True
+ layout.operator("graph.reveal")
+
+ layout.separator()
+ layout.operator("anim.channels_expand")
+ layout.operator("anim.channels_collapse")
+
+ layout.separator()
+ layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
+
+ layout.separator()
+
+ layout.operator("anim.channels_delete")
+ if st.mode == 'DRIVERS':
+ layout.operator("graph.driver_delete_invalid")
+
+
classes = (
GRAPH_HT_header,
GRAPH_MT_editor_menus,
@@ -312,6 +405,9 @@ classes = (
GRAPH_MT_key,
GRAPH_MT_key_transform,
GRAPH_MT_delete,
+ GRAPH_MT_specials,
+ GRAPH_MT_channel_specials,
+ GRAPH_PT_filters,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 9a2215969cf..1303e46ab6c 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -19,7 +19,7 @@
# <pep8 compliant>
import bpy
import math
-from bpy.types import Header, Menu, Panel
+from bpy.types import Header, Menu, Panel, UIList
from .properties_paint_common import (
UnifiedPaintPanel,
brush_texture_settings,
@@ -130,9 +130,7 @@ class IMAGE_MT_view(Menu):
layout.operator("image.cycle_render_slot", text="Render Slot Cycle Previous").reverse = True
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class IMAGE_MT_select(Menu):
@@ -141,14 +139,20 @@ class IMAGE_MT_select(Menu):
def draw(self, context):
layout = self.layout
+ layout.operator("uv.select_all", text="All").action = 'SELECT'
+ layout.operator("uv.select_all", text="None").action = 'DESELECT'
+ layout.operator("uv.select_all", text="Invert").action = 'INVERT'
+
+ layout.separator()
+
layout.operator("uv.select_border").pinned = False
layout.operator("uv.select_border", text="Border Select Pinned").pinned = True
layout.operator("uv.circle_select")
layout.separator()
- layout.operator("uv.select_all").action = 'TOGGLE'
- layout.operator("uv.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("uv.select_less", text="Less")
+ layout.operator("uv.select_more", text="More")
layout.separator()
@@ -157,11 +161,6 @@ class IMAGE_MT_select(Menu):
layout.separator()
- layout.operator("uv.select_less", text="Less")
- layout.operator("uv.select_more", text="More")
-
- layout.separator()
-
layout.operator("uv.select_split")
@@ -192,30 +191,33 @@ class IMAGE_MT_image(Menu):
sima = context.space_data
ima = sima.image
-
- layout.operator("image.new")
- layout.operator("image.open")
-
show_render = sima.show_render
- layout.operator("image.read_renderlayers")
+ layout.operator("image.new", text="New")
+ layout.operator("image.open", text="Open...")
- layout.operator("image.save_dirty", text="Save All Images")
+ layout.operator("image.read_viewlayers")
if ima:
if not show_render:
- layout.operator("image.replace")
- layout.operator("image.reload")
+ layout.operator("image.replace", text="Replace...")
+ layout.operator("image.reload", text="Reload")
- layout.operator("image.save")
- layout.operator("image.save_as")
- layout.operator("image.save_as", text="Save a Copy").copy = True
+ layout.operator("image.external_edit", "Edit Externally")
- if ima.source == 'SEQUENCE':
- layout.operator("image.save_sequence")
+ layout.separator()
- layout.operator("image.external_edit", "Edit Externally")
+ if ima:
+ layout.operator("image.save", text="Save")
+ layout.operator("image.save_as", text="Save As...")
+ layout.operator("image.save_as", text="Save a Copy...").copy = True
+ if ima and ima.source == 'SEQUENCE':
+ layout.operator("image.save_sequence")
+
+ layout.operator("image.save_dirty", text="Save All Images")
+
+ if ima:
layout.separator()
layout.menu("IMAGE_MT_image_invert")
@@ -223,7 +225,7 @@ class IMAGE_MT_image(Menu):
if not show_render:
if not ima.packed_file:
layout.separator()
- layout.operator("image.pack")
+ layout.operator("image.pack", text="Pack")
# only for dirty && specific image types, perhaps
# this could be done in operator poll too
@@ -428,6 +430,43 @@ class IMAGE_MT_uvs_select_mode(Menu):
props.data_path = "tool_settings.uv_select_mode"
+class IMAGE_MT_specials(Menu):
+ bl_label = "UV Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ sima = context.space_data
+
+ # UV Edit Mode
+ if sima.show_uvedit:
+ layout.operator("uv.unwrap")
+ layout.operator("uv.follow_active_quads")
+
+ layout.separator()
+
+ layout.operator("uv.pin").clear = False
+ layout.operator("uv.pin", text="Unpin").clear = True
+
+ layout.separator()
+
+ layout.operator("uv.weld")
+ layout.operator("uv.stitch")
+
+ layout.separator()
+
+ layout.operator_enum("uv.align", "axis") # W, 2/3/4
+
+ layout.separator()
+
+ layout.operator("transform.mirror", text="Mirror X").constraint_axis[0] = True
+ layout.operator("transform.mirror", text="Mirror Y").constraint_axis[1] = True
+
+ layout.separator()
+
+ layout.menu("IMAGE_MT_uvs_snap")
+
+
class IMAGE_HT_header(Header):
bl_space_type = 'IMAGE_EDITOR'
@@ -447,20 +486,8 @@ class IMAGE_HT_header(Header):
row = layout.row(align=True)
row.template_header()
- MASK_MT_editor_menus.draw_collapsible(context, layout)
-
- layout.template_ID(sima, "image", new="image.new", open="image.open")
- if not show_render:
- layout.prop(sima, "use_image_pin", text="")
-
layout.prop(sima, "mode", text="")
- if show_maskedit:
- row = layout.row()
- row.template_ID(sima, "mask", new="mask.new")
-
- layout.prop(sima, "pivot_point", icon_only=True)
-
# uv editing
if show_uvedit:
uvedit = sima.uv_editor
@@ -473,19 +500,45 @@ class IMAGE_HT_header(Header):
layout.prop(toolsettings, "uv_select_mode", text="", expand=True)
layout.prop(uvedit, "sticky_select_mode", icon_only=True)
- row = layout.row(align=True)
- row.prop(toolsettings, "proportional_edit", icon_only=True)
- if toolsettings.proportional_edit != 'DISABLED':
- row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+ MASK_MT_editor_menus.draw_collapsible(context, layout)
+
+ layout.separator_spacer()
+
+ layout.template_ID(sima, "image", new="image.new", open="image.open")
+
+ if show_maskedit:
+ row = layout.row()
+ row.template_ID(sima, "mask", new="mask.new")
+ layout.separator_spacer()
+
+ if show_uvedit or show_maskedit or mode == 'PAINT':
+ layout.prop(sima, "use_realtime_update", icon_only=True, icon='FILE_REFRESH')
+
+ if not show_render:
+ layout.prop(sima, "use_image_pin", text="")
+
+ if show_uvedit:
+ uvedit = sima.uv_editor
+
+ mesh = context.edit_object.data
+ layout.prop_search(mesh.uv_layers, "active", mesh, "uv_layers", text="")
+
+ # Snap
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
row.prop(toolsettings, "snap_uv_element", icon_only=True)
if toolsettings.snap_uv_element != 'INCREMENT':
row.prop(toolsettings, "snap_target", text="")
- mesh = context.edit_object.data
- layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="")
+ row = layout.row(align=True)
+ row.prop(toolsettings, "proportional_edit", icon_only=True)
+ # if toolsettings.proportional_edit != 'DISABLED':
+ sub = row.row(align=True)
+ sub.active = toolsettings.proportional_edit != 'DISABLED'
+ sub.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+
+ layout.prop(sima, "pivot_point", icon_only=True)
if ima:
if ima.is_stereo_3d:
@@ -505,9 +558,6 @@ class IMAGE_HT_header(Header):
if ima.type == 'COMPOSITE' and ima.source in {'MOVIE', 'SEQUENCE'}:
row.operator("image.play_composite", icon='PLAY')
- if show_uvedit or show_maskedit or mode == 'PAINT':
- layout.prop(sima, "use_realtime_update", icon_only=True, icon='LOCKED')
-
class MASK_MT_editor_menus(Menu):
bl_idname = "MASK_MT_editor_menus"
@@ -619,50 +669,6 @@ class IMAGE_PT_image_properties(Panel):
layout.template_image(sima, "image", iuser, multiview=True)
-class IMAGE_PT_game_properties(Panel):
- bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'UI'
- bl_label = "Game Properties"
-
- @classmethod
- def poll(cls, context):
- sima = context.space_data
- # display even when not in game mode because these settings effect the 3d view
- return (sima and sima.image and not sima.show_maskedit) # and (rd.engine == 'BLENDER_GAME')
-
- def draw(self, context):
- layout = self.layout
-
- sima = context.space_data
- ima = sima.image
-
- split = layout.split()
- col = split.column()
- col.prop(ima, "use_animation")
- sub = col.column(align=True)
- sub.active = ima.use_animation
- sub.prop(ima, "frame_start", text="Start")
- sub.prop(ima, "frame_end", text="End")
- sub.prop(ima, "fps", text="Speed")
-
- col = split.column()
- col.prop(ima, "use_tiles")
- sub = col.column(align=True)
- sub.active = ima.use_tiles or ima.use_animation
- sub.prop(ima, "tiles_x", text="X")
- sub.prop(ima, "tiles_y", text="Y")
-
- split = layout.split()
- col = split.column()
- col.label(text="Clamp:")
- col.prop(ima, "use_clamp_x", text="X")
- col.prop(ima, "use_clamp_y", text="Y")
-
- col = split.column()
- col.label(text="Mapping:")
- col.prop(ima, "mapping", expand=True)
-
-
class IMAGE_PT_view_properties(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
@@ -694,11 +700,11 @@ class IMAGE_PT_view_properties(Panel):
col.label(text="Coordinates:")
col.prop(sima, "show_repeat", text="Repeat")
if show_uvedit:
- col.prop(uvedit, "show_normalized_coords", text="Normalized")
+ col.prop(uvedit, "show_pixel_coords", text="Pixel")
elif show_uvedit:
col.label(text="Coordinates:")
- col.prop(uvedit, "show_normalized_coords", text="Normalized")
+ col.prop(uvedit, "show_pixel_coords", text="Pixel")
if show_uvedit or show_maskedit:
col = layout.column()
@@ -730,10 +736,41 @@ class IMAGE_PT_view_properties(Panel):
row.active = uvedit.show_other_objects
row.prop(uvedit, "other_uv_filter", text="Filter")
- if show_render and ima:
- layout.separator()
- render_slot = ima.render_slots.active
- layout.prop(render_slot, "name", text="Slot Name")
+
+class IMAGE_UL_render_slots(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ slot = item
+ layout.prop(slot, "name", text="", emboss=False)
+
+
+class IMAGE_PT_render_slots(Panel):
+ bl_space_type = 'IMAGE_EDITOR'
+ bl_region_type = 'UI'
+ bl_label = "Render Slots"
+
+ @classmethod
+ def poll(cls, context):
+ sima = context.space_data
+ return (sima and sima.image and sima.show_render)
+
+ def draw(self, context):
+ layout = self.layout
+
+ sima = context.space_data
+ ima = sima.image
+
+ row = layout.row()
+
+ col = row.column()
+ col.template_list("IMAGE_UL_render_slots", "render_slots", ima, "render_slots", ima.render_slots, "active_index", rows=3)
+
+ col = row.column(align=True)
+ col.operator("image.add_render_slot", icon='ZOOMIN', text="")
+ col.operator("image.remove_render_slot", icon='ZOOMOUT', text="")
+
+ col.separator()
+
+ col.operator("image.clear_render_slot", icon='X', text="")
class IMAGE_PT_tools_transform_uvs(Panel, UVToolsPanel):
@@ -1357,6 +1394,7 @@ classes = (
IMAGE_MT_uvs_mirror,
IMAGE_MT_uvs_weldalign,
IMAGE_MT_uvs_select_mode,
+ IMAGE_MT_specials,
IMAGE_HT_header,
MASK_MT_editor_menus,
IMAGE_PT_mask,
@@ -1366,7 +1404,8 @@ classes = (
IMAGE_PT_active_mask_spline,
IMAGE_PT_active_mask_point,
IMAGE_PT_image_properties,
- IMAGE_PT_game_properties,
+ IMAGE_UL_render_slots,
+ IMAGE_PT_render_slots,
IMAGE_PT_view_properties,
IMAGE_PT_tools_transform_uvs,
IMAGE_PT_tools_align_uvs,
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index edae5e2f452..e5ef5f9a0da 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -26,346 +26,29 @@ class INFO_HT_header(Header):
def draw(self, context):
layout = self.layout
+ layout.template_header()
- window = context.window
- scene = context.scene
- rd = scene.render
+ # Empty for now until info editor gets turned into log editor
+ pass
- row = layout.row(align=True)
- row.template_header()
- INFO_MT_editor_menus.draw_collapsible(context, layout)
-
- if window.screen.show_fullscreen:
- layout.operator("screen.back_to_previous", icon='SCREEN_BACK', text="Back to Previous")
- layout.separator()
- else:
- layout.template_ID(context.window, "screen", new="screen.new", unlink="screen.delete")
- layout.template_ID(context.screen, "scene", new="scene.new", unlink="scene.delete")
-
- layout.separator()
-
- if rd.has_multiple_engines:
- layout.prop(rd, "engine", text="")
-
- layout.separator()
-
- layout.template_running_jobs()
-
- layout.template_reports_banner()
-
- row = layout.row(align=True)
-
- if bpy.app.autoexec_fail is True and bpy.app.autoexec_fail_quiet is False:
- row.label("Auto-run disabled", icon='ERROR')
- if bpy.data.is_saved:
- props = row.operator("wm.revert_mainfile", icon='SCREEN_BACK', text="Reload Trusted")
- props.use_scripts = True
-
- row.operator("script.autoexec_warn_clear", text="Ignore")
-
- # include last so text doesn't push buttons out of the header
- row.label(bpy.app.autoexec_fail_message)
- return
-
- row.operator("wm.splash", text="", icon='BLENDER', emboss=False)
- row.label(text=scene.statistics(), translate=False)
-
-
-class INFO_MT_editor_menus(Menu):
- bl_idname = "INFO_MT_editor_menus"
- bl_label = ""
-
- def draw(self, context):
- self.draw_menus(self.layout, context)
-
- @staticmethod
- def draw_menus(layout, context):
- scene = context.scene
- rd = scene.render
-
- layout.menu("INFO_MT_file")
-
- if rd.use_game_engine:
- layout.menu("INFO_MT_game")
- else:
- layout.menu("INFO_MT_render")
-
- layout.menu("INFO_MT_window")
- layout.menu("INFO_MT_help")
-
-
-class INFO_MT_file(Menu):
- bl_label = "File"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.read_homefile", text="New", icon='NEW')
- layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
- layout.menu("INFO_MT_file_open_recent", icon='OPEN_RECENT')
- layout.operator("wm.revert_mainfile", icon='FILE_REFRESH')
- layout.operator("wm.recover_last_session", icon='RECOVER_LAST')
- layout.operator("wm.recover_auto_save", text="Recover Auto Save...", icon='RECOVER_AUTO')
-
- layout.separator()
-
- layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA'
- layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK')
-
- layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.save_as_mainfile", text="Save As...", icon='SAVE_AS')
- layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.save_as_mainfile", text="Save Copy...", icon='SAVE_COPY').copy = True
-
- layout.separator()
-
- layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES')
-
- layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.save_homefile", icon='SAVE_PREFS')
- layout.operator("wm.read_factory_settings", icon='LOAD_FACTORY')
-
- if any(bpy.utils.app_template_paths()):
- app_template = context.user_preferences.app_template
- if app_template:
- layout.operator(
- "wm.read_factory_settings",
- text="Load Factory Template Settings",
- icon='LOAD_FACTORY',
- ).app_template = app_template
- del app_template
-
- layout.menu("USERPREF_MT_app_templates", icon='FILE_BLEND')
-
- layout.separator()
-
- layout.operator_context = 'INVOKE_AREA'
- layout.operator("wm.link", text="Link", icon='LINK_BLEND')
- layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
- layout.menu("INFO_MT_file_previews")
-
- layout.separator()
-
- layout.menu("INFO_MT_file_import", icon='IMPORT')
- layout.menu("INFO_MT_file_export", icon='EXPORT')
-
- layout.separator()
-
- layout.menu("INFO_MT_file_external_data", icon='EXTERNAL_DATA')
- layout.operator("wm.blend_strings_utf8_validate", icon='FILE_BLEND')
-
- layout.separator()
-
- layout.operator_context = 'EXEC_AREA'
- if bpy.data.is_dirty and context.user_preferences.view.use_quit_dialog:
- layout.operator_context = 'INVOKE_SCREEN' # quit dialog
- layout.operator("wm.quit_blender", text="Quit", icon='QUIT')
-
-
-class INFO_MT_file_import(Menu):
- bl_idname = "INFO_MT_file_import"
- bl_label = "Import"
-
- def draw(self, context):
- if bpy.app.build_options.collada:
- self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)")
- if bpy.app.build_options.alembic:
- self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
-
-
-class INFO_MT_file_export(Menu):
- bl_idname = "INFO_MT_file_export"
- bl_label = "Export"
-
- def draw(self, context):
- if bpy.app.build_options.collada:
- self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)")
- if bpy.app.build_options.alembic:
- self.layout.operator("wm.alembic_export", text="Alembic (.abc)")
-
-
-class INFO_MT_file_external_data(Menu):
- bl_label = "External Data"
+# Not really info, just add to re-usable location.
+class INFO_MT_area(Menu):
+ bl_label = "Area"
def draw(self, context):
layout = self.layout
- icon = 'CHECKBOX_HLT' if bpy.data.use_autopack else 'CHECKBOX_DEHLT'
- layout.operator("file.autopack_toggle", icon=icon)
-
- layout.separator()
-
- pack_all = layout.row()
- pack_all.operator("file.pack_all")
- pack_all.active = not bpy.data.use_autopack
-
- unpack_all = layout.row()
- unpack_all.operator("file.unpack_all")
- unpack_all.active = not bpy.data.use_autopack
-
- layout.separator()
-
- layout.operator("file.make_paths_relative")
- layout.operator("file.make_paths_absolute")
- layout.operator("file.report_missing_files")
- layout.operator("file.find_missing_files")
-
-
-class INFO_MT_file_previews(Menu):
- bl_label = "Data Previews"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("wm.previews_ensure")
- layout.operator("wm.previews_batch_generate")
-
- layout.separator()
-
- layout.operator("wm.previews_clear")
- layout.operator("wm.previews_batch_clear")
-
-
-class INFO_MT_game(Menu):
- bl_label = "Game"
-
- def draw(self, context):
- layout = self.layout
-
- gs = context.scene.game_settings
-
- layout.operator("view3d.game_start")
-
- layout.separator()
-
- layout.prop(gs, "show_debug_properties")
- layout.prop(gs, "show_framerate_profile")
- layout.prop(gs, "show_physics_visualization")
- layout.prop(gs, "use_deprecation_warnings")
- layout.prop(gs, "use_animation_record")
- layout.separator()
- layout.prop(gs, "use_auto_start")
-
-
-class INFO_MT_render(Menu):
- bl_label = "Render"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("render.render", text="Render Image", icon='RENDER_STILL').use_viewport = True
- props = layout.operator("render.render", text="Render Animation", icon='RENDER_ANIMATION')
- props.animation = True
- props.use_viewport = True
-
- layout.separator()
-
- layout.operator("render.opengl", text="OpenGL Render Image")
- layout.operator("render.opengl", text="OpenGL Render Animation").animation = True
- layout.menu("INFO_MT_opengl_render")
-
- layout.separator()
-
- layout.operator("render.view_show")
- layout.operator("render.play_rendered_anim", icon='PLAY')
-
-
-class INFO_MT_opengl_render(Menu):
- bl_label = "OpenGL Render Options"
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render
- layout.prop(rd, "use_antialiasing")
- layout.prop(rd, "use_full_sample")
-
- layout.prop_menu_enum(rd, "antialiasing_samples")
- layout.prop_menu_enum(rd, "alpha_mode")
-
-
-class INFO_MT_window(Menu):
- bl_label = "Window"
-
- def draw(self, context):
- import sys
-
- layout = self.layout
-
- layout.operator("wm.window_duplicate")
- layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
-
- layout.separator()
-
- layout.operator("screen.screenshot")
-
- if sys.platform[:3] == "win":
- layout.separator()
- layout.operator("wm.console_toggle", icon='CONSOLE')
-
- if context.scene.render.use_multiview:
- layout.separator()
- layout.operator("wm.set_stereo_3d", icon='CAMERA_STEREO')
-
-
-class INFO_MT_help(Menu):
- bl_label = "Help"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator(
- "wm.url_open", text="Manual", icon='HELP',
- ).url = "https://docs.blender.org/manual/en/dev/"
- layout.operator(
- "wm.url_open", text="Release Log", icon='URL',
- ).url = "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/%d.%d" % bpy.app.version[:2]
- layout.separator()
-
- layout.operator(
- "wm.url_open", text="Blender Website", icon='URL',
- ).url = "https://www.blender.org"
- layout.operator(
- "wm.url_open", text="Blender Store", icon='URL',
- ).url = "https://store.blender.org"
- layout.operator(
- "wm.url_open", text="Developer Community", icon='URL',
- ).url = "https://www.blender.org/get-involved/"
- layout.operator(
- "wm.url_open", text="User Community", icon='URL',
- ).url = "https://www.blender.org/support/user-community"
- layout.separator()
- layout.operator(
- "wm.url_open", text="Report a Bug", icon='URL',
- ).url = "https://developer.blender.org/maniphest/task/edit/form/1"
- layout.separator()
-
- layout.operator(
- "wm.url_open", text="Python API Reference", icon='URL',
- ).url = bpy.types.WM_OT_doc_view._prefix
-
- layout.operator("wm.operator_cheat_sheet", icon='TEXT')
- layout.operator("wm.sysinfo", icon='TEXT')
- layout.separator()
-
- layout.operator("wm.splash", icon='BLENDER')
+ layout.operator("screen.area_dupli")
+ if context.space_data.type == 'VIEW_3D':
+ layout.operator("screen.region_quadview")
+ layout.operator("screen.screen_full_area")
+ layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
classes = (
INFO_HT_header,
- INFO_MT_editor_menus,
- INFO_MT_file,
- INFO_MT_file_import,
- INFO_MT_file_export,
- INFO_MT_file_external_data,
- INFO_MT_file_previews,
- INFO_MT_game,
- INFO_MT_render,
- INFO_MT_opengl_render,
- INFO_MT_window,
- INFO_MT_help,
+ INFO_MT_area,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_logic.py b/release/scripts/startup/bl_ui/space_logic.py
deleted file mode 100644
index b552181f491..00000000000
--- a/release/scripts/startup/bl_ui/space_logic.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# ##### 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.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-import bpy
-from bpy.types import Header, Menu, Panel
-
-
-class LOGIC_PT_properties(Panel):
- bl_space_type = 'LOGIC_EDITOR'
- bl_region_type = 'UI'
- bl_label = "Properties"
-
- @classmethod
- def poll(cls, context):
- ob = context.active_object
- return ob and ob.game
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.active_object
- game = ob.game
- is_font = (ob.type == 'FONT')
-
- if is_font:
- prop_index = game.properties.find("Text")
- if prop_index != -1:
- layout.operator("object.game_property_remove", text="Remove Text Game Property", icon='X').index = prop_index
- row = layout.row()
- sub = row.row()
- sub.enabled = 0
- prop = game.properties[prop_index]
- sub.prop(prop, "name", text="")
- row.prop(prop, "type", text="")
- # get the property from the body, not the game property
- # note, don't do this - it's too slow and body can potentially be a really long string.
- #~ row.prop(ob.data, "body", text="")
- row.label("See Text Object")
- else:
- props = layout.operator("object.game_property_new", text="Add Text Game Property", icon='ZOOMIN')
- props.name = "Text"
- props.type = 'STRING'
-
- props = layout.operator("object.game_property_new", text="Add Game Property", icon='ZOOMIN')
- props.name = ""
-
- for i, prop in enumerate(game.properties):
-
- if is_font and i == prop_index:
- continue
-
- box = layout.box()
- row = box.row()
- row.prop(prop, "name", text="")
- row.prop(prop, "type", text="")
- row.prop(prop, "value", text="")
- row.prop(prop, "show_debug", text="", toggle=True, icon='INFO')
- sub = row.row(align=True)
- props = sub.operator("object.game_property_move", text="", icon='TRIA_UP')
- props.index = i
- props.direction = 'UP'
- props = sub.operator("object.game_property_move", text="", icon='TRIA_DOWN')
- props.index = i
- props.direction = 'DOWN'
- row.operator("object.game_property_remove", text="", icon='X', emboss=False).index = i
-
-
-class LOGIC_MT_logicbricks_add(Menu):
- bl_label = "Add"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator_menu_enum("logic.sensor_add", "type", text="Sensor")
- layout.operator_menu_enum("logic.controller_add", "type", text="Controller")
- layout.operator_menu_enum("logic.actuator_add", "type", text="Actuator")
-
-
-class LOGIC_HT_header(Header):
- bl_space_type = 'LOGIC_EDITOR'
-
- def draw(self, context):
- layout = self.layout.row(align=True)
-
- layout.template_header()
-
- LOGIC_MT_editor_menus.draw_collapsible(context, layout)
-
-
-class LOGIC_MT_editor_menus(Menu):
- bl_idname = "LOGIC_MT_editor_menus"
- bl_label = ""
-
- def draw(self, context):
- self.draw_menus(self.layout, context)
-
- @staticmethod
- def draw_menus(layout, context):
- layout.menu("LOGIC_MT_view")
- layout.menu("LOGIC_MT_logicbricks_add")
-
-
-class LOGIC_MT_view(Menu):
- bl_label = "View"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("logic.properties", icon='MENU_PANEL')
-
- layout.separator()
-
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
-
-
-classes = (
- LOGIC_PT_properties,
- LOGIC_MT_logicbricks_add,
- LOGIC_HT_header,
- LOGIC_MT_editor_menus,
- LOGIC_MT_view,
-)
-
-if __name__ == "__main__": # only for live edit.
- from bpy.utils import register_class
- for cls in classes:
- register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index 8a933570c5e..4e20001b133 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -19,15 +19,17 @@
# <pep8 compliant>
import bpy
-from bpy.types import Header, Menu
+from bpy.types import Header, Menu, Panel
+from .space_dopesheet import (
+ DopesheetFilterPopoverBase,
+ dopesheet_filter,
+)
class NLA_HT_header(Header):
bl_space_type = 'NLA_EDITOR'
def draw(self, context):
- from .space_dopesheet import dopesheet_filter
-
layout = self.layout
st = context.space_data
@@ -37,11 +39,34 @@ class NLA_HT_header(Header):
NLA_MT_editor_menus.draw_collapsible(context, layout)
+ layout.separator_spacer()
+
dopesheet_filter(layout, context)
+ layout.popover(
+ panel="NLA_PT_filters",
+ text="",
+ icon='FILTER',
+ )
+
layout.prop(st, "auto_snap", text="")
+class NLA_PT_filters(DopesheetFilterPopoverBase, Panel):
+ bl_space_type = 'NLA_EDITOR'
+ bl_region_type = 'HEADER'
+ bl_label = "Filters"
+
+ def draw(self, context):
+ layout = self.layout
+
+ DopesheetFilterPopoverBase.draw_generic_filters(context, layout)
+ layout.separator()
+ DopesheetFilterPopoverBase.draw_search_filters(context, layout)
+ layout.separator()
+ DopesheetFilterPopoverBase.draw_standard_filters(context, layout)
+
+
class NLA_MT_editor_menus(Menu):
bl_idname = "NLA_MT_editor_menus"
bl_label = ""
@@ -90,9 +115,7 @@ class NLA_MT_view(Menu):
layout.operator("nla.view_frame")
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class NLA_MT_select(Menu):
@@ -101,9 +124,9 @@ class NLA_MT_select(Menu):
def draw(self, context):
layout = self.layout
- # This is a bit misleading as the operator's default text is "Select All" while it actually *toggles* All/None
- layout.operator("nla.select_all_toggle").invert = False
- layout.operator("nla.select_all_toggle", text="Invert Selection").invert = True
+ layout.operator("nla.select_all", text="All").action = 'SELECT'
+ layout.operator("nla.select_all", text="None").action = 'DESELECT'
+ layout.operator("nla.select_all", text="Invert").action = 'INVERT'
layout.separator()
layout.operator("nla.select_border").axis_range = False
@@ -219,6 +242,7 @@ classes = (
NLA_MT_marker,
NLA_MT_add,
NLA_MT_edit_transform,
+ NLA_PT_filters,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index c2735998d2c..9d8c14ba9c3 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -21,6 +21,7 @@ import bpy
import nodeitems_utils
from bpy.types import Header, Menu, Panel
from bpy.app.translations import pgettext_iface as iface_
+from bl_operators.presets import PresetMenu
from .properties_grease_pencil_common import (
GreasePencilDrawingToolsPanel,
GreasePencilStrokeEditPanel,
@@ -48,78 +49,107 @@ class NODE_HT_header(Header):
row = layout.row(align=True)
row.template_header()
- NODE_MT_editor_menus.draw_collapsible(context, layout)
-
- layout.prop(snode, "tree_type", text="", expand=True)
+ # Now expanded via the 'ui_type'
+ # layout.prop(snode, "tree_type", text="")
if snode.tree_type == 'ShaderNodeTree':
- if scene.render.use_shading_nodes:
- layout.prop(snode, "shader_type", text="", expand=True)
+ layout.prop(snode, "shader_type", text="")
ob = context.object
- if (not scene.render.use_shading_nodes or snode.shader_type == 'OBJECT') and ob:
+ if snode.shader_type == 'OBJECT' and ob:
+
+ NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+ # No shader nodes for Eevee lamps
+ if snode_id and not (context.engine == 'BLENDER_EEVEE' and ob.type == 'LIGHT'):
+ row = layout.row()
+ row.prop(snode_id, "use_nodes")
+
+ layout.separator_spacer()
+
row = layout.row()
# disable material slot buttons when pinned, cannot find correct slot within id_from (#36589)
row.enabled = not snode.pin
# Show material.new when no active ID/slot exists
if not id_from and ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'METABALL'}:
row.template_ID(ob, "active_material", new="material.new")
- # Material ID, but not for Lamps
- if id_from and ob.type != 'LAMP':
+ # Material ID, but not for Lights
+ if id_from and ob.type != 'LIGHT':
row.template_ID(id_from, "active_material", new="material.new")
- # Don't show "Use Nodes" Button when Engine is BI for Lamps
- if snode_id and not (scene.render.use_shading_nodes == 0 and ob.type == 'LAMP'):
- layout.prop(snode_id, "use_nodes")
+ if snode.shader_type == 'WORLD':
+ NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+ if snode_id:
+ row = layout.row()
+ row.prop(snode_id, "use_nodes")
+
+ layout.separator_spacer()
- if scene.render.use_shading_nodes and snode.shader_type == 'WORLD':
row = layout.row()
row.enabled = not snode.pin
row.template_ID(scene, "world", new="world.new")
- if snode_id:
- row.prop(snode_id, "use_nodes")
- if scene.render.use_shading_nodes and snode.shader_type == 'LINESTYLE':
- rl = context.scene.render.layers.active
- lineset = rl.freestyle_settings.linesets.active
+ if snode.shader_type == 'LINESTYLE':
+ view_layer = context.view_layer
+ lineset = view_layer.freestyle_settings.linesets.active
+
if lineset is not None:
+ NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+ if snode_id:
+ row = layout.row()
+ row.prop(snode_id, "use_nodes")
+
+ layout.separator_spacer()
+
row = layout.row()
row.enabled = not snode.pin
row.template_ID(lineset, "linestyle", new="scene.freestyle_linestyle_new")
- if snode_id:
- row.prop(snode_id, "use_nodes")
elif snode.tree_type == 'TextureNodeTree':
- layout.prop(snode, "texture_type", text="", expand=True)
+ layout.prop(snode, "texture_type", text="")
+
+ NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+ if snode_id:
+ layout.prop(snode_id, "use_nodes")
+
+ layout.separator_spacer()
if id_from:
if snode.texture_type == 'BRUSH':
layout.template_ID(id_from, "texture", new="texture.new")
else:
layout.template_ID(id_from, "active_texture", new="texture.new")
- if snode_id:
- layout.prop(snode_id, "use_nodes")
elif snode.tree_type == 'CompositorNodeTree':
+
+ NODE_MT_editor_menus.draw_collapsible(context, layout)
+
if snode_id:
layout.prop(snode_id, "use_nodes")
+
+ layout.prop(snode, "use_auto_render")
layout.prop(snode, "show_backdrop")
if snode.show_backdrop:
row = layout.row(align=True)
row.prop(snode, "backdrop_channels", text="", expand=True)
- layout.prop(snode, "use_auto_render")
else:
# Custom node tree is edited as independent ID block
+ NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+ layout.separator_spacer()
+
layout.template_ID(snode, "node_tree", new="node.new_node_tree")
- layout.prop(snode, "pin", text="")
- layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
+ layout.separator_spacer()
- layout.separator()
+ layout.template_running_jobs()
- # Auto-offset nodes (called "insert_offset" in code)
- layout.prop(snode, "use_insert_offset", text="")
+ layout.prop(snode, "pin", text="")
+ layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
# Snap
row = layout.row(align=True)
@@ -132,8 +162,6 @@ class NODE_HT_header(Header):
row.operator("node.clipboard_copy", text="", icon='COPYDOWN')
row.operator("node.clipboard_paste", text="", icon='PASTEDOWN')
- layout.template_running_jobs()
-
class NODE_MT_editor_menus(Menu):
bl_idname = "NODE_MT_editor_menus"
@@ -171,11 +199,18 @@ class NODE_MT_view(Menu):
def draw(self, context):
layout = self.layout
+ snode = context.space_data
+
layout.operator("node.properties", icon='MENU_PANEL')
layout.operator("node.toolbar", icon='MENU_PANEL')
layout.separator()
+ # Auto-offset nodes (called "insert_offset" in code)
+ layout.prop(snode, "use_insert_offset")
+
+ layout.separator()
+
layout.operator("view2d.zoom_in")
layout.operator("view2d.zoom_out")
@@ -194,9 +229,7 @@ class NODE_MT_view(Menu):
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class NODE_MT_select(Menu):
@@ -271,16 +304,16 @@ class NODE_MT_node(Menu):
layout.separator()
- layout.operator("node.read_renderlayers")
+ layout.operator("node.read_viewlayers")
layout.operator("node.read_fullsamplelayers")
-class NODE_MT_node_color_presets(Menu):
+class NODE_PT_node_color_presets(PresetMenu):
"""Predefined node color"""
bl_label = "Color Presets"
preset_subdir = "node_color"
preset_operator = "script.execute_preset"
- draw = Menu.draw_preset
+ preset_add_operator = "node.node_color_preset_add"
class NODE_MT_node_color_specials(Menu):
@@ -292,6 +325,41 @@ class NODE_MT_node_color_specials(Menu):
layout.operator("node.node_copy_color", icon='COPY_ID')
+class NODE_MT_specials(Menu):
+ bl_label = "Node Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_DEFAULT'
+ layout.operator("node.duplicate_move")
+ layout.operator("node.delete")
+ layout.operator_context = 'EXEC_DEFAULT'
+
+ layout.operator("node.delete_reconnect")
+
+ layout.separator()
+
+ layout.operator("node.link_make").replace = False
+ layout.operator("node.link_make", text="Make and Replace Links").replace = True
+ layout.operator("node.links_detach")
+
+ layout.separator()
+
+ layout.operator("node.group_make", text="Group")
+ layout.operator("node.group_ungroup", text="Ungroup")
+ layout.operator("node.group_edit").exit = False
+
+ layout.separator()
+
+ layout.operator("node.hide_toggle")
+ layout.operator("node.mute_toggle")
+ layout.operator("node.preview_toggle")
+ layout.operator("node.hide_socket_toggle")
+ layout.operator("node.options_toggle")
+ layout.operator("node.collapse_hide_unused_toggle")
+
+
class NODE_PT_active_node_generic(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
@@ -324,6 +392,9 @@ class NODE_PT_active_node_color(Panel):
node = context.active_node
self.layout.prop(node, "use_custom_color", text="")
+ def draw_header_preset(self, context):
+ NODE_PT_node_color_presets.draw_panel_header(self.layout)
+
def draw(self, context):
layout = self.layout
node = context.active_node
@@ -331,13 +402,8 @@ class NODE_PT_active_node_color(Panel):
layout.enabled = node.use_custom_color
row = layout.row()
- col = row.column()
- col.menu("NODE_MT_node_color_presets")
- col.prop(node, "color", text="")
- col = row.column(align=True)
- col.operator("node.node_color_preset_add", text="", icon='ZOOMIN').remove_active = False
- col.operator("node.node_color_preset_add", text="", icon='ZOOMOUT').remove_active = True
- col.menu("NODE_MT_node_color_specials", text="", icon='DOWNARROW_HLT')
+ row.prop(node, "color", text="")
+ row.menu("NODE_MT_node_color_specials", text="", icon='DOWNARROW_HLT')
class NODE_PT_active_node_properties(Panel):
@@ -395,8 +461,7 @@ class NODE_PT_backdrop(Panel):
col = layout.column(align=True)
col.label(text="Offset:")
- col.prop(snode, "backdrop_x", text="X")
- col.prop(snode, "backdrop_y", text="Y")
+ col.prop(snode, "backdrop_offset", text="")
col.operator("node.backimage_move", text="Move")
layout.operator("node.backimage_fit", text="Fit")
@@ -537,8 +602,9 @@ classes = (
NODE_MT_view,
NODE_MT_select,
NODE_MT_node,
- NODE_MT_node_color_presets,
+ NODE_PT_node_color_presets,
NODE_MT_node_color_specials,
+ NODE_MT_specials,
NODE_PT_active_node_generic,
NODE_PT_active_node_color,
NODE_PT_active_node_properties,
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 4951ef83ad0..97fae2690fd 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Header, Menu
+from bpy.types import Header, Menu, Panel
class OUTLINER_HT_header(Header):
@@ -28,21 +28,47 @@ class OUTLINER_HT_header(Header):
layout = self.layout
space = context.space_data
+ display_mode = space.display_mode
scene = context.scene
ks = context.scene.keying_sets.active
row = layout.row(align=True)
row.template_header()
- OUTLINER_MT_editor_menus.draw_collapsible(context, layout)
+ layout.prop(space, "display_mode", icon_only=True)
- layout.prop(space, "display_mode", text="")
+ if display_mode == 'DATA_API':
+ OUTLINER_MT_editor_menus.draw_collapsible(context, layout)
- layout.prop(space, "filter_text", icon='VIEWZOOM', text="")
+ layout.separator_spacer()
- layout.separator()
+ row = layout.row(align=True)
+ row.prop(space, "filter_text", icon='VIEWZOOM', text="")
+
+ layout.separator_spacer()
+
+ row = layout.row(align=True)
+ if display_mode in {'VIEW_LAYER'}:
+ row.popover(
+ panel="OUTLINER_PT_filter",
+ text="",
+ icon='FILTER',
+ )
+ elif display_mode in {'LIBRARIES', 'ORPHAN_DATA'}:
+ row.prop(space, "use_filter_id_type", text="", icon='FILTER')
+ sub = row.row(align=True)
+ sub.active = space.use_filter_id_type
+ sub.prop(space, "filter_id_type", text="", icon_only=True)
+
+ if display_mode == 'VIEW_LAYER':
+ layout.operator("outliner.collection_new", text="", icon='GROUP').nested = True
+
+ elif display_mode == 'ORPHAN_DATA':
+ layout.operator("outliner.orphans_purge", text="Purge")
+
+ elif space.display_mode == 'DATA_API':
+ layout.separator()
- if space.display_mode == 'DATABLOCKS':
row = layout.row(align=True)
row.operator("outliner.keyingset_add_selected", icon='ZOOMIN', text="")
row.operator("outliner.keyingset_remove_selected", icon='ZOOMOUT', text="")
@@ -57,8 +83,6 @@ class OUTLINER_HT_header(Header):
else:
row = layout.row()
row.label(text="No Keying Set Active")
- elif space.display_mode == 'ORPHAN_DATA':
- layout.operator("outliner.orphans_purge")
class OUTLINER_MT_editor_menus(Menu):
@@ -72,71 +96,213 @@ class OUTLINER_MT_editor_menus(Menu):
def draw_menus(layout, context):
space = context.space_data
- layout.menu("OUTLINER_MT_view")
- layout.menu("OUTLINER_MT_search")
-
- if space.display_mode == 'DATABLOCKS':
+ if space.display_mode == 'DATA_API':
layout.menu("OUTLINER_MT_edit_datablocks")
-class OUTLINER_MT_view(Menu):
- bl_label = "View"
+class OUTLINER_MT_context(Menu):
+ bl_label = "Outliner"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("outliner.show_one_level", text="Show One Level")
+ layout.operator("outliner.show_one_level", text="Hide One Level").open = False
+ layout.operator("outliner.show_hierarchy")
+
+ layout.separator()
+
+ layout.operator("outliner.show_active")
+
+ layout.separator()
+
+ layout.menu("INFO_MT_area")
+
+
+class OUTLINER_MT_edit_datablocks(Menu):
+ bl_label = "Edit"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("outliner.keyingset_add_selected")
+ layout.operator("outliner.keyingset_remove_selected")
+
+ layout.separator()
+
+ layout.operator("outliner.drivers_add_selected")
+ layout.operator("outliner.drivers_delete_selected")
+
+
+class OUTLINER_MT_collection_view_layer(Menu):
+ bl_label = "View Layer"
def draw(self, context):
layout = self.layout
space = context.space_data
- if space.display_mode not in {'DATABLOCKS', 'USER_PREFERENCES'}:
- layout.prop(space, "use_sort_alpha")
- layout.prop(space, "show_restrict_columns")
+ layout.operator("outliner.collection_exclude_set", text="Exclude")
+ layout.operator("outliner.collection_include_set", text="Include")
+
+
+class OUTLINER_MT_collection(Menu):
+ bl_label = "Collection"
+
+ def draw(self, context):
+ layout = self.layout
+
+ space = context.space_data
+
+ layout.operator("outliner.collection_new", text="New").nested = True
+ layout.operator("outliner.collection_duplicate", text="Duplicate")
+ layout.operator("outliner.collection_delete", text="Delete").hierarchy = False
+ layout.operator("outliner.collection_delete", text="Delete Hierarchy").hierarchy = True
+
+ layout.separator()
+
+ layout.operator("outliner.collection_objects_select", text="Select Objects")
+ layout.operator("outliner.collection_objects_deselect", text="Deselect Objects")
+
+ layout.separator()
+
+ layout.operator("outliner.collection_instance", text="Instance to Scene")
+ if space.display_mode != 'VIEW_LAYER':
+ layout.operator("outliner.collection_link", text="Link to Scene")
+ layout.operator("outliner.id_operation", text="Unlink").type = 'UNLINK'
+
+ if space.display_mode == 'VIEW_LAYER':
layout.separator()
- layout.operator("outliner.show_active")
+ layout.menu("OUTLINER_MT_collection_view_layer")
- layout.operator("outliner.show_one_level", text="Show One Level")
- layout.operator("outliner.show_one_level", text="Hide One Level").open = False
- layout.operator("outliner.show_hierarchy")
+ layout.separator()
+ layout.operator_menu_enum("outliner.id_operation", "type", text="ID Data")
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ OUTLINER_MT_context.draw(self, context)
-class OUTLINER_MT_search(Menu):
- bl_label = "Search"
+class OUTLINER_MT_collection_new(Menu):
+ bl_label = "Collection"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("outliner.collection_new", text="New").nested = False
+
+ layout.separator()
+
+ OUTLINER_MT_context.draw(self, context)
+
+
+class OUTLINER_MT_object(Menu):
+ bl_label = "Object"
def draw(self, context):
layout = self.layout
space = context.space_data
+ obj = context.active_object
+ object_mode = 'OBJECT' if obj is None else obj.mode
- layout.prop(space, "use_filter_case_sensitive")
- layout.prop(space, "use_filter_complete")
+ layout.operator("outliner.object_operation", text="Delete").type = 'DELETE'
+ if space.display_mode == 'VIEW_LAYER' and not space.use_filter_collection:
+ layout.operator("outliner.object_operation", text="Delete Hierarchy").type = 'DELETE_HIERARCHY'
+ layout.separator()
-class OUTLINER_MT_edit_datablocks(Menu):
- bl_label = "Edit"
+ layout.operator("outliner.object_operation", text="Select").type = 'SELECT'
+ layout.operator("outliner.object_operation", text="Select Hierarchy").type = 'SELECT_HIERARCHY'
+ layout.operator("outliner.object_operation", text="Deselect").type = 'DESELECT'
+
+ layout.separator()
+
+ if object_mode in {'EDIT', 'POSE'}:
+ name = bpy.types.Object.bl_rna.properties["mode"].enum_items[object_mode].name
+ layout.operator("outliner.object_operation", text=f"{name} Set").type = 'OBJECT_MODE_ENTER'
+ layout.operator("outliner.object_operation", text=f"{name} Clear").type = 'OBJECT_MODE_EXIT'
+ del name
+
+ layout.separator()
+
+ if not (space.display_mode == 'VIEW_LAYER' and not space.use_filter_collection):
+ layout.operator("outliner.id_operation", text="Unlink").type = 'UNLINK'
+ layout.separator()
+
+ layout.operator_menu_enum("outliner.id_operation", "type", text="ID Data")
+
+ layout.separator()
+
+ OUTLINER_MT_context.draw(self, context)
+
+
+class OUTLINER_PT_filter(Panel):
+ bl_space_type = 'OUTLINER'
+ bl_region_type = 'HEADER'
+ bl_label = "Filter"
def draw(self, context):
layout = self.layout
- layout.operator("outliner.keyingset_add_selected")
- layout.operator("outliner.keyingset_remove_selected")
+ space = context.space_data
+ display_mode = space.display_mode
+
+ layout.prop(space, "use_filter_complete", text="Exact Match Search")
+ layout.prop(space, "use_filter_case_sensitive", text="Case Sensitive Search")
layout.separator()
- layout.operator("outliner.drivers_add_selected")
- layout.operator("outliner.drivers_delete_selected")
+ if space.display_mode != 'DATA_API':
+ layout.prop(space, "use_sort_alpha")
+ layout.prop(space, "show_restrict_columns")
+ layout.separator()
+
+ col = layout.column(align=True)
+
+ col.prop(space, "use_filter_collection", text="Collections", icon='GROUP')
+ col.prop(space, "use_filter_object", text="Objects", icon='OBJECT_DATAMODE')
+
+ sub = col.column(align=True)
+ sub.active = space.use_filter_object
+
+ if bpy.data.meshes:
+ sub.prop(space, "use_filter_object_mesh", text="Meshes", icon='MESH_DATA')
+ if bpy.data.armatures:
+ sub.prop(space, "use_filter_object_armature", text="Armatures", icon='ARMATURE_DATA')
+ if bpy.data.lights:
+ sub.prop(space, "use_filter_object_light", text="Lights", icon='LIGHT_DATA')
+ if bpy.data.cameras:
+ sub.prop(space, "use_filter_object_camera", text="Cameras", icon='CAMERA_DATA')
+
+ sub.prop(space, "use_filter_object_empty", text="Empties", icon='EMPTY_DATA')
+
+ if (
+ bpy.data.curves or
+ bpy.data.metaballs or
+ bpy.data.lightprobes or
+ bpy.data.lattices or
+ bpy.data.fonts or
+ bpy.data.speakers
+ ):
+ sub.prop(space, "use_filter_object_others", text="Others")
+
+ subsub = sub.column(align=False)
+ subsub.prop(space, "filter_state", text="")
+ subsub.prop(space, "use_filter_object_content", text="Object Contents")
+ subsub.prop(space, "use_filter_children", text="Object Children")
classes = (
OUTLINER_HT_header,
OUTLINER_MT_editor_menus,
- OUTLINER_MT_view,
- OUTLINER_MT_search,
OUTLINER_MT_edit_datablocks,
+ OUTLINER_MT_collection,
+ OUTLINER_MT_collection_new,
+ OUTLINER_MT_collection_view_layer,
+ OUTLINER_MT_object,
+ OUTLINER_MT_context,
+ OUTLINER_PT_filter,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_properties.py b/release/scripts/startup/bl_ui/space_properties.py
index 20cb5719e20..2d1725b2087 100644
--- a/release/scripts/startup/bl_ui/space_properties.py
+++ b/release/scripts/startup/bl_ui/space_properties.py
@@ -31,6 +31,7 @@ class PROPERTIES_HT_header(Header):
row = layout.row()
row.template_header()
+
row.prop(view, "context", expand=True, icon_only=True)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index d156f822606..0bdfcc39ed9 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -79,30 +79,29 @@ class SEQUENCER_HT_header(Header):
row = layout.row(align=True)
row.template_header()
+ layout.prop(st, "view_type", text="")
+
SEQUENCER_MT_editor_menus.draw_collapsible(context, layout)
- row = layout.row(align=True)
- row.prop(scene, "use_preview_range", text="", toggle=True)
- row.prop(scene, "lock_frame_selection_to_range", text="", toggle=True)
+ if st.view_type == 'SEQUENCER':
+ layout.prop(st, "show_backdrop", text="Backdrop")
- layout.prop(st, "view_type", expand=True, text="")
+ layout.separator_spacer()
- if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
- layout.prop(st, "display_mode", expand=True, text="")
+ layout.template_running_jobs()
if st.view_type == 'SEQUENCER':
- row = layout.row(align=True)
- row.operator("sequencer.copy", text="", icon='COPYDOWN')
- row.operator("sequencer.paste", text="", icon='PASTEDOWN')
+ layout.separator()
+ layout.operator("sequencer.refresh_all")
+ if st.view_type == 'SEQUENCER_PREVIEW':
layout.separator()
layout.operator("sequencer.refresh_all")
- layout.prop(st, "show_backdrop")
- else:
- if st.view_type == 'SEQUENCER_PREVIEW':
- layout.separator()
- layout.operator("sequencer.refresh_all")
+ if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ layout.prop(st, "display_mode", expand=True, text="")
+
+ if st.view_type != 'SEQUENCER':
layout.prop(st, "preview_channels", expand=True, text="")
layout.prop(st, "display_channel", text="Channel")
@@ -134,7 +133,11 @@ class SEQUENCER_HT_header(Header):
props.animation = True
props.sequencer = True
- layout.template_running_jobs()
+ if st.view_type == 'SEQUENCER':
+
+ row = layout.row(align=True)
+ row.operator("sequencer.copy", text="", icon='COPYDOWN')
+ row.operator("sequencer.paste", text="", icon='PASTEDOWN')
class SEQUENCER_MT_editor_menus(Menu):
@@ -237,9 +240,7 @@ class SEQUENCER_MT_view(Menu):
layout.prop(st, "use_marker_sync")
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class SEQUENCER_MT_select(Menu):
@@ -248,6 +249,12 @@ class SEQUENCER_MT_select(Menu):
def draw(self, context):
layout = self.layout
+ layout.operator("sequencer.select_all", text="All").action = 'SELECT'
+ layout.operator("sequencer.select_all", text="None").action = 'DESELECT'
+ layout.operator("sequencer.select_all", text="Invert").action = 'INVERT'
+
+ layout.separator()
+
layout.operator("sequencer.select_active_side", text="Strips to the Left").side = 'LEFT'
layout.operator("sequencer.select_active_side", text="Strips to the Right").side = 'RIGHT'
props = layout.operator("sequencer.select", text="All Strips to the Left")
@@ -266,8 +273,6 @@ class SEQUENCER_MT_select(Menu):
layout.operator("sequencer.select_linked")
layout.operator("sequencer.select_less")
layout.operator("sequencer.select_more")
- layout.operator("sequencer.select_all").action = 'TOGGLE'
- layout.operator("sequencer.select_all", text="Inverse").action = 'INVERT'
class SEQUENCER_MT_marker(Menu):
@@ -431,10 +436,6 @@ class SEQUENCER_MT_strip(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("ed.undo")
- layout.operator("ed.redo")
- layout.operator("ed.undo_history")
-
layout.separator()
layout.menu("SEQUENCER_MT_strip_transform")
layout.operator("sequencer.snap")
@@ -1288,7 +1289,7 @@ class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsP
class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
_context_path = "scene.sequence_editor.active_strip"
_property_type = (bpy.types.Sequence,)
bl_category = "Strip"
diff --git a/release/scripts/startup/bl_ui/space_statusbar.py b/release/scripts/startup/bl_ui/space_statusbar.py
new file mode 100644
index 00000000000..dbcfbf165ce
--- /dev/null
+++ b/release/scripts/startup/bl_ui/space_statusbar.py
@@ -0,0 +1,68 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Header
+
+
+class STATUSBAR_HT_header(Header):
+ bl_space_type = 'STATUSBAR'
+
+ def draw(self, context):
+ layout = self.layout
+
+ # input status
+ layout.template_input_status()
+
+ layout.separator_spacer()
+
+ # messages
+ layout.template_reports_banner()
+
+ row = layout.row(align=True)
+ if bpy.app.autoexec_fail is True and bpy.app.autoexec_fail_quiet is False:
+ row.label("Auto-run disabled", icon='ERROR')
+ if bpy.data.is_saved:
+ props = row.operator("wm.revert_mainfile", icon='SCREEN_BACK', text="Reload Trusted")
+ props.use_scripts = True
+
+ row.operator("script.autoexec_warn_clear", text="Ignore")
+
+ # include last so text doesn't push buttons out of the header
+ row.label(bpy.app.autoexec_fail_message)
+
+ layout.template_running_jobs()
+
+ layout.separator_spacer()
+
+ # stats
+ scene = context.scene
+ view_layer = context.view_layer
+
+ layout.label(text=scene.statistics(view_layer), translate=False)
+
+
+classes = (
+ STATUSBAR_HT_header,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index fc93956b14b..8e370326d8c 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -41,9 +41,13 @@ class TEXT_HT_header(Header):
sub.alert = True
sub.operator("text.resolve_conflict", text="", icon='HELP')
+ layout.separator_spacer()
+
row = layout.row(align=True)
row.template_ID(st, "text", new="text.new", unlink="text.unlink", open="text.open")
+ layout.separator_spacer()
+
row = layout.row(align=True)
row.prop(st, "show_line_numbers", text="")
row.prop(st, "show_word_wrap", text="")
@@ -52,17 +56,6 @@ class TEXT_HT_header(Header):
if text:
is_osl = text.name.endswith((".osl", ".osl"))
- if is_osl:
- row = layout.row()
- row.operator("node.shader_script_update")
- else:
- row = layout.row()
- row.operator("text.run_script")
-
- row = layout.row()
- row.active = text.name.endswith(".py")
- row.prop(text, "use_module")
-
row = layout.row()
if text.filepath:
if text.is_dirty:
@@ -81,6 +74,16 @@ class TEXT_HT_header(Header):
if text.library
else "Text: Internal"
)
+ if is_osl:
+ row = layout.row()
+ row.operator("node.shader_script_update")
+ else:
+ row = layout.row()
+ row.active = text.name.endswith(".py")
+ row.prop(text, "use_module")
+
+ row = layout.row()
+ row.operator("text.run_script")
class TEXT_MT_editor_menus(Menu):
@@ -186,9 +189,7 @@ class TEXT_MT_view(Menu):
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class TEXT_MT_text(Menu):
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index 9026a93aa99..99e5f6b08e5 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -18,43 +18,27 @@
# <pep8 compliant>
import bpy
-from bpy.types import Header, Menu
+from bpy.types import Header, Menu, Panel
-class TIME_HT_header(Header):
- bl_space_type = 'TIMELINE'
+# Header buttons for timeline header (play, etc.)
+class TIME_HT_editor_buttons(Header):
+ bl_idname = "TIME_HT_editor_buttons"
+ bl_space_type = 'DOPESHEET_EDITOR'
+ bl_label = ""
def draw(self, context):
- layout = self.layout
+ pass
+ @staticmethod
+ def draw_header(context, layout):
scene = context.scene
toolsettings = context.tool_settings
screen = context.screen
- userprefs = context.user_preferences
- row = layout.row(align=True)
- row.template_header()
-
- TIME_MT_editor_menus.draw_collapsible(context, layout)
-
- row = layout.row(align=True)
- row.prop(scene, "use_preview_range", text="", toggle=True)
- row.prop(scene, "lock_frame_selection_to_range", text="", toggle=True)
-
- row = layout.row(align=True)
- if not scene.use_preview_range:
- row.prop(scene, "frame_start", text="Start")
- row.prop(scene, "frame_end", text="End")
- else:
- row.prop(scene, "frame_preview_start", text="Start")
- row.prop(scene, "frame_preview_end", text="End")
-
- if scene.show_subframe:
- layout.prop(scene, "frame_float", text="")
- else:
- layout.prop(scene, "frame_current", text="")
+ layout.separator_spacer()
- layout.separator()
+ layout.prop(toolsettings, "use_keyframe_insert_auto", text="", toggle=True)
row = layout.row(align=True)
row.operator("screen.frame_jump", text="", icon='REW').end = False
@@ -65,37 +49,37 @@ class TIME_HT_header(Header):
# since JACK transport doesn't support reversed playback
if scene.sync_mode == 'AUDIO_SYNC' and context.user_preferences.system.audio_device == 'JACK':
sub = row.row(align=True)
- sub.scale_x = 2.0
+ sub.scale_x = 1.4
sub.operator("screen.animation_play", text="", icon='PLAY')
else:
row.operator("screen.animation_play", text="", icon='PLAY_REVERSE').reverse = True
row.operator("screen.animation_play", text="", icon='PLAY')
else:
sub = row.row(align=True)
- sub.scale_x = 2.0
+ sub.scale_x = 1.4
sub.operator("screen.animation_play", text="", icon='PAUSE')
row.operator("screen.keyframe_jump", text="", icon='NEXT_KEYFRAME').next = True
row.operator("screen.frame_jump", text="", icon='FF').end = True
- layout.prop(scene, "sync_mode", text="")
-
- layout.separator()
-
- row = layout.row(align=True)
- row.prop(toolsettings, "use_keyframe_insert_auto", text="", toggle=True)
- if toolsettings.use_keyframe_insert_auto:
- row.prop(toolsettings, "use_keyframe_insert_keyingset", text="", toggle=True)
-
- if screen.is_animation_playing and not userprefs.edit.use_keyframe_insert_available:
- subsub = row.row(align=True)
- subsub.prop(toolsettings, "use_record_with_nla", toggle=True)
+ layout.separator_spacer()
- layout.prop(toolsettings, "keyframe_type", text="", icon_only=True)
+ row = layout.row()
+ row.scale_x = 0.95
+ if scene.show_subframe:
+ row.prop(scene, "frame_float", text="")
+ else:
+ row.prop(scene, "frame_current", text="")
row = layout.row(align=True)
- row.prop_search(scene.keying_sets_all, "active", scene, "keying_sets_all", text="")
- row.operator("anim.keyframe_insert", text="", icon='KEY_HLT')
- row.operator("anim.keyframe_delete", text="", icon='KEY_DEHLT')
+ row.prop(scene, "use_preview_range", text="", toggle=True)
+ sub = row.row(align=True)
+ sub.scale_x = 0.8
+ if not scene.use_preview_range:
+ sub.prop(scene, "frame_start", text="Start")
+ sub.prop(scene, "frame_end", text="End")
+ else:
+ sub.prop(scene, "frame_preview_start", text="Start")
+ sub.prop(scene, "frame_preview_end", text="End")
class TIME_MT_editor_menus(Menu):
@@ -107,10 +91,20 @@ class TIME_MT_editor_menus(Menu):
@staticmethod
def draw_menus(layout, context):
- layout.menu("TIME_MT_view")
- layout.menu("TIME_MT_marker")
- layout.menu("TIME_MT_frame")
- layout.menu("TIME_MT_playback")
+ row = layout.row()
+ sub = row.row(align=True)
+ sub.popover(
+ panel="TIME_PT_playback",
+ text="Playback",
+ )
+ sub.popover(
+ panel="TIME_PT_keyframing_settings",
+ text="Keying",
+ )
+
+ sub = row.row(align=True)
+ sub.menu("TIME_MT_view")
+ sub.menu("TIME_MT_marker")
class TIME_MT_marker(Menu):
@@ -138,7 +132,6 @@ class TIME_MT_view(Menu):
layout.prop(st, "show_frame_indicator")
layout.prop(scene, "show_keys_from_selected_only")
- layout.prop(scene, "show_subframe")
layout.separator()
@@ -146,18 +139,13 @@ class TIME_MT_view(Menu):
layout.separator()
- layout.operator("time.view_all")
- layout.operator("time.view_frame")
-
- layout.separator()
-
- layout.operator("marker.camera_bind")
+ # NOTE: "action" now, since timeline is in the dopesheet editor, instead of as own editor
+ layout.operator("action.view_all")
+ layout.operator("action.view_frame")
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class TIME_MT_cache(Menu):
@@ -182,25 +170,56 @@ class TIME_MT_cache(Menu):
col.prop(st, "cache_rigidbody")
-class TIME_MT_frame(Menu):
- bl_label = "Frame"
+def marker_menu_generic(layout):
+ from bpy import context
- def draw(self, context):
- layout = self.layout
+ # layout.operator_context = 'EXEC_REGION_WIN'
- layout.operator("anim.previewrange_clear")
- layout.operator("anim.previewrange_set")
- layout.separator()
- layout.operator("time.end_frame_set")
- layout.operator("time.start_frame_set")
+ layout.column()
+ layout.operator("marker.add", "Add Marker")
+ layout.operator("marker.duplicate", text="Duplicate Marker")
- layout.separator()
+ if len(bpy.data.scenes) > 10:
+ layout.operator_context = 'INVOKE_DEFAULT'
+ layout.operator("marker.make_links_scene", text="Duplicate Marker to Scene...", icon='OUTLINER_OB_EMPTY')
+ else:
+ layout.operator_menu_enum("marker.make_links_scene", "scene", text="Duplicate Marker to Scene")
- layout.menu("TIME_MT_autokey")
+ layout.operator("marker.delete", text="Delete Marker")
+ layout.separator()
-class TIME_MT_playback(Menu):
+ layout.operator("marker.rename", text="Rename Marker")
+ layout.operator("marker.move", text="Grab/Move Marker")
+
+ layout.separator()
+
+ layout.operator("marker.camera_bind")
+
+ layout.separator()
+
+ layout.operator("screen.marker_jump", text="Jump to Next Marker").next = True
+ layout.operator("screen.marker_jump", text="Jump to Previous Marker").next = False
+
+ layout.separator()
+ ts = context.tool_settings
+ layout.prop(ts, "lock_markers")
+
+###################################
+
+
+class TimelinePanelButtons:
+ bl_space_type = 'DOPESHEET_EDITOR'
+ bl_region_type = 'UI'
+
+ @staticmethod
+ def has_timeline(context):
+ return context.space_data.mode == 'TIMELINE'
+
+
+class TIME_PT_playback(TimelinePanelButtons, Panel):
bl_label = "Playback"
+ bl_region_type = 'HEADER'
def draw(self, context):
layout = self.layout
@@ -208,7 +227,20 @@ class TIME_MT_playback(Menu):
screen = context.screen
scene = context.scene
- layout.prop(screen, "use_play_top_left_3d_editor")
+ layout.prop(scene, "sync_mode", text="")
+ layout.prop(scene, "use_audio_scrub")
+ layout.prop(scene, "use_audio", text="Mute Audio")
+
+ layout.prop(scene, "show_subframe", text="Subframes")
+
+ layout.prop(scene, "lock_frame_selection_to_range", text="Limit Playhead to Frame Range")
+ layout.prop(screen, "use_follow", text="Follow Playhead")
+
+ layout.separator()
+
+ col = layout.column()
+ col.label("Play Animation In:")
+ layout.prop(screen, "use_play_top_left_3d_editor", text="Active Editor Only")
layout.prop(screen, "use_play_3d_editors")
layout.prop(screen, "use_play_animation_editors")
layout.prop(screen, "use_play_properties_editors")
@@ -218,67 +250,59 @@ class TIME_MT_playback(Menu):
layout.prop(screen, "use_play_clip_editors")
layout.separator()
- layout.prop(screen, "use_follow")
- layout.separator()
- layout.prop(scene, "use_frame_drop", text="Frame Dropping")
- layout.prop(scene, "use_audio_sync", text="AV-sync", icon='SPEAKER')
- layout.prop(scene, "use_audio")
- layout.prop(scene, "use_audio_scrub")
+ row = layout.row(align=True)
+ row.operator("anim.start_frame_set")
+ row.operator("anim.end_frame_set")
-class TIME_MT_autokey(Menu):
- bl_label = "Auto-Keyframing Mode"
+class TIME_PT_keyframing_settings(TimelinePanelButtons, Panel):
+ bl_label = "Keyframing Settings"
+ bl_options = {'HIDE_HEADER'}
+ bl_region_type = 'HEADER'
+
+ @classmethod
+ def poll(cls, context):
+ # only for timeline editor
+ return cls.has_timeline(context)
def draw(self, context):
layout = self.layout
- toolsettings = context.tool_settings
-
- layout.prop_enum(toolsettings, "auto_keying_mode", 'ADD_REPLACE_KEYS')
- layout.prop_enum(toolsettings, "auto_keying_mode", 'REPLACE_KEYS')
-
-
-def marker_menu_generic(layout):
- from bpy import context
- # layout.operator_context = 'EXEC_REGION_WIN'
-
- layout.column()
- layout.operator("marker.add", "Add Marker")
- layout.operator("marker.duplicate", text="Duplicate Marker")
-
- if len(bpy.data.scenes) > 10:
- layout.operator_context = 'INVOKE_DEFAULT'
- layout.operator("marker.make_links_scene", text="Duplicate Marker to Scene...", icon='OUTLINER_OB_EMPTY')
- else:
- layout.operator_menu_enum("marker.make_links_scene", "scene", text="Duplicate Marker to Scene")
-
- layout.operator("marker.delete", text="Delete Marker")
-
- layout.separator()
+ scene = context.scene
+ toolsettings = context.tool_settings
+ userprefs = context.user_preferences
- layout.operator("marker.rename", text="Rename Marker")
- layout.operator("marker.move", text="Grab/Move Marker")
+ col = layout.column(align=True)
+ col.label("Active Keying Set:")
+ row = col.row(align=True)
+ row.prop_search(scene.keying_sets_all, "active", scene, "keying_sets_all", text="")
+ row.operator("anim.keyframe_insert", text="", icon='KEY_HLT')
+ row.operator("anim.keyframe_delete", text="", icon='KEY_DEHLT')
- layout.separator()
+ col = layout.column(align=True)
+ col.label("New Keyframe Type:")
+ col.prop(toolsettings, "keyframe_type", text="")
- layout.operator("screen.marker_jump", text="Jump to Next Marker").next = True
- layout.operator("screen.marker_jump", text="Jump to Previous Marker").next = False
+ col = layout.column(align=True)
+ col.label("Auto Keyframing:")
+ row = col.row()
+ row.prop(toolsettings, "auto_keying_mode", text="")
+ row.prop(toolsettings, "use_keyframe_insert_keyingset", text="")
+ if not userprefs.edit.use_keyframe_insert_available:
+ col.prop(toolsettings, "use_record_with_nla", text="Layered Recording")
- layout.separator()
- ts = context.tool_settings
- layout.prop(ts, "lock_markers")
+###################################
classes = (
- TIME_HT_header,
+ TIME_HT_editor_buttons,
TIME_MT_editor_menus,
TIME_MT_marker,
TIME_MT_view,
TIME_MT_cache,
- TIME_MT_frame,
- TIME_MT_playback,
- TIME_MT_autokey,
+ TIME_PT_playback,
+ TIME_PT_keyframing_settings,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
new file mode 100644
index 00000000000..ffd95ec7c64
--- /dev/null
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -0,0 +1,725 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import (
+ Menu,
+)
+
+__all__ = (
+ "ToolSelectPanelHelper",
+ "ToolDef",
+)
+
+# Support reloading icons.
+if "_icon_cache" in locals():
+ release = bpy.app.icons.release
+ for icon_value in _icon_cache.values():
+ if icon_value != 0:
+ release(icon_value)
+ del release
+
+
+# (filename -> icon_value) map
+_icon_cache = {}
+
+
+def _keymap_fn_from_seq(keymap_data):
+
+ # standalone
+ def _props_assign_recursive(rna_props, py_props):
+ for prop_id, value in py_props.items():
+ if isinstance(value, dict):
+ _props_assign_recursive(getattr(rna_props, prop_id), value)
+ else:
+ setattr(rna_props, prop_id, value)
+
+ def keymap_fn(km):
+ for op_idname, op_props_dict, kmi_kwargs in keymap_fn.keymap_data:
+ kmi = km.keymap_items.new(op_idname, **kmi_kwargs)
+ kmi_props = kmi.properties
+ if op_props_dict:
+ _props_assign_recursive(kmi.properties, op_props_dict)
+ keymap_fn.keymap_data = keymap_data
+ return keymap_fn
+
+
+def _item_is_fn(item):
+ return (not (type(item) is ToolDef) and callable(item))
+
+
+from collections import namedtuple
+ToolDef = namedtuple(
+ "ToolDef",
+ (
+ # The name to display in the interface.
+ "text",
+ # The name of the icon to use (found in ``release/datafiles/icons``) or None for no icon.
+ "icon",
+ # An optional cursor to use when this tool is active.
+ "cursor",
+ # An optional manipulator group to activate when the tool is set or None for no widget.
+ "widget",
+ # Optional keymap for tool, either:
+ # - A function that populates a keymaps passed in as an argument.
+ # - A tuple filled with triple's of:
+ # ``(operator_id, operator_properties, keymap_item_args)``.
+ #
+ # Warning: currently 'from_dict' this is a list of one item,
+ # so internally we can swap the keymap function for the keymap it's self.
+ # This isn't very nice and may change, tool definitions shouldn't care about this.
+ "keymap",
+ # Optional data-block assosiated with this tool.
+ # (Typically brush name, usage depends on mode, we could use for non-brush ID's in other modes).
+ "data_block",
+ # Optional primary operator (for introspection only).
+ "operator",
+ # Optional draw settings (operator options, toolsettings).
+ "draw_settings",
+ )
+)
+del namedtuple
+
+
+def from_dict(kw_args):
+ """
+ Use so each tool can avoid defining all members of the named tuple.
+ Also convert the keymap from a tuple into a function
+ (since keymap is a callback).
+ """
+ kw = {
+ "icon": None,
+ "cursor": None,
+ "widget": None,
+ "keymap": None,
+ "data_block": None,
+ "operator": None,
+ "draw_settings": None,
+ }
+ kw.update(kw_args)
+
+ keymap = kw["keymap"]
+ if kw["keymap"] is None:
+ pass
+ elif type(keymap) is tuple:
+ keymap = [_keymap_fn_from_seq(keymap)]
+ else:
+ keymap = [keymap]
+ kw["keymap"] = keymap
+ return ToolDef(**kw)
+
+
+def from_fn(fn):
+ """
+ Use as decorator so we can define functions.
+ """
+ return ToolDef.from_dict(fn())
+
+
+ToolDef.from_dict = from_dict
+ToolDef.from_fn = from_fn
+del from_dict
+del from_fn
+
+
+class ToolSelectPanelHelper:
+ """
+ Generic Class, can be used for any toolbar.
+
+ - keymap_prefix:
+ The text prefix for each key-map for this spaces tools.
+ - tools_all():
+ Returns (context_mode, tools) tuple pair for all tools defined.
+ - tools_from_context(context, mode=None):
+ Returns tools available in this context.
+
+ Each tool is a 'ToolDef' or None for a separator in the toolbar, use ``None``.
+ """
+
+ @staticmethod
+ def _tool_class_from_space_type(space_type):
+ return next(
+ (cls for cls in ToolSelectPanelHelper.__subclasses__()
+ if cls.bl_space_type == space_type),
+ None
+ )
+
+ @staticmethod
+ def _icon_value_from_icon_handle(icon_name):
+ import os
+ if icon_name is not None:
+ assert(type(icon_name) is str)
+ icon_value = _icon_cache.get(icon_name)
+ if icon_value is None:
+ dirname = bpy.utils.resource_path('LOCAL')
+ if not os.path.exists(dirname):
+ # TODO(campbell): use a better way of finding datafiles.
+ dirname = bpy.utils.resource_path('SYSTEM')
+ filename = os.path.join(dirname, "datafiles", "icons", icon_name + ".dat")
+ try:
+ icon_value = bpy.app.icons.new_triangles_from_file(filename)
+ except Exception as ex:
+ if not os.path.exists(filename):
+ print("Missing icons:", filename, ex)
+ else:
+ print("Corrupt icon:", filename, ex)
+ # Use none as a fallback (avoids layout issues).
+ if icon_name != "none":
+ icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle("none")
+ else:
+ icon_value = 0
+ _icon_cache[icon_name] = icon_value
+ return icon_value
+ else:
+ return 0
+
+ @staticmethod
+ def _tools_flatten(tools):
+ """
+ Flattens, skips None and calls generators.
+ """
+ for item in tools:
+ if item is None:
+ yield None
+ elif type(item) is tuple:
+ for sub_item in item:
+ if sub_item is None:
+ yield None
+ elif _item_is_fn(sub_item):
+ yield from sub_item(context)
+ else:
+ yield sub_item
+ else:
+ if _item_is_fn(item):
+ yield from item(context)
+ else:
+ yield item
+
+ @staticmethod
+ def _tools_flatten_with_tool_index(tools):
+ for item in tools:
+ if item is None:
+ yield None, -1
+ elif type(item) is tuple:
+ i = 0
+ for sub_item in item:
+ if sub_item is None:
+ yield None
+ elif _item_is_fn(sub_item):
+ for item_dyn in sub_item(context):
+ yield item_dyn, i
+ i += 1
+ else:
+ yield sub_item, i
+ i += 1
+ else:
+ if _item_is_fn(item):
+ for item_dyn in item(context):
+ yield item_dyn, -1
+ else:
+ yield item, -1
+
+ @staticmethod
+ def _tool_get_active(context, space_type, mode, with_icon=False):
+ """
+ Return the active Python tool definition and icon name.
+ """
+ workspace = context.workspace
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is not None:
+ tool_active = ToolSelectPanelHelper._tool_active_from_context(context, space_type, mode)
+ tool_active_text = getattr(tool_active, "name", None)
+ for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context, mode)):
+ if item is not None:
+ if item.text == tool_active_text:
+ if with_icon:
+ icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(item.icon)
+ else:
+ icon_value = 0
+ return (item, tool_active, icon_value)
+ return None, None, 0
+
+ @staticmethod
+ def _tool_get_by_name(context, space_type, text):
+ """
+ Return the active Python tool definition and index (if in sub-group, else -1).
+ """
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ if cls is not None:
+ for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)):
+ if item is not None:
+ if item.text == text:
+ return (cls, item, index)
+ return None, None, -1
+
+ @staticmethod
+ def _tool_active_from_context(context, space_type, mode=None, create=False):
+ if space_type == 'VIEW_3D':
+ if mode is None:
+ mode = context.mode
+ tool = context.workspace.tools.from_space_view3d_mode(mode, create)
+ if tool is not None:
+ return tool
+ elif space_type == 'IMAGE_EDITOR':
+ space_data = context.space_data
+ if mode is None:
+ mode = space_data.mode
+ tool = context.workspace.tools.from_space_image_mode(mode, create)
+ if tool is not None:
+ return tool
+ return None
+
+ @staticmethod
+ def _tool_text_from_button(context):
+ return context.button_operator.name
+
+ @classmethod
+ def _km_action_simple(cls, kc, context_mode, text, keymap_fn):
+ if context_mode is None:
+ context_mode = "All"
+ km_idname = f"{cls.keymap_prefix} {context_mode}, {text}"
+ km = kc.keymaps.get(km_idname)
+ if km is None:
+ km = kc.keymaps.new(km_idname, space_type=cls.bl_space_type, region_type='WINDOW')
+ keymap_fn[0](km)
+ keymap_fn[0] = km
+
+ @classmethod
+ def register(cls):
+ wm = bpy.context.window_manager
+
+ # XXX, should we be manipulating the user-keyconfig on load?
+ # Perhaps this should only add when keymap items don't already exist.
+ #
+ # This needs some careful consideration.
+ kc = wm.keyconfigs.user
+
+ # Track which tool-group was last used for non-active groups.
+ # Blender stores the active tool-group index.
+ #
+ # {tool_name_first: index_in_group, ...}
+ cls._tool_group_active = {}
+
+ # ignore in background mode
+ if kc is None:
+ return
+
+ for context_mode, tools in cls.tools_all():
+ for item_parent in tools:
+ if item_parent is None:
+ continue
+ for item in item_parent if (type(item_parent) is tuple) else (item_parent,):
+ # skip None or generator function
+ if item is None or _item_is_fn(item):
+ continue
+ keymap_data = item.keymap
+ if keymap_data is not None and callable(keymap_data[0]):
+ text = item.text
+ icon_name = item.icon
+ cls._km_action_simple(kc, context_mode, text, keymap_data)
+
+ # -------------------------------------------------------------------------
+ # Layout Generators
+ #
+ # Meaning of recieved values:
+ # - Bool: True for a separator, otherwise False for regular tools.
+ # - None: Signal to finish (complete any final operations, e.g. add padding).
+
+ @staticmethod
+ def _layout_generator_single_column(layout, scale_y):
+ col = layout.column(align=True)
+ col.scale_y = scale_y
+ is_sep = False
+ while True:
+ if is_sep is True:
+ col = layout.column(align=True)
+ col.scale_y = scale_y
+ elif is_sep is None:
+ yield None
+ return
+ is_sep = yield col
+
+ @staticmethod
+ def _layout_generator_multi_columns(layout, column_count, scale_y):
+ scale_x = scale_y * 1.1
+ column_last = column_count - 1
+
+ col = layout.column(align=True)
+
+ row = col.row(align=True)
+
+ row.scale_x = scale_x
+ row.scale_y = scale_y
+
+ is_sep = False
+ column_index = 0
+ while True:
+ if is_sep is True:
+ if column_index != column_last:
+ row.label("")
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ row.scale_x = scale_x
+ row.scale_y = scale_y
+ column_index = 0
+
+ is_sep = yield row
+ if is_sep is None:
+ if column_index == column_last:
+ row.label("")
+ yield None
+ return
+
+ if column_index == column_count:
+ column_index = 0
+ row = col.row(align=True)
+ row.scale_x = scale_x
+ row.scale_y = scale_y
+ column_index += 1
+
+ @staticmethod
+ def _layout_generator_detect_from_region(layout, region, scale_y):
+ """
+ Choose an appropriate layout for the toolbar.
+ """
+ # Currently this just checks the width,
+ # we could have different layouts as preferences too.
+ system = bpy.context.user_preferences.system
+ view2d = region.view2d
+ view2d_scale = (
+ view2d.region_to_view(1.0, 0.0)[0] -
+ view2d.region_to_view(0.0, 0.0)[0]
+ )
+ width_scale = region.width * view2d_scale / system.ui_scale
+
+ if width_scale > 120.0:
+ show_text = True
+ column_count = 1
+ else:
+ show_text = False
+ # 2 column layout, disabled
+ if width_scale > 80.0:
+ column_count = 2
+ use_columns = True
+ else:
+ column_count = 1
+
+ if column_count == 1:
+ ui_gen = ToolSelectPanelHelper._layout_generator_single_column(layout, scale_y=scale_y)
+ else:
+ ui_gen = ToolSelectPanelHelper._layout_generator_multi_columns(layout, column_count=column_count, scale_y=scale_y)
+
+ return ui_gen, show_text
+
+ @classmethod
+ def draw_cls(cls, layout, context, detect_layout=True, scale_y=1.75):
+ # Use a classmethod so it can be called outside of a panel context.
+
+ # XXX, this UI isn't very nice.
+ # We might need to create new button types for this.
+ # Since we probably want:
+ # - tool-tips that include multiple key shortcuts.
+ # - ability to click and hold to expose sub-tools.
+
+ space_type = context.space_data.type
+ tool_active_text = getattr(
+ ToolSelectPanelHelper._tool_active_from_context(context, space_type),
+ "name", None,
+ )
+
+ if detect_layout:
+ ui_gen, show_text = cls._layout_generator_detect_from_region(layout, context.region, scale_y)
+ else:
+ ui_gen = ToolSelectPanelHelper._layout_generator_single_column(layout, scale_y)
+ show_text = True
+
+ # Start iteration
+ ui_gen.send(None)
+
+ for item in cls.tools_from_context(context):
+ if item is None:
+ ui_gen.send(True)
+ continue
+
+ if type(item) is tuple:
+ is_active = False
+ i = 0
+ for i, sub_item in enumerate(item):
+ if sub_item is None:
+ continue
+ is_active = (sub_item.text == tool_active_text)
+ if is_active:
+ index = i
+ break
+ del i, sub_item
+
+ if is_active:
+ # not ideal, write this every time :S
+ cls._tool_group_active[item[0].text] = index
+ else:
+ index = cls._tool_group_active.get(item[0].text, 0)
+
+ item = item[index]
+ use_menu = True
+ else:
+ index = -1
+ use_menu = False
+
+ is_active = (item.text == tool_active_text)
+ icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(item.icon)
+
+ sub = ui_gen.send(False)
+
+ if use_menu:
+ sub.operator_menu_hold(
+ "wm.tool_set_by_name",
+ text=item.text if show_text else "",
+ depress=is_active,
+ menu="WM_MT_toolsystem_submenu",
+ icon_value=icon_value,
+ ).name = item.text
+ else:
+ sub.operator(
+ "wm.tool_set_by_name",
+ text=item.text if show_text else "",
+ depress=is_active,
+ icon_value=icon_value,
+ ).name = item.text
+ # Signal to finish any remaining layout edits.
+ ui_gen.send(None)
+
+ def draw(self, context):
+ self.draw_cls(self.layout, context)
+
+ @staticmethod
+ def draw_active_tool_header(context, layout):
+ # BAD DESIGN WARNING: last used tool
+ workspace = context.workspace
+ space_type = workspace.tools_space_type
+ mode = workspace.tools_mode
+ item, tool, icon_value = ToolSelectPanelHelper._tool_get_active(context, space_type, mode, with_icon=True)
+ if item is None:
+ return
+ # Note: we could show 'item.text' here but it makes the layout jitter when switcuing tools.
+ layout.label(" ", icon_value=icon_value)
+ draw_settings = item.draw_settings
+ if draw_settings is not None:
+ draw_settings(context, layout, tool)
+
+
+# The purpose of this menu is to be a generic popup to select between tools
+# in cases when a single tool allows to select alternative tools.
+class WM_MT_toolsystem_submenu(Menu):
+ bl_label = ""
+
+ @staticmethod
+ def _tool_group_from_button(context):
+ # Lookup the tool definitions based on the space-type.
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(context.space_data.type)
+ if cls is not None:
+ button_text = ToolSelectPanelHelper._tool_text_from_button(context)
+ for item_group in cls.tools_from_context(context):
+ if type(item_group) is tuple:
+ for sub_item in item_group:
+ if sub_item.text == button_text:
+ return cls, item_group
+ return None, None
+
+ def draw(self, context):
+ layout = self.layout
+ layout.scale_y = 2.0
+
+ cls, item_group = self._tool_group_from_button(context)
+ if item_group is None:
+ # Should never happen, just in case
+ layout.label("Unable to find toolbar group")
+ return
+
+ for item in item_group:
+ if item is None:
+ layout.separator()
+ continue
+ icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(item.icon)
+ layout.operator(
+ "wm.tool_set_by_name",
+ text=item.text,
+ icon_value=icon_value,
+ ).name = item.text
+
+
+def _activate_by_item(context, space_type, item, index):
+ tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True)
+ tool.setup(
+ name=item.text,
+ keymap=item.keymap[0].name if item.keymap is not None else "",
+ cursor=item.cursor or 'DEFAULT',
+ manipulator_group=item.widget or "",
+ data_block=item.data_block or "",
+ operator=item.operator or "",
+ index=index,
+ )
+
+
+def activate_by_name(context, space_type, text):
+ cls, item, index = ToolSelectPanelHelper._tool_get_by_name(context, space_type, text)
+ if item is None:
+ return False
+ _activate_by_item(context, space_type, item, index)
+ return True
+
+
+def activate_by_name_or_cycle(context, space_type, text, offset=1):
+
+ # Only cycle when the active tool is activated again.
+ cls, item, index = ToolSelectPanelHelper._tool_get_by_name(context, space_type, text)
+ if item is None:
+ return False
+
+ tool_active = ToolSelectPanelHelper._tool_active_from_context(context, space_type)
+ text_active = getattr(tool_active, "name", None)
+
+ text_current = ""
+ for item_group in cls.tools_from_context(context):
+ if type(item_group) is tuple:
+ index_current = cls._tool_group_active.get(item_group[0].text, 0)
+ ok = False
+ for i, sub_item in enumerate(item_group):
+ if sub_item.text == text:
+ text_current = item_group[index_current].text
+ break
+ if text_current:
+ break
+
+ if text_current == "":
+ return activate_by_name(context, space_type, text)
+ if text_active != text_current:
+ return activate_by_name(context, space_type, text_current)
+
+ index_found = (tool_active.index + offset) % len(item_group)
+
+ cls._tool_group_active[item_group[0].text] = index_found
+
+ item_found = item_group[index_found]
+ _activate_by_item(context, space_type, item_found, index_found)
+ return True
+
+
+def keymap_from_context(context, space_type):
+ """
+ Keymap for popup toolbar, currently generated each time.
+ """
+
+ def modifier_keywords_from_item(kmi):
+ return {
+ "any": kmi.any,
+ "shift": kmi.shift,
+ "ctrl": kmi.ctrl,
+ "alt": kmi.alt,
+ "oskey": kmi.oskey,
+ "key_modifier": kmi.key_modifier,
+ }
+
+ use_search = False # allows double tap
+ use_simple_keymap = False
+
+ km_name = "Toolbar Popup"
+ wm = context.window_manager
+ keyconf = wm.keyconfigs.active
+ keymap = keyconf.keymaps.get(km_name)
+ if keymap is None:
+ keymap = keyconf.keymaps.new(km_name, space_type='EMPTY', region_type='TEMPORARY')
+ for kmi in keymap.keymap_items:
+ keymap.keymap_items.remove(kmi)
+
+ if use_search:
+ kmi_search = wm.keyconfigs.find_item_from_operator(idname="wm.toolbar")[1]
+ kmi_search_type = None if not kmi_search else kmi_search.type
+
+ items = []
+ cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
+ for i, item in enumerate(
+ ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context))
+ ):
+ if item is not None:
+ if use_simple_keymap:
+ # Simply assign a key from A-Z
+ items.append(((chr(ord('A') + i)), item.text))
+ kmi = keymap.keymap_items.new("wm.tool_set_by_name", key, 'PRESS')
+ kmi.properties.name = item.text
+ continue
+
+ # Only check the first item in the tools key-map (a little arbitrary).
+ if item.operator is not None:
+ kmi_found = wm.keyconfigs.find_item_from_operator(
+ idname=item.operator,
+ )[1]
+ elif item.keymap is not None:
+ kmi_first = item.keymap[0].keymap_items[0]
+ kmi_found = wm.keyconfigs.find_item_from_operator(
+ idname=kmi_first.idname,
+ # properties=kmi_first.properties, # prevents matches, don't use.
+ )[1]
+ del kmi_first
+ else:
+ kmi_found = None
+
+ if kmi_found is not None:
+ kmi_found_type = kmi_found.type
+ # Only for single keys.
+ if len(kmi_found_type) == 1:
+ kmi = keymap.keymap_items.new(
+ idname="wm.tool_set_by_name",
+ type=kmi_found_type,
+ value='PRESS',
+ **modifier_keywords_from_item(kmi_found),
+ )
+ kmi.properties.name = item.text
+
+ if use_search:
+ # Disallow overlap
+ if kmi_search_type == kmi_found_type:
+ kmi_search_type = None
+
+ if use_search:
+ # Support double-tap for search.
+ if kmi_search_type:
+ keymap.keymap_items.new("wm.search_menu", type=kmi_search_type, value='PRESS')
+ else:
+ # The shortcut will show, so we better support running it.
+ kmi_search = wm.keyconfigs.find_item_from_operator(idname="wm.search_menu")[1]
+ if kmi_search:
+ keymap.keymap_items.new(
+ "wm.search_menu",
+ type=kmi_search.type,
+ value='PRESS',
+ **modifier_keywords_from_item(kmi_search),
+ )
+
+ wm.keyconfigs.update()
+ return keymap
+
+
+classes = (
+ WM_MT_toolsystem_submenu,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
new file mode 100644
index 00000000000..527dfdc3c6f
--- /dev/null
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -0,0 +1,1089 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# For now group all tools together
+# we may want to move these into per space-type files.
+#
+# For now keep this in a single file since it's an area that may change,
+# so avoid making changes all over the place.
+
+from bpy.types import Panel
+
+from .space_toolsystem_common import (
+ ToolSelectPanelHelper,
+ ToolDef,
+)
+
+
+def generate_from_brushes_ex(
+ context, *,
+ icon_prefix,
+ brush_test_attr,
+ brush_category_attr,
+ brush_category_layout,
+):
+ # Categories
+ brush_categories = {}
+ for brush in context.blend_data.brushes:
+ if getattr(brush, brush_test_attr):
+ category = getattr(brush, brush_category_attr)
+ name = brush.name
+ brush_categories.setdefault(category, []).append(
+ ToolDef.from_dict(
+ dict(
+ text=name,
+ icon=icon_prefix + category.lower(),
+ data_block=name,
+ )
+ )
+ )
+
+ def tools_from_brush_group(groups):
+ assert(type(groups) is tuple)
+ if len(groups) == 1:
+ tool_defs = tuple(brush_categories.pop(groups[0], ()))
+ else:
+ tool_defs = tuple(item for g in groups for item in brush_categories.pop(g, ()))
+ if len(tool_defs) > 1:
+ return (tool_defs,)
+ else:
+ return tool_defs
+
+ # Each item below is a single toolbar entry:
+ # Grouped for multiple or none if no brushes are found.
+ tool_defs = tuple(
+ tool_def
+ for category in brush_category_layout
+ for tool_def in tools_from_brush_group(category)
+ )
+ # Ensure we use all types.
+ if brush_categories:
+ print(brush_categories)
+ assert(len(brush_categories) == 0)
+ return tool_defs
+
+
+class _defs_view3d_generic:
+ @ToolDef.from_fn
+ def cursor():
+ def draw_settings(context, layout, tool):
+ wm = context.window_manager
+ props = tool.operator_properties("view3d.cursor3d")
+ layout.prop(props, "use_depth")
+ layout.prop(props, "orientation")
+
+ return dict(
+ text="Cursor",
+ icon="ops.generic.cursor",
+ keymap=(
+ ("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ("transform.translate",
+ dict(release_confirm=True, cursor_transform=True),
+ dict(type='EVT_TWEAK_A', value='ANY'),
+ ),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def cursor_click():
+ return dict(
+ text="None",
+ icon="ops.generic.cursor",
+ keymap=(
+ # This is a dummy keymap entry, until particle system is properly working with toolsystem.
+ ("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='CLICK', ctrl=True, alt=True, shift=True)),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def ruler():
+ return dict(
+ text="Ruler",
+ icon="ops.view3d.ruler",
+ widget="VIEW3D_WGT_ruler",
+ keymap=(
+ ("view3d.ruler_add", dict(), dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+
+class _defs_transform:
+
+ @ToolDef.from_fn
+ def translate():
+ return dict(
+ text="Grab",
+ # cursor='SCROLL_XY',
+ icon="ops.transform.translate",
+ widget="TRANSFORM_WGT_manipulator",
+ operator="transform.translate",
+ # TODO, implement as optional fallback manipulator
+ # keymap=(
+ # ("transform.translate", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
+ # ),
+ )
+
+ @ToolDef.from_fn
+ def rotate():
+ return dict(
+ text="Rotate",
+ # cursor='SCROLL_XY',
+ icon="ops.transform.rotate",
+ widget="TRANSFORM_WGT_manipulator",
+ operator="transform.rotate",
+ # TODO, implement as optional fallback manipulator
+ # keymap=(
+ # ("transform.rotate", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
+ # ),
+ )
+
+ @ToolDef.from_fn
+ def scale():
+ return dict(
+ text="Scale",
+ # cursor='SCROLL_XY',
+ icon="ops.transform.resize",
+ widget="TRANSFORM_WGT_manipulator",
+ operator="transform.resize",
+ # TODO, implement as optional fallback manipulator
+ # keymap=(
+ # ("transform.resize", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
+ # ),
+ )
+
+ @ToolDef.from_fn
+ def scale_cage():
+ return dict(
+ text="Scale Cage",
+ icon="ops.transform.resize.cage",
+ widget="VIEW3D_WGT_xform_cage",
+ operator="transform.resize",
+ )
+
+ @ToolDef.from_fn
+ def transform():
+ def draw_settings(context, layout, tool):
+ tool_settings = context.tool_settings
+ layout.prop(tool_settings, "use_manipulator_mode")
+
+ return dict(
+ text="Transform",
+ icon="ops.transform.transform",
+ widget="TRANSFORM_WGT_manipulator",
+ # No keymap default action, only for manipulators!
+ draw_settings=draw_settings,
+ )
+
+
+class _defs_view3d_select:
+
+ @ToolDef.from_fn
+ def border():
+ return dict(
+ text="Select Border",
+ icon="ops.generic.select_border",
+ widget=None,
+ keymap=(
+ ("view3d.select_border",
+ dict(deselect=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ("view3d.select_border",
+ dict(deselect=True),
+ dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def circle():
+ return dict(
+ text="Select Circle",
+ icon="ops.generic.select_circle",
+ widget=None,
+ keymap=(
+ ("view3d.select_circle",
+ dict(deselect=False),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ("view3d.select_circle",
+ dict(deselect=True),
+ dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def lasso():
+ return dict(
+ text="Select Lasso",
+ icon="ops.generic.select_lasso",
+ widget=None,
+ keymap=(
+ ("view3d.select_lasso",
+ dict(deselect=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ("view3d.select_lasso",
+ dict(deselect=True),
+ dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
+ ),
+ )
+# -----------------------------------------------------------------------------
+# Object Modes (named based on context.mode)
+
+
+class _defs_edit_armature:
+
+ @ToolDef.from_fn
+ def roll():
+ return dict(
+ text="Roll",
+ icon="ops.armature.bone.roll",
+ widget=None,
+ keymap=(
+ ("transform.transform",
+ dict(release_confirm=True, mode='BONE_ROLL'),
+ dict(type='EVT_TWEAK_A', value='ANY'),),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def bone_envelope():
+ return dict(
+ text="Bone Envelope",
+ icon="ops.transform.bone_envelope",
+ widget=None,
+ keymap=(
+ ("transform.transform",
+ dict(release_confirm=True, mode='BONE_ENVELOPE'),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def bone_size():
+ return dict(
+ text="Bone Size",
+ icon="ops.transform.bone_size",
+ widget=None,
+ keymap=(
+ ("transform.transform",
+ dict(release_confirm=True, mode='BONE_SIZE'),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def extrude():
+ return dict(
+ text="Extrude",
+ icon="ops.armature.extrude_move",
+ widget=None,
+ keymap=(
+ ("armature.click_extrude", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def extrude_cursor():
+ return dict(
+ text="Extrude to Cursor",
+ icon="ops.armature.extrude_cursor",
+ widget=None,
+ keymap=(
+ ("armature.click_extrude", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+
+class _defs_edit_mesh:
+
+ @ToolDef.from_fn
+ def cube_add():
+ return dict(
+ text="Add Cube",
+ icon="ops.mesh.primitive_cube_add_manipulator",
+ widget=None,
+ keymap=(
+ ("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='CLICK')),
+ ("mesh.primitive_cube_add_manipulator", dict(), dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def rip_region():
+ def draw_settings(context, layout, tool):
+ wm = context.window_manager
+ props = tool.operator_properties("mesh.rip_move")
+ props_macro = props.MESH_OT_rip
+ layout.prop(props_macro, "use_fill")
+
+ return dict(
+ text="Rip Region",
+ icon="ops.mesh.rip",
+ widget=None,
+ keymap=(
+ ("mesh.rip_move",
+ dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def rip_edge():
+ return dict(
+ text="Rip Edge",
+ icon="ops.mesh.rip_edge",
+ widget=None,
+ keymap=(
+ ("mesh.rip_edge_edge_move", dict(),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def poly_build():
+ return dict(
+ text="Poly Build",
+ icon="ops.mesh.polybuild_hover",
+ widget=None,
+ keymap=(
+ ("mesh.polybuild_face_at_cursor_move",
+ dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ("mesh.polybuild_split_at_cursor_move",
+ dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
+ dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)),
+ ("mesh.polybuild_dissolve_at_cursor", dict(), dict(type='ACTIONMOUSE', value='CLICK', alt=True)),
+ ("mesh.polybuild_hover", dict(use_boundary=False), dict(type='MOUSEMOVE', value='ANY', alt=True)),
+ ("mesh.polybuild_hover", dict(use_boundary=True), dict(type='MOUSEMOVE', value='ANY', any=True)),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def edge_slide():
+ return dict(
+ text="Edge Slide",
+ icon="ops.transform.edge_slide",
+ widget=None,
+ keymap=(
+ ("transform.edge_slide", dict(release_confirm=True),
+ dict(type='ACTIONMOUSE', value='PRESS')
+ ),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def vert_slide():
+ return dict(
+ text="Vertex Slide",
+ icon="ops.transform.vert_slide",
+ widget=None,
+ keymap=(
+ ("transform.vert_slide", dict(release_confirm=True),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def spin():
+ return dict(
+ text="Spin",
+ icon="ops.mesh.spin",
+ widget=None,
+ keymap=(
+ ("mesh.spin", dict(),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def spin_duplicate():
+ return dict(
+ text="Spin (Duplicate)",
+ icon="ops.mesh.spin.duplicate",
+ widget=None,
+ keymap=(
+ ("mesh.spin", dict(dupli=True),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def inset():
+ def draw_settings(context, layout, tool):
+ wm = context.window_manager
+ props = tool.operator_properties("mesh.inset")
+ layout.prop(props, "use_outset")
+ layout.prop(props, "use_individual")
+ layout.prop(props, "use_even_offset")
+ layout.prop(props, "use_relative_offset")
+
+ return dict(
+ text="Inset Faces",
+ icon="ops.mesh.inset",
+ widget=None,
+ keymap=(
+ ("mesh.inset", dict(release_confirm=True),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def bevel():
+ return dict(
+ text="Bevel",
+ icon="ops.mesh.bevel",
+ widget=None,
+ keymap=(
+ ("mesh.bevel", dict(),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def extrude():
+ return dict(
+ text="Extrude Region",
+ icon="ops.mesh.extrude_region_move",
+ widget="MESH_WGT_extrude",
+ operator="view3d.edit_mesh_extrude_move_normal",
+ keymap=(
+ ("mesh.extrude_context_move", dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def extrude_individual():
+ return dict(
+ text="Extrude Individual",
+ icon="ops.mesh.extrude_faces_move",
+ widget=None,
+ keymap=(
+ ("mesh.extrude_faces_move", dict(TRANSFORM_OT_shrink_fatten=dict(release_confirm=True)),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def extrude_cursor():
+ return dict(
+ text="Extrude to Cursor",
+ icon="ops.mesh.dupli_extrude_cursor",
+ widget=None,
+ keymap=(
+ ("mesh.dupli_extrude_cursor", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def loopcut_slide():
+ return dict(
+ text="Loop Cut",
+ icon="ops.mesh.loopcut_slide",
+ widget=None,
+ keymap=(
+ ("mesh.loopcut_slide", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def offset_edge_loops_slide():
+ return dict(
+ text="Offset Edge Loop Cut",
+ icon="ops.mesh.offset_edge_loops_slide",
+ widget=None,
+ keymap=(
+ ("mesh.offset_edge_loops_slide", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def vertex_smooth():
+ return dict(
+ text="Smooth",
+ icon="ops.mesh.vertices_smooth",
+ widget=None,
+ keymap=(
+ ("mesh.vertices_smooth", dict(),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def vertex_randomize():
+ return dict(
+ text="Randomize",
+ icon="ops.transform.vertex_random",
+ widget=None,
+ keymap=(
+ ("transform.vertex_random", dict(),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def shrink_fatten():
+ def draw_settings(context, layout, tool):
+ wm = context.window_manager
+ props = tool.operator_properties("transform.shrink_fatten")
+ layout.prop(props, "use_even_offset")
+
+ return dict(
+ text="Shrink/Fatten",
+ icon="ops.transform.shrink_fatten",
+ widget=None,
+ keymap=(
+ ("transform.shrink_fatten", dict(release_confirm=True),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def push_pull():
+ return dict(
+ text="Push/Pull",
+ icon="ops.transform.push_pull",
+ widget=None,
+ keymap=(
+ ("transform.push_pull", dict(release_confirm=True),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def knife():
+ def draw_settings(context, layout, tool):
+ wm = context.window_manager
+ props = tool.operator_properties("mesh.knife_tool")
+ layout.prop(props, "use_occlude_geometry")
+ layout.prop(props, "only_selected")
+
+ return dict(
+ text="Knife",
+ icon="ops.mesh.knife_tool",
+ widget=None,
+ keymap=(
+ ("mesh.knife_tool",
+ dict(wait_for_input=False),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def bisect():
+ return dict(
+ text="Bisect",
+ icon="ops.mesh.bisect",
+ widget=None,
+ keymap=(
+ ("mesh.bisect",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+
+class _defs_edit_curve:
+
+ @ToolDef.from_fn
+ def draw():
+ def draw_settings(context, layout, tool):
+ # Tool settings initialize operator options.
+ tool_settings = context.tool_settings
+ cps = tool_settings.curve_paint_settings
+
+ col = layout.row()
+
+ col.prop(cps, "curve_type")
+
+ if cps.curve_type == 'BEZIER':
+ col.prop(cps, "error_threshold")
+ col.prop(cps, "fit_method")
+ col.prop(cps, "use_corners_detect")
+
+ col = layout.row()
+ col.active = cps.use_corners_detect
+ col.prop(cps, "corner_angle")
+
+ return dict(
+ text="Draw",
+ cursor='PAINT_BRUSH',
+ icon=None,
+ widget=None,
+ keymap=(
+ ("curve.draw", dict(wait_for_input=False), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def extrude_cursor():
+ return dict(
+ text="Extrude Cursor",
+ icon=None,
+ widget=None,
+ keymap=(
+ ("curve.vertex_add", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+
+class _defs_pose:
+
+ @ToolDef.from_fn
+ def breakdown():
+ return dict(
+ text="Breakdowner",
+ icon="ops.pose.breakdowner",
+ widget=None,
+ keymap=(
+ ("pose.breakdown", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def push():
+ return dict(
+ text="Push",
+ icon="ops.pose.push",
+ widget=None,
+ keymap=(
+ ("pose.push", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def relax():
+ return dict(
+ text="Relax",
+ icon="ops.pose.relax",
+ widget=None,
+ keymap=(
+ ("pose.relax", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+
+class _defs_sculpt:
+
+ @staticmethod
+ def generate_from_brushes(context):
+ return generate_from_brushes_ex(
+ context,
+ icon_prefix="brush.sculpt.",
+ brush_test_attr="use_paint_sculpt",
+ brush_category_attr="sculpt_tool",
+ brush_category_layout=(
+ ('DRAW',),
+ ('GRAB', 'THUMB'),
+ ('SNAKE_HOOK',),
+ ('BLOB', 'INFLATE'),
+ ('SMOOTH', 'SCRAPE', 'FLATTEN'),
+ ('CREASE', 'PINCH'),
+ ('CLAY', 'CLAY_STRIPS'),
+ ('LAYER',),
+ ('NUDGE', 'ROTATE'),
+ ('FILL',),
+ ('SIMPLIFY',),
+ ('MASK',),
+ )
+ )
+
+
+class _defs_vertex_paint:
+
+ @staticmethod
+ def generate_from_brushes(context):
+ return generate_from_brushes_ex(
+ context,
+ icon_prefix="brush.paint_vertex.",
+ brush_test_attr="use_paint_vertex",
+ brush_category_attr="vertex_tool",
+ brush_category_layout=(
+ ('MIX',),
+ ('BLUR', 'AVERAGE'),
+ ('SMEAR',),
+ (
+ 'ADD', 'SUB', 'MUL', 'LIGHTEN', 'DARKEN',
+ 'COLORDODGE', 'DIFFERENCE', 'SCREEN', 'HARDLIGHT',
+ 'OVERLAY', 'SOFTLIGHT', 'EXCLUSION', 'LUMINOCITY',
+ 'SATURATION', 'HUE', 'ERASE_ALPHA', 'ADD_ALPHA',
+ ),
+ )
+ )
+
+
+class _defs_texture_paint:
+
+ @staticmethod
+ def generate_from_brushes(context):
+ return generate_from_brushes_ex(
+ context,
+ icon_prefix="brush.paint_texture.",
+ brush_test_attr="use_paint_image",
+ brush_category_attr="image_tool",
+ brush_category_layout=(
+ ('DRAW',),
+ ('SOFTEN',),
+ ('SMEAR',),
+ ('CLONE',),
+ ('FILL',),
+ ('MASK',),
+ )
+ )
+
+
+class _defs_weight_paint:
+
+ @staticmethod
+ def generate_from_brushes(context):
+ return generate_from_brushes_ex(
+ context,
+ icon_prefix="brush.paint_weight.",
+ brush_test_attr="use_paint_weight",
+ brush_category_attr="vertex_tool",
+ brush_category_layout=(
+ ('MIX',),
+ ('BLUR', 'AVERAGE'),
+ ('SMEAR',),
+ (
+ 'ADD', 'SUB', 'MUL', 'LIGHTEN', 'DARKEN',
+ 'COLORDODGE', 'DIFFERENCE', 'SCREEN', 'HARDLIGHT',
+ 'OVERLAY', 'SOFTLIGHT', 'EXCLUSION', 'LUMINOCITY',
+ 'SATURATION', 'HUE',
+ ),
+ )
+ )
+
+ @ToolDef.from_fn
+ def sample_weight():
+ return dict(
+ text="Sample Weight",
+ icon="ops.paint.weight_sample",
+ widget=None,
+ keymap=(
+ ("paint.weight_sample", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def sample_weight_group():
+ return dict(
+ text="Sample Vertex Group",
+ icon="ops.paint.weight_sample_group",
+ widget=None,
+ keymap=(
+ ("paint.weight_sample_group", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def gradient():
+ def draw_settings(context, layout, tool):
+ wm = context.window_manager
+ props = tool.operator_properties("paint.weight_gradient")
+ layout.prop(props, "type")
+
+ return dict(
+ text="Gradient",
+ icon="ops.paint.weight_gradient",
+ widget=None,
+ keymap=(
+ ("paint.weight_gradient", dict(), dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+
+class _defs_uv_select:
+
+ @ToolDef.from_fn
+ def border():
+ return dict(
+ text="Select Border",
+ icon="ops.generic.select_border",
+ widget=None,
+ keymap=(
+ ("uv.select_border",
+ dict(deselect=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ # ("uv.select_border",
+ # dict(deselect=True),
+ # dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def circle():
+ return dict(
+ text="Select Circle",
+ icon="ops.generic.select_circle",
+ widget=None,
+ keymap=(
+ ("uv.select_circle",
+ dict(), # dict(deselect=False),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ # ("uv.select_circle",
+ # dict(deselect=True),
+ # dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def lasso():
+ return dict(
+ text="Select Lasso",
+ icon="ops.generic.select_lasso",
+ widget=None,
+ keymap=(
+ ("uv.select_lasso",
+ dict(deselect=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ # ("uv.select_lasso",
+ # dict(deselect=True),
+ # dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
+ ),
+ )
+
+
+class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
+ bl_space_type = 'IMAGE_EDITOR'
+ bl_region_type = 'TOOLS'
+ bl_category = "Tools"
+ bl_label = "Tools" # not visible
+ bl_options = {'HIDE_HEADER'}
+
+ # Satisfy the 'ToolSelectPanelHelper' API.
+ keymap_prefix = "Image Editor Tool:"
+
+ @classmethod
+ def tools_from_context(cls, context, mode=None):
+ if mode is None:
+ mode = context.space_data.mode
+ for tools in (cls._tools[None], cls._tools.get(mode, ())):
+ for item in tools:
+ if not (type(item) is ToolDef) and callable(item):
+ yield from item(context)
+ else:
+ yield item
+
+ @classmethod
+ def tools_all(cls):
+ yield from cls._tools.items()
+
+ # for reuse
+ _tools_select = (
+ (
+ _defs_uv_select.border,
+ _defs_uv_select.circle,
+ _defs_uv_select.lasso,
+ ),
+ )
+
+ _tools = {
+ None: [
+ # for all modes
+ ],
+ 'VIEW': [
+ *_tools_select,
+
+ ],
+ 'MASK': [
+ None,
+ ],
+ 'PAINT': [
+ _defs_texture_paint.generate_from_brushes,
+ ],
+ }
+
+
+class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'TOOLS'
+ bl_category = "Tools"
+ bl_label = "Tools" # not visible
+ bl_options = {'HIDE_HEADER'}
+
+ # Satisfy the 'ToolSelectPanelHelper' API.
+ keymap_prefix = "3D View Tool:"
+
+ @classmethod
+ def tools_from_context(cls, context, mode=None):
+ if mode is None:
+ mode = context.mode
+ for tools in (cls._tools[None], cls._tools.get(mode, ())):
+ for item in tools:
+ if not (type(item) is ToolDef) and callable(item):
+ yield from item(context)
+ else:
+ yield item
+
+ @classmethod
+ def tools_all(cls):
+ yield from cls._tools.items()
+
+ # for reuse
+ _tools_transform = (
+ _defs_transform.transform,
+ _defs_transform.translate,
+ _defs_transform.rotate,
+ (
+ _defs_transform.scale,
+ _defs_transform.scale_cage,
+ ),
+ None,
+ _defs_view3d_generic.ruler,
+ )
+
+ _tools_select = (
+ (
+ _defs_view3d_select.border,
+ _defs_view3d_select.circle,
+ _defs_view3d_select.lasso,
+ ),
+ )
+
+ _tools = {
+ None: [
+ _defs_view3d_generic.cursor,
+ # End group.
+ ],
+ 'OBJECT': [
+ *_tools_select,
+ None,
+ *_tools_transform,
+ ],
+ 'POSE': [
+ *_tools_select,
+ *_tools_transform,
+ None,
+ (
+ _defs_pose.breakdown,
+ _defs_pose.push,
+ _defs_pose.relax,
+ )
+ ],
+ 'EDIT_ARMATURE': [
+ *_tools_select,
+ None,
+ *_tools_transform,
+ _defs_edit_armature.roll,
+ (
+ _defs_edit_armature.bone_size,
+ _defs_edit_armature.bone_envelope,
+ ),
+ None,
+ (
+ _defs_edit_armature.extrude,
+ _defs_edit_armature.extrude_cursor,
+ )
+ ],
+ 'EDIT_MESH': [
+ *_tools_select,
+ None,
+ *_tools_transform,
+ None,
+ _defs_edit_mesh.cube_add,
+ None,
+ (
+ _defs_edit_mesh.extrude,
+ _defs_edit_mesh.extrude_individual,
+ _defs_edit_mesh.extrude_cursor,
+ ),
+ _defs_edit_mesh.inset,
+ _defs_edit_mesh.bevel,
+ (
+ _defs_edit_mesh.loopcut_slide,
+ _defs_edit_mesh.offset_edge_loops_slide,
+ ),
+ (
+ _defs_edit_mesh.knife,
+ _defs_edit_mesh.bisect,
+ ),
+ _defs_edit_mesh.poly_build,
+ (
+ _defs_edit_mesh.spin,
+ _defs_edit_mesh.spin_duplicate,
+ ),
+ (
+ _defs_edit_mesh.vertex_smooth,
+ _defs_edit_mesh.vertex_randomize,
+ ),
+ (
+ _defs_edit_mesh.edge_slide,
+ _defs_edit_mesh.vert_slide,
+ ),
+ (
+ _defs_edit_mesh.shrink_fatten,
+ _defs_edit_mesh.push_pull,
+ ),
+ (
+ _defs_edit_mesh.rip_region,
+ _defs_edit_mesh.rip_edge,
+ ),
+ ],
+ 'EDIT_CURVE': [
+ *_tools_select,
+ None,
+ *_tools_transform,
+ None,
+ _defs_edit_curve.draw,
+ _defs_edit_curve.extrude_cursor,
+ ],
+ 'PARTICLE': [
+ # TODO(campbell): use cursor click tool to allow paint tools to run,
+ # we need to integrate particle system tools properly.
+ _defs_view3d_generic.cursor_click,
+ ],
+ 'SCULPT': [
+ _defs_sculpt.generate_from_brushes,
+ ],
+ 'PAINT_TEXTURE': [
+ _defs_texture_paint.generate_from_brushes,
+ ],
+ 'PAINT_VERTEX': [
+ _defs_vertex_paint.generate_from_brushes,
+ ],
+ 'PAINT_WEIGHT': [
+ _defs_weight_paint.generate_from_brushes,
+ None,
+ _defs_weight_paint.sample_weight,
+ _defs_weight_paint.sample_weight_group,
+ None,
+ # TODO, override brush events
+ *_tools_select,
+ None,
+ _defs_weight_paint.gradient,
+ ],
+ }
+
+
+classes = (
+ IMAGE_PT_tools_active,
+ VIEW3D_PT_tools_active,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
new file mode 100644
index 00000000000..96ef2e51e60
--- /dev/null
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -0,0 +1,600 @@
+# ##### 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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Header, Menu, Panel
+
+
+class TOPBAR_HT_upper_bar(Header):
+ bl_space_type = 'TOPBAR'
+
+ def draw(self, context):
+ region = context.region
+
+ if region.alignment == 'RIGHT':
+ self.draw_right(context)
+ else:
+ self.draw_left(context)
+
+ def draw_left(self, context):
+ layout = self.layout
+
+ window = context.window
+ screen = context.screen
+
+ layout.operator("wm.splash", text="", icon='BLENDER', emboss=False)
+
+ INFO_MT_editor_menus.draw_collapsible(context, layout)
+
+ layout.separator()
+
+ if not screen.show_fullscreen:
+ layout.template_ID_tabs(
+ window, "workspace",
+ new="workspace.workspace_add_menu",
+ unlink="workspace.workspace_delete",
+ )
+ else:
+ layout.operator(
+ "screen.back_to_previous",
+ icon='SCREEN_BACK',
+ text="Back to Previous",
+ )
+
+ def draw_right(self, context):
+ layout = self.layout
+
+ window = context.window
+ scene = window.scene
+
+ # Active workspace view-layer is retrieved through window, not through workspace.
+ layout.template_ID(window, "scene", new="scene.new", unlink="scene.delete")
+
+ row = layout.row(align=True)
+ row.template_search(
+ window, "view_layer",
+ scene, "view_layers",
+ new="scene.view_layer_add",
+ unlink="scene.view_layer_remove")
+
+
+class TOPBAR_HT_lower_bar(Header):
+ bl_space_type = 'TOPBAR'
+ bl_region_type = 'WINDOW'
+
+ def draw(self, context):
+ layout = self.layout
+ region = context.region
+
+ if region.alignment == 'LEFT':
+ self.draw_left(context)
+ elif region.alignment == 'RIGHT':
+ self.draw_right(context)
+ else:
+ self.draw_center(context)
+
+ def draw_left(self, context):
+ layout = self.layout
+ mode = context.mode
+
+ # Active Tool
+ # -----------
+ from .space_toolsystem_common import ToolSelectPanelHelper
+ ToolSelectPanelHelper.draw_active_tool_header(context, layout)
+
+ # Object Mode Options
+ # -------------------
+
+ # Example of how toolsettings can be accessed as pop-overs.
+
+ # TODO(campbell): editing options should be after active tool options
+ # (obviously separated for from the users POV)
+ draw_fn = getattr(_draw_left_context_mode, mode, None)
+ if draw_fn is not None:
+ draw_fn(context, layout)
+
+ # Note: general mode options should be added to 'draw_right'.
+ if mode == 'SCULPT':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
+ elif mode == 'PAINT_VERTEX':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
+ elif mode == 'PAINT_WEIGHT':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
+ elif mode == 'PAINT_TEXTURE':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
+ elif mode == 'EDIT_ARMATURE':
+ pass
+ elif mode == 'EDIT_CURVE':
+ pass
+ elif mode == 'EDIT_MESH':
+ pass
+ elif mode == 'POSE':
+ pass
+ elif mode == 'PARTICLE':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
+
+ def draw_center(self, context):
+ pass
+
+ def draw_right(self, context):
+ layout = self.layout
+
+ # General options, note, these _could_ display at the RHS of the draw_left callback.
+ # we just want them not to be confused with tool options.
+ mode = context.mode
+
+ if mode == 'SCULPT':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".sculpt_mode", category="")
+ elif mode == 'PAINT_VERTEX':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".vertexpaint", category="")
+ elif mode == 'PAINT_WEIGHT':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".weightpaint", category="")
+ elif mode == 'PAINT_TEXTURE':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".imagepaint", category="")
+ elif mode == 'EDIT_TEXT':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".text_edit", category="")
+ elif mode == 'EDIT_ARMATURE':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".armature_edit", category="")
+ elif mode == 'EDIT_METABALL':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".mball_edit", category="")
+ elif mode == 'EDIT_LATTICE':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".lattice_edit", category="")
+ elif mode == 'EDIT_CURVE':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".curve_edit", category="")
+ elif mode == 'EDIT_MESH':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".mesh_edit", category="")
+ elif mode == 'POSE':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".posemode", category="")
+ elif mode == 'PARTICLE':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".particlemode", category="")
+ elif mode == 'OBJECT':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".objectmode", category="")
+
+
+class _draw_left_context_mode:
+ @staticmethod
+ def SCULPT(context, layout):
+ brush = context.tool_settings.sculpt.brush
+ if brush is None:
+ return
+
+ from .properties_paint_common import UnifiedPaintPanel
+
+ UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True, text="Radius")
+ UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength", slider=True, text="Strength")
+ layout.prop(brush, "direction", text="", expand=True)
+
+ def PAINT_TEXTURE(context, layout):
+ brush = context.tool_settings.vertex_paint.brush
+ if brush is None:
+ return
+
+ from .properties_paint_common import UnifiedPaintPanel
+
+ layout.prop(brush, "color", text="")
+ UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True, text="Radius")
+ UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength", slider=True, text="Strength")
+
+ def PAINT_VERTEX(context, layout):
+ brush = context.tool_settings.vertex_paint.brush
+ if brush is None:
+ return
+
+ from .properties_paint_common import UnifiedPaintPanel
+
+ layout.prop(brush, "color", text="")
+ UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True, text="Radius")
+ UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength", slider=True, text="Strength")
+
+ def PAINT_WEIGHT(context, layout):
+ brush = context.tool_settings.weight_paint.brush
+ if brush is None:
+ return
+
+ from .properties_paint_common import UnifiedPaintPanel
+
+ UnifiedPaintPanel.prop_unified_weight(layout, context, brush, "weight", slider=True, text="Weight")
+ UnifiedPaintPanel.prop_unified_size(layout, context, brush, "size", slider=True, text="Radius")
+ UnifiedPaintPanel.prop_unified_strength(layout, context, brush, "strength", slider=True, text="Strength")
+
+
+class INFO_MT_editor_menus(Menu):
+ bl_idname = "INFO_MT_editor_menus"
+ bl_label = ""
+
+ def draw(self, context):
+ self.draw_menus(self.layout, context)
+
+ @staticmethod
+ def draw_menus(layout, context):
+ layout.menu("INFO_MT_file")
+ layout.menu("INFO_MT_edit")
+
+ layout.menu("INFO_MT_render")
+
+ layout.menu("INFO_MT_window")
+ layout.menu("INFO_MT_help")
+
+
+class INFO_MT_file(Menu):
+ bl_label = "File"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_AREA'
+ layout.operator("wm.read_homefile", text="New", icon='NEW')
+ layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
+ layout.menu("INFO_MT_file_open_recent")
+ layout.operator("wm.revert_mainfile")
+ layout.operator("wm.recover_last_session")
+ layout.operator("wm.recover_auto_save", text="Recover Auto Save...")
+
+ layout.separator()
+
+ layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA'
+ layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK')
+
+ layout.operator_context = 'INVOKE_AREA'
+ layout.operator("wm.save_as_mainfile", text="Save As...")
+ layout.operator_context = 'INVOKE_AREA'
+ layout.operator("wm.save_as_mainfile", text="Save Copy...").copy = True
+
+ layout.separator()
+
+ layout.operator_context = 'INVOKE_AREA'
+ layout.operator("wm.save_homefile")
+ layout.operator("wm.read_factory_settings")
+
+ layout.separator()
+
+ layout.operator_context = 'INVOKE_AREA'
+ layout.operator("wm.link", text="Link", icon='LINK_BLEND')
+ layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
+ layout.menu("INFO_MT_file_previews")
+
+ layout.separator()
+
+ layout.menu("INFO_MT_file_import", icon='IMPORT')
+ layout.menu("INFO_MT_file_export", icon='EXPORT')
+
+ layout.separator()
+
+ layout.menu("INFO_MT_file_external_data")
+
+ layout.separator()
+
+ layout.operator_context = 'EXEC_AREA'
+ if bpy.data.is_dirty and context.user_preferences.view.use_quit_dialog:
+ layout.operator_context = 'INVOKE_SCREEN' # quit dialog
+ layout.operator("wm.quit_blender", text="Quit", icon='QUIT')
+
+
+class INFO_MT_file_import(Menu):
+ bl_idname = "INFO_MT_file_import"
+ bl_label = "Import"
+
+ def draw(self, context):
+ if bpy.app.build_options.collada:
+ self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)")
+ if bpy.app.build_options.alembic:
+ self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
+
+
+class INFO_MT_file_export(Menu):
+ bl_idname = "INFO_MT_file_export"
+ bl_label = "Export"
+
+ def draw(self, context):
+ if bpy.app.build_options.collada:
+ self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)")
+ if bpy.app.build_options.alembic:
+ self.layout.operator("wm.alembic_export", text="Alembic (.abc)")
+
+
+class INFO_MT_file_external_data(Menu):
+ bl_label = "External Data"
+
+ def draw(self, context):
+ layout = self.layout
+
+ icon = 'CHECKBOX_HLT' if bpy.data.use_autopack else 'CHECKBOX_DEHLT'
+ layout.operator("file.autopack_toggle", icon=icon)
+
+ layout.separator()
+
+ pack_all = layout.row()
+ pack_all.operator("file.pack_all")
+ pack_all.active = not bpy.data.use_autopack
+
+ unpack_all = layout.row()
+ unpack_all.operator("file.unpack_all")
+ unpack_all.active = not bpy.data.use_autopack
+
+ layout.separator()
+
+ layout.operator("file.make_paths_relative")
+ layout.operator("file.make_paths_absolute")
+ layout.operator("file.report_missing_files")
+ layout.operator("file.find_missing_files")
+
+
+class INFO_MT_file_previews(Menu):
+ bl_label = "Data Previews"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.previews_ensure")
+ layout.operator("wm.previews_batch_generate")
+
+ layout.separator()
+
+ layout.operator("wm.previews_clear")
+ layout.operator("wm.previews_batch_clear")
+
+
+class INFO_MT_game(Menu):
+ bl_label = "Game"
+
+ def draw(self, context):
+ layout = self.layout
+
+ gs = context.scene.game_settings
+
+ layout.operator("view3d.game_start")
+
+ layout.separator()
+
+ layout.prop(gs, "show_debug_properties")
+ layout.prop(gs, "show_framerate_profile")
+ layout.prop(gs, "show_physics_visualization")
+ layout.prop(gs, "use_deprecation_warnings")
+ layout.prop(gs, "use_animation_record")
+ layout.separator()
+ layout.prop(gs, "use_auto_start")
+
+
+class INFO_MT_render(Menu):
+ bl_label = "Render"
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+
+ layout.operator("render.render", text="Render Image", icon='RENDER_STILL').use_viewport = True
+ props = layout.operator("render.render", text="Render Animation", icon='RENDER_ANIMATION')
+ props.animation = True
+ props.use_viewport = True
+ layout.operator("sound.mixdown", text="Render Audio", icon='PLAY_AUDIO')
+
+ layout.separator()
+
+ layout.prop_menu_enum(rd, "display_mode", text="Display Mode")
+ layout.prop(rd, "use_lock_interface", text="Lock Interface")
+
+ layout.separator()
+
+ props = layout.operator("render.opengl", text="OpenGL Render Image", icon='RENDER_STILL')
+ props.view_context = False
+ props = layout.operator("render.opengl", text="OpenGL Render Animation", icon='RENDER_ANIMATION')
+ props.view_context = False
+ props.animation = True
+ layout.menu("INFO_MT_opengl_render")
+
+ layout.separator()
+
+ layout.operator("render.view_show")
+ layout.operator("render.play_rendered_anim", icon='PLAY')
+
+
+class INFO_MT_opengl_render(Menu):
+ bl_label = "OpenGL Render Options"
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+ layout.prop(rd, "use_antialiasing")
+ layout.prop(rd, "use_full_sample")
+
+ layout.prop_menu_enum(rd, "antialiasing_samples")
+ layout.prop_menu_enum(rd, "alpha_mode")
+
+
+class INFO_MT_edit(Menu):
+ bl_label = "Edit"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("ed.undo")
+ layout.operator("ed.redo")
+
+ layout.separator()
+
+ layout.operator("ed.undo_history", text="Undo History...")
+
+ layout.separator()
+
+ layout.operator("screen.repeat_last")
+ layout.operator("screen.repeat_history", text="Repeat History...")
+
+ layout.separator()
+
+ layout.operator("screen.redo_last", text="Adjust Last Operation...")
+
+ layout.separator()
+
+ layout.operator("wm.search_menu", text="Operator Search...")
+
+ layout.separator()
+
+ # Should move elsewhere (impacts outliner & 3D view).
+ tool_settings = context.tool_settings
+ layout.prop(tool_settings, "lock_object_mode")
+
+ layout.separator()
+
+ layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES')
+
+
+class INFO_MT_window(Menu):
+ bl_label = "Window"
+
+ def draw(self, context):
+ import sys
+
+ layout = self.layout
+
+ layout.operator("wm.window_new")
+ layout.operator("wm.window_new_main")
+
+ layout.separator()
+
+ layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
+
+ layout.separator()
+
+ layout.operator("screen.workspace_cycle", text="Next Workspace").direction = 'NEXT'
+ layout.operator("screen.workspace_cycle", text="Previous Workspace").direction = 'PREV'
+
+ layout.separator()
+
+ layout.operator("screen.screenshot")
+
+ if sys.platform[:3] == "win":
+ layout.separator()
+ layout.operator("wm.console_toggle", icon='CONSOLE')
+
+ if context.scene.render.use_multiview:
+ layout.separator()
+ layout.operator("wm.set_stereo_3d")
+
+
+class INFO_MT_help(Menu):
+ bl_label = "Help"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator(
+ "wm.url_open", text="Manual", icon='HELP',
+ ).url = "https://docs.blender.org/manual/en/dev/"
+ layout.operator(
+ "wm.url_open", text="Release Log", icon='URL',
+ ).url = "http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/%d.%d" % bpy.app.version[:2]
+ layout.separator()
+
+ layout.operator(
+ "wm.url_open", text="Blender Website", icon='URL',
+ ).url = "https://www.blender.org"
+ layout.operator(
+ "wm.url_open", text="Blender Store", icon='URL',
+ ).url = "https://store.blender.org"
+ layout.operator(
+ "wm.url_open", text="Developer Community", icon='URL',
+ ).url = "https://www.blender.org/get-involved/"
+ layout.operator(
+ "wm.url_open", text="User Community", icon='URL',
+ ).url = "https://www.blender.org/support/user-community"
+ layout.separator()
+ layout.operator(
+ "wm.url_open", text="Report a Bug", icon='URL',
+ ).url = "https://developer.blender.org/maniphest/task/edit/form/1"
+ layout.separator()
+
+ layout.operator(
+ "wm.url_open", text="Python API Reference", icon='URL',
+ ).url = bpy.types.WM_OT_doc_view._prefix
+
+ layout.operator("wm.operator_cheat_sheet", icon='TEXT')
+ layout.operator("wm.sysinfo", icon='TEXT')
+ layout.separator()
+
+ layout.operator("wm.splash", icon='BLENDER')
+
+
+class TOPBAR_MT_file_specials(Menu):
+ bl_label = "File Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_AREA'
+ layout.operator("wm.link", text="Link", icon='LINK_BLEND')
+ layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
+
+ layout.separator()
+
+ layout.menu("INFO_MT_file_import", icon='IMPORT')
+ layout.menu("INFO_MT_file_export", icon='EXPORT')
+
+
+class TOPBAR_MT_window_specials(Menu):
+ bl_label = "Window Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'EXEC_AREA'
+
+ layout.operator("wm.window_new")
+ layout.operator("wm.window_new_main")
+
+ layout.operator_context = 'INVOKE_AREA'
+
+ layout.operator("screen.area_dupli")
+
+ layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
+
+ layout.separator()
+
+ layout.operator("screen.area_split", text="Horizontal Split").direction = 'HORIZONTAL'
+ layout.operator("screen.area_split", text="Vertical Split").direction = 'VERTICAL'
+
+ layout.separator()
+
+ layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES')
+
+
+classes = (
+ TOPBAR_HT_upper_bar,
+ TOPBAR_HT_lower_bar,
+ TOPBAR_MT_file_specials,
+ TOPBAR_MT_window_specials,
+ INFO_MT_editor_menus,
+ INFO_MT_file,
+ INFO_MT_file_import,
+ INFO_MT_file_export,
+ INFO_MT_file_external_data,
+ INFO_MT_file_previews,
+ INFO_MT_edit,
+ INFO_MT_game,
+ INFO_MT_render,
+ INFO_MT_opengl_render,
+ INFO_MT_window,
+ INFO_MT_help,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index ee1dcae29a1..806b57e0297 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -22,28 +22,29 @@ from bpy.types import (
Header,
Menu,
Panel,
+ Operator,
)
from bpy.app.translations import pgettext_iface as iface_
from bpy.app.translations import contexts as i18n_contexts
-def opengl_lamp_buttons(column, lamp):
+def opengl_light_buttons(column, light):
split = column.row()
- split.prop(lamp, "use", text="", icon='OUTLINER_OB_LAMP' if lamp.use else 'LAMP_DATA')
+ split.prop(light, "use", text="", icon='OUTLINER_OB_LIGHT' if light.use else 'LIGHT_DATA')
col = split.column()
- col.active = lamp.use
+ col.active = light.use
row = col.row()
row.label(text="Diffuse:")
- row.prop(lamp, "diffuse_color", text="")
+ row.prop(light, "diffuse_color", text="")
row = col.row()
row.label(text="Specular:")
- row.prop(lamp, "specular_color", text="")
+ row.prop(light, "specular_color", text="")
col = split.column()
- col.active = lamp.use
- col.prop(lamp, "direction", text="")
+ col.active = light.use
+ col.prop(light, "direction", text="")
class USERPREF_HT_header(Header):
@@ -52,7 +53,8 @@ class USERPREF_HT_header(Header):
def draw(self, context):
layout = self.layout
- layout.template_header()
+ # No need to show type selector.
+ # layout.template_header()
userpref = context.user_preferences
@@ -61,13 +63,19 @@ class USERPREF_HT_header(Header):
layout.operator_context = 'INVOKE_DEFAULT'
- if userpref.active_section == 'INPUT':
+ if userpref.active_section == 'INTERFACE':
+ layout.operator("wm.save_workspace_file")
+ elif userpref.active_section == 'INPUT':
layout.operator("wm.keyconfig_import")
layout.operator("wm.keyconfig_export")
elif userpref.active_section == 'ADDONS':
layout.operator("wm.addon_install", icon='FILESEL')
layout.operator("wm.addon_refresh", icon='FILE_REFRESH')
layout.menu("USERPREF_MT_addons_online_resources")
+ elif userpref.active_section == 'LIGHTS':
+ layout.operator('wm.studiolight_install', text="Install MatCap").orientation = 'MATCAP'
+ layout.operator('wm.studiolight_install', text="Install World HDRI").orientation = 'WORLD'
+ layout.operator('wm.studiolight_install', text="Install Camera HDRI").orientation = 'CAMERA'
elif userpref.active_section == 'THEMES':
layout.operator("ui.reset_default_theme")
layout.operator("wm.theme_install")
@@ -222,29 +230,44 @@ class USERPREF_PT_interface(Panel):
col.prop(view, "ui_scale", text="Scale")
col.prop(view, "ui_line_width", text="Line Width")
col.prop(view, "show_tooltips")
- col.prop(view, "show_tooltips_python")
- col.prop(view, "show_developer_ui")
col.prop(view, "show_object_info", text="Object Info")
col.prop(view, "show_large_cursors")
col.prop(view, "show_view_name", text="View Name")
col.prop(view, "show_playback_fps", text="Playback FPS")
- col.prop(view, "use_global_scene")
col.prop(view, "object_origin_size")
col.separator()
- col.separator()
- col.separator()
- col.prop(view, "show_mini_axis", text="Display Mini Axis")
- sub = col.column()
- sub.active = view.show_mini_axis
+ # col.prop(view, "show_manipulator_navigate")
+
+ sub = col.column(align=True)
+
+ sub.label("3D Viewport Axis:")
+ sub.row().prop(view, "mini_axis_type", expand=True)
+
+ sub = col.column(align=True)
+ sub.active = view.mini_axis_type == 'MINIMAL'
sub.prop(view, "mini_axis_size", text="Size")
sub.prop(view, "mini_axis_brightness", text="Brightness")
col.separator()
- col.label("Warnings")
- col.prop(view, "use_quit_dialog")
+ # Toolbox doesn't exist yet
+ # col.label(text="Toolbox:")
+ #col.prop(view, "show_column_layout")
+ #col.label(text="Open Toolbox Delay:")
+ #col.prop(view, "open_left_mouse_delay", text="Hold LMB")
+ #col.prop(view, "open_right_mouse_delay", text="Hold RMB")
+ col.prop(view, "show_manipulator", text="Manipulators")
+ sub = col.column()
+ sub.active = view.show_manipulator
+ sub.prop(view, "manipulator_size", text="Size")
+
+ col.separator()
+
+ col.label("Development:")
+ col.prop(view, "show_tooltips_python")
+ col.prop(view, "show_developer_ui")
row.separator()
row.separator()
@@ -256,7 +279,6 @@ class USERPREF_PT_interface(Panel):
col.prop(view, "use_mouse_depth_navigate")
col.prop(view, "use_zoom_to_mouse")
col.prop(view, "use_rotate_around_active")
- col.prop(view, "use_global_pivot")
col.prop(view, "use_camera_lock_parent")
col.separator()
@@ -281,22 +303,6 @@ class USERPREF_PT_interface(Panel):
row.separator()
col = row.column()
- # Toolbox doesn't exist yet
- # col.label(text="Toolbox:")
- #col.prop(view, "show_column_layout")
- #col.label(text="Open Toolbox Delay:")
- #col.prop(view, "open_left_mouse_delay", text="Hold LMB")
- #col.prop(view, "open_right_mouse_delay", text="Hold RMB")
- col.prop(view, "show_manipulator")
- sub = col.column()
- sub.active = view.show_manipulator
- sub.prop(view, "manipulator_size", text="Size")
- sub.prop(view, "manipulator_handle_size", text="Handle Size")
- sub.prop(view, "manipulator_hotspot", text="Hotspot")
-
- col.separator()
- col.separator()
- col.separator()
col.label(text="Menus:")
col.prop(view, "use_mouse_over_open")
@@ -317,6 +323,10 @@ class USERPREF_PT_interface(Panel):
col.separator()
col.prop(view, "show_splash")
+
+ col.label("Warnings:")
+ col.prop(view, "use_quit_dialog")
+
col.separator()
col.label(text="App Template:")
@@ -424,6 +434,7 @@ class USERPREF_PT_edit(Panel):
col.label(text="Transform:")
col.prop(edit, "use_drag_immediately")
+ col.prop(edit, "use_numeric_input_advanced")
row.separator()
row.separator()
@@ -442,7 +453,7 @@ class USERPREF_PT_edit(Panel):
col.prop(edit, "use_duplicate_text", text="Text")
col.prop(edit, "use_duplicate_metaball", text="Metaball")
col.prop(edit, "use_duplicate_armature", text="Armature")
- col.prop(edit, "use_duplicate_lamp", text="Lamp")
+ col.prop(edit, "use_duplicate_light", text="Light")
col.prop(edit, "use_duplicate_material", text="Material")
col.prop(edit, "use_duplicate_texture", text="Texture")
#col.prop(edit, "use_duplicate_fcurve", text="F-Curve")
@@ -477,7 +488,6 @@ class USERPREF_PT_system(Panel):
col = colsplit.column()
col.label(text="General:")
- col.prop(system, "frame_server_port")
col.prop(system, "scrollback", text="Console Scrollback")
col.separator()
@@ -511,24 +521,21 @@ class USERPREF_PT_system(Panel):
col = colsplit.column()
col.label(text="OpenGL:")
col.prop(system, "gl_clip_alpha", slider=True)
- col.prop(system, "use_mipmaps")
col.prop(system, "use_gpu_mipmap")
col.prop(system, "use_16bit_textures")
col.separator()
- col.label(text="Selection")
+ col.label(text="Selection:")
col.prop(system, "select_method", text="")
col.prop(system, "use_select_pick_depth")
col.separator()
- col.label(text="Anisotropic Filtering")
+ col.label(text="Anisotropic Filtering:")
col.prop(system, "anisotropic_filter", text="")
col.separator()
- col.label(text="Window Draw Method:")
- col.prop(system, "window_draw_method", text="")
col.prop(system, "multi_sample", text="")
if sys.platform == "linux" and system.multi_sample != 'NONE':
col.label(text="Might fail for Mesh editing selection!")
@@ -536,6 +543,9 @@ class USERPREF_PT_system(Panel):
col.prop(system, "use_region_overlap")
col.separator()
+ col.prop(system, "gpu_viewport_quality")
+
+ col.separator()
col.label(text="Text Draw Options:")
col.prop(system, "use_text_antialiasing")
@@ -569,14 +579,14 @@ class USERPREF_PT_system(Panel):
split.label(text="Colors:")
split.label(text="Direction:")
- lamp = system.solid_lights[0]
- opengl_lamp_buttons(column, lamp)
+ light = system.solid_lights[0]
+ opengl_light_buttons(column, light)
- lamp = system.solid_lights[1]
- opengl_lamp_buttons(column, lamp)
+ light = system.solid_lights[1]
+ opengl_light_buttons(column, light)
- lamp = system.solid_lights[2]
- opengl_lamp_buttons(column, lamp)
+ light = system.solid_lights[2]
+ opengl_light_buttons(column, light)
column.separator()
@@ -718,6 +728,7 @@ class USERPREF_PT_theme(Panel):
colsub.row().prop(widget_style, "item", slider=True)
colsub.row().prop(widget_style, "inner", slider=True)
colsub.row().prop(widget_style, "inner_sel", slider=True)
+ colsub.row().prop(widget_style, "roundness")
subsplit = row.split(percentage=0.85)
@@ -797,6 +808,9 @@ class USERPREF_PT_theme(Panel):
col.label(text="Tool:")
self._theme_widget_style(col, ui.wcol_tool)
+ col.label(text="Toolbar Item:")
+ self._theme_widget_style(col, ui.wcol_toolbar_item)
+
col.label(text="Radio Buttons:")
self._theme_widget_style(col, ui.wcol_radio)
@@ -845,6 +859,9 @@ class USERPREF_PT_theme(Panel):
col.label(text="List Item:")
self._theme_widget_style(col, ui.wcol_list_item)
+ col.label(text="Tab:")
+ self._theme_widget_style(col, ui.wcol_tab)
+
ui_state = theme.user_interface.wcol_state
col.label(text="State:")
@@ -859,6 +876,7 @@ class USERPREF_PT_theme(Panel):
colsub.row().prop(ui_state, "inner_anim_sel")
colsub.row().prop(ui_state, "inner_driven")
colsub.row().prop(ui_state, "inner_driven_sel")
+ colsub.row().prop(ui_state, "blend")
subsplit = row.split(percentage=0.85)
@@ -867,7 +885,8 @@ class USERPREF_PT_theme(Panel):
colsub = padding.column()
colsub.row().prop(ui_state, "inner_key")
colsub.row().prop(ui_state, "inner_key_sel")
- colsub.row().prop(ui_state, "blend")
+ colsub.row().prop(ui_state, "inner_overridden")
+ colsub.row().prop(ui_state, "inner_overridden_sel")
col.separator()
col.separator()
@@ -882,34 +901,22 @@ class USERPREF_PT_theme(Panel):
colsub = padding.column()
colsub = padding.column()
colsub.row().prop(ui, "menu_shadow_fac")
-
- subsplit = row.split(percentage=0.85)
-
- padding = subsplit.split(percentage=0.15)
- colsub = padding.column()
- colsub = padding.column()
- colsub.row().prop(ui, "menu_shadow_width")
-
- row = col.row()
-
- subsplit = row.split(percentage=0.95)
-
- padding = subsplit.split(percentage=0.15)
- colsub = padding.column()
- colsub = padding.column()
colsub.row().prop(ui, "icon_alpha")
+ colsub.row().prop(ui, "icon_saturation")
+ colsub.row().prop(ui, "editor_outline")
subsplit = row.split(percentage=0.85)
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
+ colsub.row().prop(ui, "menu_shadow_width")
colsub.row().prop(ui, "widget_emboss")
col.separator()
col.separator()
- col.label("Axis Colors:")
+ col.label("Axis & Manipulator Colors:")
row = col.row()
@@ -927,9 +934,13 @@ class USERPREF_PT_theme(Panel):
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
+ colsub.row().prop(ui, "manipulator_primary")
+ colsub.row().prop(ui, "manipulator_secondary")
+ colsub.row().prop(ui, "manipulator_a")
+ colsub.row().prop(ui, "manipulator_b")
- layout.separator()
- layout.separator()
+ col.separator()
+ col.separator()
elif theme.theme_area == 'BONE_COLOR_SETS':
col = split.column()
@@ -1426,12 +1437,13 @@ class USERPREF_PT_addons(Panel):
continue
# check if addon should be visible with current filters
- if ((filter == "All") or
- (filter == info["category"]) or
- (filter == "Enabled" and is_enabled) or
+ if (
+ (filter == "All") or
+ (filter == info["category"]) or
+ (filter == "Enabled" and is_enabled) or
(filter == "Disabled" and not is_enabled) or
(filter == "User" and (mod.__file__.startswith((scripts_addons_folder, userpref_addons_folder))))
- ):
+ ):
if search and search not in info["name"].lower():
if info["author"]:
if search not in info["author"].lower():
@@ -1460,7 +1472,14 @@ class USERPREF_PT_addons(Panel):
sub = row.row()
sub.active = is_enabled
sub.label(text="%s: %s" % (info["category"], info["name"]))
- if info["warning"]:
+
+ # WARNING: 2.8x exception, may be removed
+ # use disabled state for old add-ons, chances are they are broken.
+ if info.get("blender", (0,)) < (2, 80):
+ sub.label(text="upgrade to 2.8x required")
+ sub.label(icon='ERROR')
+ # Remove code above after 2.8x migration is complete.
+ elif info["warning"]:
sub.label(icon='ERROR')
# icon showing support level.
@@ -1565,6 +1584,62 @@ class USERPREF_PT_addons(Panel):
row.label(text=module_name, translate=False)
+class StudioLightPanelMixin():
+ bl_space_type = 'USER_PREFERENCES'
+ bl_region_type = 'WINDOW'
+
+ @classmethod
+ def poll(cls, context):
+ userpref = context.user_preferences
+ return (userpref.active_section == 'LIGHTS')
+
+ def _get_lights(self, userpref):
+ return [light for light in userpref.studio_lights if light.is_user_defined and light.orientation == self.sl_orientation]
+
+ def draw_header(self, context):
+ layout = self.layout
+ row = layout.row()
+ userpref = context.user_preferences
+ lights = self._get_lights(userpref)
+ row.label("({})".format(len(lights)))
+
+ def draw(self, context):
+ layout = self.layout
+ userpref = context.user_preferences
+ lights = self._get_lights(userpref)
+ if lights:
+ flow = layout.column_flow(4)
+ for studio_light in lights:
+ self.draw_studio_light(flow, studio_light)
+ else:
+ layout.label("No custom {} configured".format(self.bl_label))
+
+ def draw_studio_light(self, layout, studio_light):
+ box = layout.box()
+ row = box.row()
+
+ row.template_icon(layout.icon(studio_light), scale=6.0)
+ op = row.operator('wm.studiolight_uninstall', text="", icon='ZOOMOUT')
+ op.index = studio_light.index
+
+ box.label(text=studio_light.name)
+
+
+class USERPREF_PT_studiolight_matcaps(Panel, StudioLightPanelMixin):
+ bl_label = "MatCaps"
+ sl_orientation = 'MATCAP'
+
+
+class USERPREF_PT_studiolight_world(Panel, StudioLightPanelMixin):
+ bl_label = "World HDRI"
+ sl_orientation = 'WORLD'
+
+
+class USERPREF_PT_studiolight_camera(Panel, StudioLightPanelMixin):
+ bl_label = "Camera HDRI"
+ sl_orientation = 'CAMERA'
+
+
classes = (
USERPREF_HT_header,
USERPREF_PT_tabs,
@@ -1585,6 +1660,9 @@ classes = (
USERPREF_PT_input,
USERPREF_MT_addons_online_resources,
USERPREF_PT_addons,
+ USERPREF_PT_studiolight_matcaps,
+ USERPREF_PT_studiolight_world,
+ USERPREF_PT_studiolight_camera,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 0a365c6a20c..f9b69b8de66 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -34,117 +34,192 @@ class VIEW3D_HT_header(Header):
layout = self.layout
view = context.space_data
+ shading = view.shading
# mode_string = context.mode
obj = context.active_object
- toolsettings = context.tool_settings
+ overlay = view.overlay
+ tool_settings = context.tool_settings
row = layout.row(align=True)
row.template_header()
- VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
+ object_mode = 'OBJECT' if obj is None else obj.mode
+
+ act_mode_item = bpy.types.Object.bl_rna.properties["mode"].enum_items[object_mode]
+ layout.operator_menu_enum("object.mode_set", "mode", text=act_mode_item.name, icon=act_mode_item.icon)
+ del act_mode_item
+
+ layout.template_header_3D_mode()
# Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode...
- row = layout
- layout.template_header_3D()
+ shading_type = view.shading.type
+ shading_item = bpy.types.View3DShading.bl_rna.properties["type"].enum_items[shading_type]
if obj:
- mode = obj.mode
+ # Set above:
+ # object_mode = obj.mode
+
# Particle edit
- if mode == 'PARTICLE_EDIT':
- row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
+ if object_mode == 'PARTICLE_EDIT':
+ row = layout.row()
+ row.prop(tool_settings.particle_edit, "select_mode", text="", expand=True)
# Occlude geometry
- if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
- (mode in {'WEIGHT_PAINT', 'VERTEX_PAINT'})):
+ if (
+ (((shading.type not in {'SOLID', 'TEXTURED'}) or not shading.show_xray) and
+ (object_mode == 'PARTICLE_EDIT' or (object_mode == 'EDIT' and obj.type == 'MESH'))) or
+ (object_mode in {'WEIGHT_PAINT', 'VERTEX_PAINT'})
+ ):
+ row = layout.row()
row.prop(view, "use_occlude_geometry", text="")
- # Proportional editing
- if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
- row = layout.row(align=True)
- row.prop(toolsettings, "proportional_edit", icon_only=True)
- if toolsettings.proportional_edit != 'DISABLED':
- row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
- elif mode in {'EDIT', 'PARTICLE_EDIT'}:
- row = layout.row(align=True)
- row.prop(toolsettings, "proportional_edit", icon_only=True)
- if toolsettings.proportional_edit != 'DISABLED':
- row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
- elif mode == 'OBJECT':
- row = layout.row(align=True)
- row.prop(toolsettings, "use_proportional_edit_objects", icon_only=True)
- if toolsettings.use_proportional_edit_objects:
- row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
- else:
- # Proportional editing
- if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
- row = layout.row(align=True)
- row.prop(toolsettings, "proportional_edit", icon_only=True)
- if toolsettings.proportional_edit != 'DISABLED':
- row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
+ # Pose
+ if obj and object_mode == 'POSE':
+ row = layout.row(align=True)
+ row.operator("pose.copy", text="", icon='COPYDOWN')
+ row.operator("pose.paste", text="", icon='PASTEDOWN').flipped = False
+ row.operator("pose.paste", text="", icon='PASTEFLIPDOWN').flipped = True
+
+ # GPencil
+ if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.operator("gpencil.copy", text="", icon='COPYDOWN')
+ row.operator("gpencil.paste", text="", icon='PASTEDOWN')
+
+ # XXX: icon
+ layout.prop(context.gpencil_data, "use_onion_skinning", text="Onion Skins", icon='PARTICLE_PATH')
+
+ row = layout.row(align=True)
+ row.prop(tool_settings.gpencil_sculpt, "use_select_mask")
+ row.prop(tool_settings.gpencil_sculpt, "selection_alpha", slider=True)
+
+ VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
+
+ layout.separator_spacer()
+
+ # Mode & Transform Settings
+ scene = context.scene
+
+ # Orientation
+ if object_mode in {'OBJECT', 'EDIT', 'POSE'}:
+ orientation = scene.transform_orientation
+ current_orientation = scene.current_orientation
+
+ if not current_orientation:
+ trans_orientation = \
+ bpy.types.Scene.bl_rna.properties["transform_orientation"].enum_items[orientation]
+ trans_icon = getattr(trans_orientation, "icon", "BLANK1")
+ trans_name = getattr(trans_orientation, "name", "Orientation")
+ else:
+ trans_icon = 'VISIBLE_IPO_OFF'
+ trans_name = getattr(current_orientation, "name", "Orientation")
+
+ row = layout.row(align=True)
+ row.popover(
+ panel="VIEW3D_PT_transform_orientations",
+ text=trans_name,
+ icon=trans_icon,
+ )
# Snap
show_snap = False
if obj is None:
show_snap = True
else:
- if mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT'}:
+ if object_mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT'}:
show_snap = True
else:
+
+ from .properties_paint_common import UnifiedPaintPanel
paint_settings = UnifiedPaintPanel.paint_settings(context)
+
if paint_settings:
brush = paint_settings.brush
if brush and brush.stroke_method == 'CURVE':
show_snap = True
if show_snap:
- snap_element = toolsettings.snap_element
- row = layout.row(align=True)
- row.prop(toolsettings, "use_snap", text="")
- row.prop(toolsettings, "snap_element", icon_only=True)
- if snap_element == 'INCREMENT':
- row.prop(toolsettings, "use_snap_grid_absolute", text="")
+ snap_items = bpy.types.ToolSettings.bl_rna.properties['snap_elements'].enum_items
+ for elem in tool_settings.snap_elements:
+ # TODO: Display multiple icons.
+ # (Currently only one of the enabled modes icons is displayed)
+ icon = snap_items[elem].icon
+ break
else:
- row.prop(toolsettings, "snap_target", text="")
- if obj:
- if mode == 'EDIT':
- row.prop(toolsettings, "use_snap_self", text="")
- if mode in {'OBJECT', 'POSE', 'EDIT'} and snap_element != 'VOLUME':
- row.prop(toolsettings, "use_snap_align_rotation", text="")
-
- if snap_element == 'VOLUME':
- row.prop(toolsettings, "use_snap_peel_object", text="")
- elif snap_element == 'FACE':
- row.prop(toolsettings, "use_snap_project", text="")
-
- # AutoMerge editing
+ icon = 'NONE'
+
+ row = layout.row(align=True)
+ row.prop(tool_settings, "use_snap", text="")
+
+ sub = row.row(align=True)
+ sub.popover(
+ panel="VIEW3D_PT_snapping",
+ icon=icon,
+ text="",
+ )
+
+ # Proportional editing
if obj:
- if (mode == 'EDIT' and obj.type == 'MESH'):
- layout.prop(toolsettings, "use_mesh_automerge", text="", icon='AUTOMERGE_ON')
+ if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.prop(tool_settings, "proportional_edit", icon_only=True)
- # OpenGL render
- row = layout.row(align=True)
- row.operator("render.opengl", text="", icon='RENDER_STILL')
- row.operator("render.opengl", text="", icon='RENDER_ANIMATION').animation = True
+ sub = row.row(align=True)
+ sub.active = tool_settings.proportional_edit != 'DISABLED'
+ sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
- # Pose
- if obj and mode == 'POSE':
- row = layout.row(align=True)
- row.operator("pose.copy", text="", icon='COPYDOWN')
- row.operator("pose.paste", text="", icon='PASTEDOWN').flipped = False
- row.operator("pose.paste", text="", icon='PASTEFLIPDOWN').flipped = True
+ elif object_mode in {'EDIT', 'PARTICLE_EDIT'}:
+ row = layout.row(align=True)
+ row.prop(tool_settings, "proportional_edit", icon_only=True)
+ sub = row.row(align=True)
+ sub.active = tool_settings.proportional_edit != 'DISABLED'
+ sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
- # GPencil
- if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
+ elif object_mode == 'OBJECT':
+ row = layout.row(align=True)
+ row.prop(tool_settings, "use_proportional_edit_objects", icon_only=True)
+ sub = row.row(align=True)
+ sub.active = tool_settings.use_proportional_edit_objects
+ sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
+ else:
+ if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.prop(tool_settings, "proportional_edit", icon_only=True)
+ sub = row.row(align=True)
+ sub.active = tool_settings.proportional_edit != 'DISABLED'
+ sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
+
+ # Pivot
+ if object_mode in {'OBJECT', 'EDIT', 'POSE'}:
+ pivot_point = tool_settings.transform_pivot_point
+ act_pivot_point = bpy.types.ToolSettings.bl_rna.properties["transform_pivot_point"].enum_items[pivot_point]
row = layout.row(align=True)
- row.operator("gpencil.copy", text="", icon='COPYDOWN')
- row.operator("gpencil.paste", text="", icon='PASTEDOWN')
+ row.popover(
+ panel="VIEW3D_PT_pivot_point",
+ icon=act_pivot_point.icon,
+ text="",
+ )
- # XXX: icon
- layout.prop(context.gpencil_data, "use_onion_skinning", text="Onion Skins", icon='PARTICLE_PATH')
+ layout.separator_spacer()
- row = layout.row(align=True)
- row.prop(context.tool_settings.gpencil_sculpt, "use_select_mask")
- row.prop(context.tool_settings.gpencil_sculpt, "selection_alpha", slider=True)
+ # Viewport Settings
+ layout.popover(
+ panel="VIEW3D_PT_object_type_visibility",
+ icon_value=view.icon_from_show_object_viewport,
+ text="",
+ )
+
+ row = layout.row(align=True)
+ row.prop(overlay, "show_overlays", icon='WIRE', text="")
+ sub = row.row(align=True)
+ sub.active = overlay.show_overlays
+ sub.popover(panel="VIEW3D_PT_overlay")
+
+ row = layout.row(align=True)
+ row.prop(shading, "type", text="", expand=True)
+ sub = row.row(align=True)
+ sub.enabled = shading.type != 'RENDERED'
+ sub.popover(panel="VIEW3D_PT_shading")
class VIEW3D_MT_editor_menus(Menu):
@@ -194,6 +269,12 @@ class VIEW3D_MT_editor_menus(Menu):
layout.menu("VIEW3D_MT_edit_gpencil")
elif edit_object:
layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())
+
+ if mode_string == 'EDIT_MESH':
+ layout.menu("VIEW3D_MT_edit_mesh_vertices")
+ layout.menu("VIEW3D_MT_edit_mesh_edges")
+ layout.menu("VIEW3D_MT_edit_mesh_faces")
+
elif obj:
if mode_string != 'PAINT_TEXTURE':
layout.menu("VIEW3D_MT_%s" % mode_string.lower())
@@ -232,15 +313,6 @@ class VIEW3D_MT_transform_base(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("transform.translate", text="Grab/Move")
- # TODO: sub-menu for grab per axis
- layout.operator("transform.rotate", text="Rotate")
- # TODO: sub-menu for rot per axis
- layout.operator("transform.resize", text="Scale")
- # TODO: sub-menu for scale per axis
-
- layout.separator()
-
layout.operator("transform.tosphere", text="To Sphere")
layout.operator("transform.shear", text="Shear")
layout.operator("transform.bend", text="Bend")
@@ -301,6 +373,12 @@ class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base):
layout.operator("object.randomize_transform")
layout.operator("object.align")
+ # TODO: there is a strange context bug here.
+ """
+ layout.operator_context = 'INVOKE_REGION_WIN'
+ layout.operator("object.transform_axis_target")
+ """
+
# Armature EditMode extensions to Transform menu
class VIEW3D_MT_transform_armature(VIEW3D_MT_transform_base):
@@ -416,6 +494,11 @@ class VIEW3D_MT_uv_map(Menu):
layout.operator("uv.reset")
+ layout.separator()
+
+ layout.operator("mesh.uvs_rotate")
+ layout.operator("mesh.uvs_reverse")
+
class VIEW3D_MT_edit_proportional(Menu):
bl_label = "Proportional Editing"
@@ -423,12 +506,12 @@ class VIEW3D_MT_edit_proportional(Menu):
def draw(self, context):
layout = self.layout
- layout.props_enum(context.tool_settings, "proportional_edit")
+ layout.props_enum(tool_settings, "proportional_edit")
layout.separator()
layout.label("Falloff:")
- layout.props_enum(context.tool_settings, "proportional_edit_falloff")
+ layout.props_enum(tool_settings, "proportional_edit_falloff")
# ********** View menus **********
@@ -441,18 +524,17 @@ class VIEW3D_MT_view(Menu):
layout = self.layout
view = context.space_data
- layout.operator("view3d.properties", icon='MENU_PANEL')
layout.operator("view3d.toolshelf", icon='MENU_PANEL')
+ layout.operator("view3d.properties", icon='MENU_PANEL')
layout.separator()
- layout.operator("view3d.view_selected").use_all_regions = False
+ layout.operator("view3d.view_selected", text="Frame Selected").use_all_regions = False
if view.region_quadviews:
- layout.operator("view3d.view_selected", text="View Selected (Quad View)").use_all_regions = True
+ layout.operator("view3d.view_selected", text="Frame Selected (Quad View)").use_all_regions = True
- layout.operator("view3d.view_all").center = False
- layout.operator("view3d.localview", text="View Global/Local")
- layout.operator("view3d.view_persportho")
+ layout.operator("view3d.view_all", text="Frame All").center = False
+ layout.operator("view3d.view_persportho", text="Perspective/Orthographic")
layout.separator()
@@ -470,18 +552,16 @@ class VIEW3D_MT_view(Menu):
layout.separator()
- layout.operator("view3d.layers", text="Show All Layers").nr = 0
+ layout.operator("screen.animation_play", text="Play Animation")
layout.separator()
- layout.operator("screen.animation_play", text="Playback Animation")
+ layout.operator("render.opengl", icon='RENDER_STILL')
+ layout.operator("render.opengl", text="OpenGL Render Animation", icon='RENDER_ANIMATION').animation = True
layout.separator()
- layout.operator("screen.area_dupli")
- layout.operator("screen.region_quadview")
- layout.operator("screen.screen_full_area")
- layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+ layout.menu("INFO_MT_area")
class VIEW3D_MT_view_cameras(Menu):
@@ -491,7 +571,7 @@ class VIEW3D_MT_view_cameras(Menu):
layout = self.layout
layout.operator("view3d.object_as_camera")
- layout.operator("view3d.viewnumpad", text="Active Camera").type = 'CAMERA'
+ layout.operator("view3d.view_camera", text="Active Camera")
class VIEW3D_MT_view_viewpoint(Menu):
@@ -500,22 +580,22 @@ class VIEW3D_MT_view_viewpoint(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.viewnumpad", text="Camera").type = 'CAMERA'
+ layout.operator("view3d.view_camera", text="Camera")
layout.separator()
- layout.operator("view3d.viewnumpad", text="Top").type = 'TOP'
- layout.operator("view3d.viewnumpad", text="Bottom").type = 'BOTTOM'
+ layout.operator("view3d.view_axis", text="Top").type = 'TOP'
+ layout.operator("view3d.view_axis", text="Bottom").type = 'BOTTOM'
layout.separator()
- layout.operator("view3d.viewnumpad", text="Front").type = 'FRONT'
- layout.operator("view3d.viewnumpad", text="Back").type = 'BACK'
+ layout.operator("view3d.view_axis", text="Front").type = 'FRONT'
+ layout.operator("view3d.view_axis", text="Back").type = 'BACK'
layout.separator()
- layout.operator("view3d.viewnumpad", text="Right").type = 'RIGHT'
- layout.operator("view3d.viewnumpad", text="Left").type = 'LEFT'
+ layout.operator("view3d.view_axis", text="Right").type = 'RIGHT'
+ layout.operator("view3d.view_axis", text="Left").type = 'LEFT'
class VIEW3D_MT_view_navigation(Menu):
@@ -579,27 +659,27 @@ class VIEW3D_MT_view_align_selected(Menu):
def draw(self, context):
layout = self.layout
- props = layout.operator("view3d.viewnumpad", text="Top")
+ props = layout.operator("view3d.view_axis", text="Top")
props.align_active = True
props.type = 'TOP'
- props = layout.operator("view3d.viewnumpad", text="Bottom")
+ props = layout.operator("view3d.view_axis", text="Bottom")
props.align_active = True
props.type = 'BOTTOM'
- props = layout.operator("view3d.viewnumpad", text="Front")
+ props = layout.operator("view3d.view_axis", text="Front")
props.align_active = True
props.type = 'FRONT'
- props = layout.operator("view3d.viewnumpad", text="Back")
+ props = layout.operator("view3d.view_axis", text="Back")
props.align_active = True
props.type = 'BACK'
- props = layout.operator("view3d.viewnumpad", text="Right")
+ props = layout.operator("view3d.view_axis", text="Right")
props.align_active = True
props.type = 'RIGHT'
- props = layout.operator("view3d.viewnumpad", text="Left")
+ props = layout.operator("view3d.view_axis", text="Left")
props.align_active = True
props.type = 'LEFT'
@@ -610,7 +690,7 @@ class VIEW3D_MT_view_borders(Menu):
def draw(self, context):
layout = self.layout
layout.operator("view3d.clip_border", text="Clipping Border...")
- layout.operator("view3d.render_border", text="Render Border...").camera_only = False
+ layout.operator("view3d.render_border", text="Render Border...")
layout.separator()
@@ -657,21 +737,21 @@ class VIEW3D_MT_select_object(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
+ layout.operator("object.select_all", text="All").action = 'SELECT'
+ layout.operator("object.select_all", text="None").action = 'DESELECT'
+ layout.operator("object.select_all", text="Invert").action = 'INVERT'
layout.separator()
- layout.operator("object.select_all").action = 'TOGGLE'
- layout.operator("object.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
- layout.operator("object.select_random", text="Random")
- layout.operator("object.select_mirror", text="Mirror")
- layout.operator("object.select_by_layer", text="Select All by Layer")
layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
- layout.operator("object.select_camera", text="Select Camera")
+ layout.operator("object.select_camera", text="Select Active Camera")
+ layout.operator("object.select_mirror", text="Mirror Selection")
+ layout.operator("object.select_random", text="Select Random")
layout.separator()
@@ -679,8 +759,8 @@ class VIEW3D_MT_select_object(Menu):
layout.separator()
- layout.operator_menu_enum("object.select_grouped", "type", text="Grouped")
- layout.operator_menu_enum("object.select_linked", "type", text="Linked")
+ layout.operator_menu_enum("object.select_grouped", "type", text="Select Grouped")
+ layout.operator_menu_enum("object.select_linked", "type", text="Select Linked")
layout.operator("object.select_pattern", text="Select Pattern...")
@@ -717,13 +797,17 @@ class VIEW3D_MT_select_pose(Menu):
def draw(self, context):
layout = self.layout
+ layout.operator("pose.select_all", text="All").action = 'SELECT'
+ layout.operator("pose.select_all", text="None").action = 'DESELECT'
+ layout.operator("pose.select_all", text="Invert").action = 'INVERT'
+
+ layout.separator()
+
layout.operator("view3d.select_border")
layout.operator("view3d.select_circle")
layout.separator()
- layout.operator("pose.select_all").action = 'TOGGLE'
- layout.operator("pose.select_all", text="Inverse").action = 'INVERT'
layout.operator("pose.select_mirror", text="Flip Active")
layout.separator()
@@ -747,14 +831,18 @@ class VIEW3D_MT_select_particle(Menu):
def draw(self, context):
layout = self.layout
+ layout.operator("particle.select_all", text="All").action = 'SELECT'
+ layout.operator("particle.select_all", text="None").action = 'DESELECT'
+ layout.operator("particle.select_all", text="Invert").action = 'INVERT'
+
+ layout.separator()
+
layout.operator("view3d.select_border")
layout.operator("view3d.select_circle")
layout.separator()
- layout.operator("particle.select_all").action = 'TOGGLE'
layout.operator("particle.select_linked")
- layout.operator("particle.select_all", text="Inverse").action = 'INVERT'
layout.separator()
@@ -789,7 +877,8 @@ class VIEW3D_MT_edit_mesh_select_by_trait(Menu):
def draw(self, context):
layout = self.layout
- if context.scene.tool_settings.mesh_select_mode[2] is False:
+ tool_settings = context.tool_settings
+ if tool_settings.mesh_select_mode[2] is False:
layout.operator("mesh.select_non_manifold", text="Non Manifold")
layout.operator("mesh.select_loose", text="Loose Geometry")
layout.operator("mesh.select_interior_faces", text="Interior Faces")
@@ -847,25 +936,26 @@ class VIEW3D_MT_select_edit_mesh(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
+ # primitive
+ layout.operator("mesh.select_all", text="All").action = 'SELECT'
+ layout.operator("mesh.select_all", text="None").action = 'DESELECT'
+ layout.operator("mesh.select_all", text="Invert").action = 'INVERT'
layout.separator()
- # primitive
- layout.operator("mesh.select_all").action = 'TOGGLE'
- layout.operator("mesh.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
# numeric
- layout.operator("mesh.select_random", text="Random")
+ layout.operator("mesh.select_random", text="Select Random")
layout.operator("mesh.select_nth")
layout.separator()
# geometric
- layout.operator("mesh.edges_select_sharp", text="Sharp Edges")
+ layout.operator("mesh.edges_select_sharp", text="Select Sharp Edges")
layout.separator()
@@ -891,7 +981,7 @@ class VIEW3D_MT_select_edit_mesh(Menu):
layout.separator()
layout.operator("mesh.select_axis", text="Side of Active")
- layout.operator("mesh.select_mirror", text="Mirror")
+ layout.operator("mesh.select_mirror", text="Mirror Selection")
class VIEW3D_MT_select_edit_curve(Menu):
@@ -900,13 +990,14 @@ class VIEW3D_MT_select_edit_curve(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
+ layout.operator("curve.select_all", text="All").action = 'SELECT'
+ layout.operator("curve.select_all", text="None").action = 'DESELECT'
+ layout.operator("curve.select_all", text="Invert").action = 'INVERT'
layout.separator()
- layout.operator("curve.select_all").action = 'TOGGLE'
- layout.operator("curve.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
@@ -934,13 +1025,14 @@ class VIEW3D_MT_select_edit_surface(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
+ layout.operator("curve.select_all", text="All").action = 'SELECT'
+ layout.operator("curve.select_all", text="None").action = 'DESELECT'
+ layout.operator("curve.select_all", text="Invert").action = 'INVERT'
layout.separator()
- layout.operator("curve.select_all").action = 'TOGGLE'
- layout.operator("curve.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
@@ -967,10 +1059,6 @@ class VIEW3D_MT_select_edit_text(Menu):
def draw(self, context):
layout = self.layout
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
layout.operator("font.text_paste", text="Paste")
layout.operator("font.text_cut", text="Cut")
layout.operator("font.text_copy", text="Copy")
@@ -990,13 +1078,14 @@ class VIEW3D_MT_select_edit_metaball(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
+ layout.operator("mball.select_all", text="All").action = 'SELECT'
+ layout.operator("mball.select_all", text="None").action = 'DESELECT'
+ layout.operator("mball.select_all", text="Invert").action = 'INVERT'
layout.separator()
- layout.operator("mball.select_all").action = 'TOGGLE'
- layout.operator("mball.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
@@ -1013,13 +1102,14 @@ class VIEW3D_MT_select_edit_lattice(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
+ layout.operator("lattice.select_all", text="All").action = 'SELECT'
+ layout.operator("lattice.select_all", text="None").action = 'DESELECT'
+ layout.operator("lattice.select_all", text="Invert").action = 'INVERT'
layout.separator()
- layout.operator("lattice.select_all").action = 'TOGGLE'
- layout.operator("lattice.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
@@ -1037,13 +1127,17 @@ class VIEW3D_MT_select_edit_armature(Menu):
def draw(self, context):
layout = self.layout
+ layout.operator("armature.select_all", text="All").action = 'SELECT'
+ layout.operator("armature.select_all", text="None").action = 'DESELECT'
+ layout.operator("armature.select_all", text="Invert").action = 'INVERT'
+
+ layout.separator()
+
layout.operator("view3d.select_border")
layout.operator("view3d.select_circle")
layout.separator()
- layout.operator("armature.select_all").action = 'TOGGLE'
- layout.operator("armature.select_all", text="Inverse").action = 'INVERT'
layout.operator("armature.select_mirror", text="Mirror").extend = False
layout.separator()
@@ -1081,13 +1175,14 @@ class VIEW3D_MT_select_gpencil(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("gpencil.select_border")
- layout.operator("gpencil.select_circle")
+ layout.operator("gpencil.select_all", text="All").action = 'SELECT'
+ layout.operator("gpencil.select_all", text="None").action = 'DESELECT'
+ layout.operator("gpencil.select_all", text="Invert").action = 'INVERT'
layout.separator()
- layout.operator("gpencil.select_all", text="(De)select All").action = 'TOGGLE'
- layout.operator("gpencil.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("gpencil.select_border")
+ layout.operator("gpencil.select_circle")
layout.separator()
@@ -1111,13 +1206,14 @@ class VIEW3D_MT_select_paint_mask(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
+ layout.operator("paint.face_select_all", text="All").action = 'SELECT'
+ layout.operator("paint.face_select_all", text="None").action = 'DESELECT'
+ layout.operator("paint.face_select_all", text="Invert").action = 'INVERT'
layout.separator()
- layout.operator("paint.face_select_all").action = 'TOGGLE'
- layout.operator("paint.face_select_all", text="Inverse").action = 'INVERT'
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
@@ -1130,13 +1226,14 @@ class VIEW3D_MT_select_paint_mask_vertex(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
+ layout.operator("paint.vert_select_all", text="All").action = 'SELECT'
+ layout.operator("paint.vert_select_all", text="None").action = 'DESELECT'
+ layout.operator("paint.vert_select_all", text="Invert").action = 'INVERT'
layout.separator()
- layout.operator("paint.vert_select_all").action = 'TOGGLE'
- layout.operator("paint.vert_select_all", text="Inverse").action = 'INVERT'
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
@@ -1183,13 +1280,23 @@ class INFO_MT_mesh_add(Menu):
bl_label = "Mesh"
def draw(self, context):
- from .space_view3d_toolbar import VIEW3D_PT_tools_add_object
-
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- VIEW3D_PT_tools_add_object.draw_add_mesh(layout)
+ layout.operator("mesh.primitive_plane_add", text="Plane", icon='MESH_PLANE')
+ layout.operator("mesh.primitive_cube_add", text="Cube", icon='MESH_CUBE')
+ layout.operator("mesh.primitive_circle_add", text="Circle", icon='MESH_CIRCLE')
+ layout.operator("mesh.primitive_uv_sphere_add", text="UV Sphere", icon='MESH_UVSPHERE')
+ layout.operator("mesh.primitive_ico_sphere_add", text="Ico Sphere", icon='MESH_ICOSPHERE')
+ layout.operator("mesh.primitive_cylinder_add", text="Cylinder", icon='MESH_CYLINDER')
+ layout.operator("mesh.primitive_cone_add", text="Cone", icon='MESH_CONE')
+ layout.operator("mesh.primitive_torus_add", text="Torus", icon='MESH_TORUS')
+
+ layout.separator()
+
+ layout.operator("mesh.primitive_grid_add", text="Grid", icon='MESH_GRID')
+ layout.operator("mesh.primitive_monkey_add", text="Monkey", icon='MESH_MONKEY')
class INFO_MT_curve_add(Menu):
@@ -1197,12 +1304,22 @@ class INFO_MT_curve_add(Menu):
bl_label = "Curve"
def draw(self, context):
- from .space_view3d_toolbar import VIEW3D_PT_tools_add_object
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- VIEW3D_PT_tools_add_object.draw_add_curve(layout)
+ layout.operator("curve.primitive_bezier_curve_add", text="Bezier", icon='CURVE_BEZCURVE')
+ layout.operator("curve.primitive_bezier_circle_add", text="Circle", icon='CURVE_BEZCIRCLE')
+
+ layout.separator()
+
+ layout.operator("curve.primitive_nurbs_curve_add", text="Nurbs Curve", icon='CURVE_NCURVE')
+ layout.operator("curve.primitive_nurbs_circle_add", text="Nurbs Circle", icon='CURVE_NCIRCLE')
+ layout.operator("curve.primitive_nurbs_path_add", text="Path", icon='CURVE_PATH')
+
+ layout.separator()
+
+ layout.operator("curve.draw", icon='LINE_DATA')
class INFO_MT_surface_add(Menu):
@@ -1210,12 +1327,17 @@ class INFO_MT_surface_add(Menu):
bl_label = "Surface"
def draw(self, context):
- from .space_view3d_toolbar import VIEW3D_PT_tools_add_object
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- VIEW3D_PT_tools_add_object.draw_add_surface(layout)
+ layout.operator("surface.primitive_nurbs_surface_curve_add", text="Nurbs Curve", icon='SURFACE_NCURVE')
+ layout.operator("surface.primitive_nurbs_surface_circle_add", text="Nurbs Circle", icon='SURFACE_NCIRCLE')
+ layout.operator("surface.primitive_nurbs_surface_surface_add", text="Nurbs Surface", icon='SURFACE_NSURFACE')
+ layout.operator("surface.primitive_nurbs_surface_cylinder_add",
+ text="Nurbs Cylinder", icon='SURFACE_NCYLINDER')
+ layout.operator("surface.primitive_nurbs_surface_sphere_add", text="Nurbs Sphere", icon='SURFACE_NSPHERE')
+ layout.operator("surface.primitive_nurbs_surface_torus_add", text="Nurbs Torus", icon='SURFACE_NTORUS')
class INFO_MT_metaball_add(Menu):
@@ -1267,15 +1389,26 @@ class INFO_MT_armature_add(Menu):
layout.operator("object.armature_add", text="Single Bone", icon='BONE_DATA')
-class INFO_MT_lamp_add(Menu):
- bl_idname = "INFO_MT_lamp_add"
- bl_label = "Lamp"
+class INFO_MT_light_add(Menu):
+ bl_idname = "INFO_MT_light_add"
+ bl_label = "Light"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator_enum("object.lamp_add", "type")
+ layout.operator_enum("object.light_add", "type")
+
+
+class INFO_MT_lightprobe_add(Menu):
+ bl_idname = "INFO_MT_lightprobe_add"
+ bl_label = "Light Probe"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_REGION_WIN'
+ layout.operator_enum("object.lightprobe_add", "type")
class INFO_MT_camera_add(Menu):
@@ -1324,39 +1457,34 @@ class INFO_MT_add(Menu):
else:
INFO_MT_camera_add.draw(self, context)
- layout.menu("INFO_MT_lamp_add", icon='OUTLINER_OB_LAMP')
+ layout.menu("INFO_MT_light_add", icon='OUTLINER_OB_LIGHT')
+ layout.separator()
+ layout.menu("INFO_MT_lightprobe_add", icon='OUTLINER_OB_LIGHTPROBE')
layout.separator()
layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_FORCE_FIELD')
layout.separator()
- if len(bpy.data.groups) > 10:
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("object.group_instance_add", text="Group Instance...", icon='OUTLINER_OB_GROUP_INSTANCE')
+ has_collections = bool(bpy.data.collections)
+ col = layout.column()
+ col.enabled = has_collections
+
+ if not has_collections or len(bpy.data.collections) > 10:
+ col.operator_context = 'INVOKE_REGION_WIN'
+ col.operator(
+ "object.collection_instance_add",
+ text="Collection Instance..." if has_collections else "No Collections to Instance",
+ icon='OUTLINER_OB_GROUP_INSTANCE',
+ )
else:
- layout.operator_menu_enum(
- "object.group_instance_add",
- "group",
- text="Group Instance",
+ col.operator_menu_enum(
+ "object.collection_instance_add",
+ "collection",
+ text="Collection Instance",
icon='OUTLINER_OB_GROUP_INSTANCE',
)
-class VIEW3D_MT_undo_redo(Menu):
- bl_label = "Undo/Redo"
- _operator_name = ""
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("ed.undo")
- layout.operator("ed.redo")
-
- layout.separator()
-
- layout.operator("ed.undo_history")
-
-
class VIEW3D_MT_object_relations(Menu):
bl_label = "Relations"
@@ -1384,26 +1512,11 @@ class VIEW3D_MT_object(Menu):
def draw(self, context):
layout = self.layout
- view = context.space_data
- is_local_view = (view.local_view is not None)
-
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
- layout.operator("object.delete", text="Delete...").use_global = False
-
- layout.separator()
layout.menu("VIEW3D_MT_transform_object")
layout.menu("VIEW3D_MT_mirror")
layout.menu("VIEW3D_MT_object_clear")
layout.menu("VIEW3D_MT_object_apply")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_object_parent")
- layout.menu("VIEW3D_MT_object_group")
layout.menu("VIEW3D_MT_snap")
layout.separator()
@@ -1411,22 +1524,30 @@ class VIEW3D_MT_object(Menu):
layout.operator("object.duplicate_move")
layout.operator("object.duplicate_move_linked")
layout.operator("object.join")
- if is_local_view:
- layout.operator_context = 'EXEC_REGION_WIN'
- layout.operator("object.move_to_layer", text="Move out of Local View")
- layout.operator_context = 'INVOKE_REGION_WIN'
- else:
- layout.operator("object.move_to_layer", text="Move to Layer...")
layout.separator()
- layout.menu("VIEW3D_MT_make_links", text="Make Links...")
+
+ layout.operator("view3d.copybuffer", text="Copy Objects")
+ layout.operator("view3d.pastebuffer", text="Paste Objects")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_object_parent")
+ layout.menu("VIEW3D_MT_object_collection")
layout.menu("VIEW3D_MT_object_relations")
layout.menu("VIEW3D_MT_object_constraints")
layout.menu("VIEW3D_MT_object_track")
+ layout.menu("VIEW3D_MT_make_links", text="Make Links...")
+
+ layout.separator()
+
+ layout.operator("object.shade_smooth", text="Smooth Shading")
+ layout.operator("object.shade_flat", text="Flat Shading")
layout.separator()
layout.menu("VIEW3D_MT_object_animation")
+ layout.menu("VIEW3D_MT_object_rigid_body")
layout.separator()
@@ -1434,13 +1555,15 @@ class VIEW3D_MT_object(Menu):
layout.separator()
- layout.menu("VIEW3D_MT_object_game")
+ layout.operator_menu_enum("object.convert", "target")
layout.separator()
layout.menu("VIEW3D_MT_object_showhide")
- layout.operator_menu_enum("object.convert", "target")
+ layout.separator()
+
+ layout.operator("object.delete", text="Delete...").use_global = False
class VIEW3D_MT_object_animation(Menu):
@@ -1459,6 +1582,32 @@ class VIEW3D_MT_object_animation(Menu):
layout.operator("nla.bake", text="Bake Action...")
+class VIEW3D_MT_object_rigid_body(Menu):
+ bl_label = "Rigid Body"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("rigidbody.objects_add", text="Add Active").type = 'ACTIVE'
+ layout.operator("rigidbody.objects_add", text="Add Passive").type = 'PASSIVE'
+
+ layout.separator()
+
+ layout.operator("rigidbody.objects_remove", text="Remove")
+
+ layout.separator()
+
+ layout.operator("rigidbody.shape_change", text="Change Shape")
+ layout.operator("rigidbody.mass_calculate", text="Calculate Mass")
+ layout.operator("rigidbody.object_settings_copy", text="Copy from Active")
+ layout.operator("object.visual_transform_apply", text="Apply Transformation")
+ layout.operator("rigidbody.bake_to_keyframes", text="Bake To Keyframes")
+
+ layout.separator()
+
+ layout.operator("rigidbody.connect", text="Connect")
+
+
class VIEW3D_MT_object_clear(Menu):
bl_label = "Clear"
@@ -1475,7 +1624,7 @@ class VIEW3D_MT_object_clear(Menu):
class VIEW3D_MT_object_specials(Menu):
- bl_label = "Specials"
+ bl_label = "Object Context Menu"
@classmethod
def poll(cls, context):
@@ -1488,6 +1637,42 @@ class VIEW3D_MT_object_specials(Menu):
scene = context.scene
obj = context.object
+ layout.operator("view3d.copybuffer", text="Copy Objects", icon='COPYDOWN')
+ layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN')
+
+ layout.separator()
+
+ layout.operator("object.duplicate_move")
+ layout.operator("object.duplicate_move_linked")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_snap")
+ layout.menu("VIEW3D_MT_object_parent")
+ layout.operator_context = 'INVOKE_REGION_WIN'
+ layout.operator("object.move_to_collection")
+
+ layout.separator()
+
+ layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
+
+ layout.separator()
+
+ layout.operator("object.delete", text="Delete...").use_global = False
+
+ if obj.type == 'MESH':
+
+ layout.separator()
+
+ layout.operator("object.shade_smooth", text="Smooth Shading")
+ layout.operator("object.shade_flat", text="Flat Shading")
+
+ layout.separator()
+
+ layout.operator("object.origin_set")
+ layout.operator("object.join")
+ layout.operator_menu_enum("object.convert", "target")
+
if obj.type == 'CAMERA':
layout.operator_context = 'INVOKE_REGION_WIN'
@@ -1544,59 +1729,46 @@ class VIEW3D_MT_object_specials(Menu):
props.input_scale = 0.01
props.header_text = "Empty Draw Size: %.3f"
- if obj.type == 'LAMP':
- lamp = obj.data
+ if obj.type == 'LIGHT':
+ light = obj.data
layout.operator_context = 'INVOKE_REGION_WIN'
- if scene.render.use_shading_nodes:
- emission_node = None
- if lamp.node_tree:
- for node in lamp.node_tree.nodes:
- if getattr(node, "type", None) == 'EMISSION':
- emission_node = node
- break
+ emission_node = None
+ if light.node_tree:
+ for node in light.node_tree.nodes:
+ if getattr(node, "type", None) == 'EMISSION':
+ emission_node = node
+ break
- if emission_node is not None:
- props = layout.operator("wm.context_modal_mouse", text="Strength")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.node_tree" \
- ".nodes[\"" + emission_node.name + "\"]" \
- ".inputs[\"Strength\"].default_value"
- props.header_text = "Lamp Strength: %.3f"
- props.input_scale = 0.1
-
- if lamp.type == 'AREA':
- props = layout.operator("wm.context_modal_mouse", text="Size X")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.size"
- props.header_text = "Lamp Size X: %.3f"
-
- if lamp.shape == 'RECTANGLE':
- props = layout.operator("wm.context_modal_mouse", text="Size Y")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.size_y"
- props.header_text = "Lamp Size Y: %.3f"
+ if emission_node is not None:
+ props = layout.operator("wm.context_modal_mouse", text="Strength")
+ props.data_path_iter = "selected_editable_objects"
+ props.data_path_item = "data.node_tree" \
+ ".nodes[\"" + emission_node.name + "\"]" \
+ ".inputs[\"Strength\"].default_value"
+ props.header_text = "Light Strength: %.3f"
+ props.input_scale = 0.1
- elif lamp.type in {'SPOT', 'POINT', 'SUN'}:
- props = layout.operator("wm.context_modal_mouse", text="Size")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.shadow_soft_size"
- props.header_text = "Lamp Size: %.3f"
- else:
- props = layout.operator("wm.context_modal_mouse", text="Energy")
+ if light.type == 'AREA':
+ props = layout.operator("wm.context_modal_mouse", text="Size X")
props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.energy"
- props.header_text = "Lamp Energy: %.3f"
+ props.data_path_item = "data.size"
+ props.header_text = "Light Size X: %.3f"
- if lamp.type in {'SPOT', 'AREA', 'POINT'}:
- props = layout.operator("wm.context_modal_mouse", text="Falloff Distance")
+ if light.shape in {'RECTANGLE', 'ELLIPSE'}:
+ props = layout.operator("wm.context_modal_mouse", text="Size Y")
props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.distance"
- props.input_scale = 0.1
- props.header_text = "Lamp Falloff Distance: %.1f"
+ props.data_path_item = "data.size_y"
+ props.header_text = "Light Size Y: %.3f"
+
+ elif light.type in {'SPOT', 'POINT', 'SUN'}:
+ props = layout.operator("wm.context_modal_mouse", text="Size")
+ props.data_path_iter = "selected_editable_objects"
+ props.data_path_item = "data.shadow_soft_size"
+ props.header_text = "Light Size: %.3f"
- if lamp.type == 'SPOT':
+ if light.type == 'SPOT':
layout.separator()
props = layout.operator("wm.context_modal_mouse", text="Spot Size")
props.data_path_iter = "selected_editable_objects"
@@ -1610,23 +1782,15 @@ class VIEW3D_MT_object_specials(Menu):
props.input_scale = -0.01
props.header_text = "Spot Blend: %.2f"
- if not scene.render.use_shading_nodes:
- props = layout.operator("wm.context_modal_mouse", text="Clip Start")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.shadow_buffer_clip_start"
- props.input_scale = 0.05
- props.header_text = "Clip Start: %.2f"
-
- props = layout.operator("wm.context_modal_mouse", text="Clip End")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.shadow_buffer_clip_end"
- props.input_scale = 0.05
- props.header_text = "Clip End: %.2f"
- layout.separator()
+class VIEW3D_MT_object_shading(Menu):
+ # XXX, this menu is a place to store shading operator in object mode
+ bl_label = "Shading"
- props = layout.operator("object.isolate_type_render")
- props = layout.operator("object.hide_render_clear_all")
+ def draw(self, context):
+ layout = self.layout
+ layout.operator("object.shade_smooth", text="Smooth")
+ layout.operator("object.shade_flat", text="Flat")
class VIEW3D_MT_object_apply(Menu):
@@ -1712,21 +1876,21 @@ class VIEW3D_MT_object_track(Menu):
layout.operator_enum("object.track_clear", "type")
-class VIEW3D_MT_object_group(Menu):
- bl_label = "Group"
+class VIEW3D_MT_object_collection(Menu):
+ bl_label = "Collection"
def draw(self, context):
layout = self.layout
- layout.operator("group.create")
- # layout.operator_menu_enum("group.objects_remove", "group") # BUGGY
- layout.operator("group.objects_remove")
- layout.operator("group.objects_remove_all")
+ layout.operator("collection.create")
+ # layout.operator_menu_enum("collection.objects_remove", "collection") # BUGGY
+ layout.operator("collection.objects_remove")
+ layout.operator("collection.objects_remove_all")
layout.separator()
- layout.operator("group.objects_add_active")
- layout.operator("group.objects_remove_active")
+ layout.operator("collection.objects_add_active")
+ layout.operator("collection.objects_remove_active")
class VIEW3D_MT_object_constraints(Menu):
@@ -1777,23 +1941,23 @@ class VIEW3D_MT_make_single_user(Menu):
props = layout.operator("object.make_single_user", text="Object")
props.object = True
- props.obdata = props.material = props.texture = props.animation = False
+ props.obdata = props.material = props.animation = False
props = layout.operator("object.make_single_user", text="Object & Data")
props.object = props.obdata = True
- props.material = props.texture = props.animation = False
+ props.material = props.animation = False
- props = layout.operator("object.make_single_user", text="Object & Data & Materials+Tex")
- props.object = props.obdata = props.material = props.texture = True
+ props = layout.operator("object.make_single_user", text="Object & Data & Materials")
+ props.object = props.obdata = props.material = True
props.animation = False
- props = layout.operator("object.make_single_user", text="Materials+Tex")
- props.material = props.texture = True
+ props = layout.operator("object.make_single_user", text="Materials")
+ props.material = True
props.object = props.obdata = props.animation = False
props = layout.operator("object.make_single_user", text="Object Animation")
props.animation = True
- props.object = props.obdata = props.material = props.texture = False
+ props.object = props.obdata = props.material = False
class VIEW3D_MT_make_links(Menu):
@@ -1819,36 +1983,17 @@ class VIEW3D_MT_make_links(Menu):
layout.operator("object.join_uvs") # stupid place to add this!
-class VIEW3D_MT_object_game(Menu):
- bl_label = "Game"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("object.logic_bricks_copy", text="Copy Logic Bricks")
- layout.operator("object.game_physics_copy", text="Copy Physics Properties")
-
- layout.separator()
-
- layout.operator("object.game_property_copy", text="Replace Properties").operation = 'REPLACE'
- layout.operator("object.game_property_copy", text="Merge Properties").operation = 'MERGE'
- layout.operator_menu_enum("object.game_property_copy", "property", text="Copy Properties...")
-
- layout.separator()
-
- layout.operator("object.game_property_clear")
-
-
class VIEW3D_MT_brush(Menu):
bl_label = "Brush"
def draw(self, context):
layout = self.layout
+ tool_settings = context.tool_settings
settings = UnifiedPaintPanel.paint_settings(context)
brush = getattr(settings, "brush", None)
- ups = context.tool_settings.unified_paint_settings
+ ups = tool_settings.unified_paint_settings
layout.prop(ups, "use_unified_size", text="Unified Size")
layout.prop(ups, "use_unified_strength", text="Unified Strength")
if context.image_paint_object or context.vertex_paint_object:
@@ -1915,10 +2060,6 @@ class VIEW3D_MT_paint_vertex(Menu):
def draw(self, context):
layout = self.layout
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
layout.operator("paint.vertex_color_set")
layout.operator("paint.vertex_color_smooth")
layout.operator("paint.vertex_color_dirt")
@@ -1987,17 +2128,15 @@ class VIEW3D_MT_vertex_group(Menu):
class VIEW3D_MT_paint_weight(Menu):
bl_label = "Weights"
- def draw(self, context):
- layout = self.layout
-
- layout.menu("VIEW3D_MT_undo_redo")
+ @staticmethod
+ def draw_generic(layout, is_editmode=False):
- layout.separator()
+ if not is_editmode:
- layout.operator("paint.weight_from_bones", text="Assign Automatic From Bones").type = 'AUTOMATIC'
- layout.operator("paint.weight_from_bones", text="Assign From Bone Envelopes").type = 'ENVELOPES'
+ layout.operator("paint.weight_from_bones", text="Assign Automatic From Bones").type = 'AUTOMATIC'
+ layout.operator("paint.weight_from_bones", text="Assign From Bone Envelopes").type = 'ENVELOPES'
- layout.separator()
+ layout.separator()
layout.operator("object.vertex_group_normalize_all", text="Normalize All")
layout.operator("object.vertex_group_normalize", text="Normalize")
@@ -2014,16 +2153,21 @@ class VIEW3D_MT_paint_weight(Menu):
layout.operator("object.vertex_group_levels", text="Levels")
layout.operator("object.vertex_group_smooth", text="Smooth")
- props = layout.operator("object.data_transfer", text="Transfer Weights")
- props.use_reverse_transfer = True
- props.data_type = 'VGROUP_WEIGHTS'
+ if not is_editmode:
+ props = layout.operator("object.data_transfer", text="Transfer Weights")
+ props.use_reverse_transfer = True
+ props.data_type = 'VGROUP_WEIGHTS'
layout.operator("object.vertex_group_limit_total", text="Limit Total")
layout.operator("object.vertex_group_fix", text="Fix Deforms")
- layout.separator()
+ if not is_editmode:
+ layout.separator()
- layout.operator("paint.weight_set")
+ layout.operator("paint.weight_set")
+
+ def draw(self, context):
+ self.draw_generic(self.layout, is_editmode=False)
class VIEW3D_MT_sculpt(Menu):
@@ -2032,12 +2176,8 @@ class VIEW3D_MT_sculpt(Menu):
def draw(self, context):
layout = self.layout
- toolsettings = context.tool_settings
- sculpt = toolsettings.sculpt
-
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
+ tool_settings = context.tool_settings
+ sculpt = tool_settings.sculpt
layout.prop(sculpt, "use_symmetry_x")
layout.prop(sculpt, "use_symmetry_y")
@@ -2103,16 +2243,9 @@ class VIEW3D_MT_particle(Menu):
def draw(self, context):
layout = self.layout
+ tool_settings = context.tool_settings
- particle_edit = context.tool_settings.particle_edit
-
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
- layout.operator("particle.delete")
-
- layout.separator()
+ particle_edit = tool_settings.particle_edit
layout.operator("particle.mirror")
@@ -2131,14 +2264,19 @@ class VIEW3D_MT_particle(Menu):
layout.menu("VIEW3D_MT_particle_showhide")
+ layout.separator()
+
+ layout.operator("particle.delete")
+
class VIEW3D_MT_particle_specials(Menu):
- bl_label = "Specials"
+ bl_label = "Particle Context Menu"
def draw(self, context):
layout = self.layout
+ tool_settings = context.tool_settings
- particle_edit = context.tool_settings.particle_edit
+ particle_edit = tool_settings.particle_edit
layout.operator("particle.rekey")
@@ -2162,6 +2300,13 @@ class VIEW3D_MT_particle_specials(Menu):
if particle_edit.select_mode == 'POINT':
layout.separator()
+
+ layout.operator("particle.select_all", text="All").action = 'SELECT'
+ layout.operator("particle.select_all", text="None").action = 'DESELECT'
+ layout.operator("particle.select_all", text="Invert").action = 'INVERT'
+
+ layout.separator()
+
layout.operator("particle.select_roots")
layout.operator("particle.select_tips")
@@ -2176,9 +2321,7 @@ class VIEW3D_MT_particle_specials(Menu):
layout.separator()
- layout.operator("particle.select_all").action = 'TOGGLE'
layout.operator("particle.select_linked")
- layout.operator("particle.select_all", text="Inverse").action = 'INVERT'
class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
@@ -2191,10 +2334,6 @@ class VIEW3D_MT_pose(Menu):
def draw(self, context):
layout = self.layout
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
layout.menu("VIEW3D_MT_transform_armature")
layout.menu("VIEW3D_MT_pose_transform")
@@ -2387,30 +2526,41 @@ class VIEW3D_MT_pose_apply(Menu):
class VIEW3D_MT_pose_specials(Menu):
- bl_label = "Specials"
+ bl_label = "Pose Context Menu"
def draw(self, context):
layout = self.layout
- layout.operator("paint.weight_from_bones", text="Assign Automatic from Bones").type = 'AUTOMATIC'
- layout.operator("paint.weight_from_bones", text="Assign from Bone Envelopes").type = 'ENVELOPES'
+ layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
+
+ layout.separator()
+
+ layout.operator("pose.copy")
+ layout.operator("pose.paste").flipped = False
+ layout.operator("pose.paste", text="Paste X-Flipped Pose").flipped = True
layout.separator()
layout.operator("pose.select_constraint_target")
- layout.operator("pose.flip_names")
+
+ layout.separator()
+
+ layout.operator("pose.paths_calculate", text="Calculate")
+ layout.operator("pose.paths_clear", text="Clear")
layout.separator()
layout.operator("pose.paths_calculate")
layout.operator("pose.paths_clear")
- layout.operator("pose.user_transforms_clear")
- layout.operator("pose.user_transforms_clear", text="Clear User Transforms (All)").only_selected = False
- layout.operator("pose.relax")
layout.separator()
- layout.operator_menu_enum("pose.autoside_names", "axis")
+ layout.operator("pose.hide").unselected = False
+ layout.operator("pose.reveal")
+
+ layout.separator()
+
+ layout.operator("pose.user_transforms_clear")
class BoneOptions:
@@ -2466,16 +2616,9 @@ class VIEW3D_MT_edit_mesh(Menu):
def draw(self, context):
layout = self.layout
+ tool_settings = context.tool_settings
- toolsettings = context.tool_settings
-
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_edit_mesh_delete")
-
- layout.separator()
+ with_bullet = bpy.app.build_options.bullet
layout.menu("VIEW3D_MT_transform")
layout.menu("VIEW3D_MT_mirror")
@@ -2487,85 +2630,124 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.separator()
- layout.operator("mesh.duplicate_move")
+ layout.operator("mesh.duplicate_move", text="Duplicate")
layout.menu("VIEW3D_MT_edit_mesh_extrude")
+ layout.operator("mesh.split")
+ layout.operator("mesh.bisect")
- layout.separator()
-
- layout.menu("VIEW3D_MT_edit_mesh_vertices")
- layout.menu("VIEW3D_MT_edit_mesh_edges")
- layout.menu("VIEW3D_MT_edit_mesh_faces")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_edit_mesh_normals")
- layout.menu("VIEW3D_MT_edit_mesh_clean")
+ if with_bullet:
+ layout.operator("mesh.convex_hull")
layout.separator()
layout.operator("mesh.symmetrize")
layout.operator("mesh.symmetry_snap")
- layout.operator("mesh.bisect")
- layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...")
layout.separator()
- layout.prop(toolsettings, "use_mesh_automerge")
- layout.menu("VIEW3D_MT_edit_proportional")
+ layout.menu("VIEW3D_MT_edit_mesh_normals")
+ layout.menu("VIEW3D_MT_edit_mesh_shading")
+ layout.menu("VIEW3D_MT_edit_mesh_weights")
+ layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...")
layout.separator()
layout.menu("VIEW3D_MT_edit_mesh_showhide")
+ layout.operator_menu_enum("mesh.separate", "type")
+ layout.menu("VIEW3D_MT_edit_mesh_clean")
+ layout.menu("VIEW3D_MT_edit_mesh_delete")
class VIEW3D_MT_edit_mesh_specials(Menu):
- bl_label = "Specials"
+ bl_label = "Mesh Context Menu"
def draw(self, context):
layout = self.layout
+ select_mode = context.tool_settings.mesh_select_mode
+
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("mesh.subdivide", text="Subdivide").smoothness = 0.0
- layout.operator("mesh.subdivide", text="Subdivide Smooth").smoothness = 1.0
+ layout.operator("mesh.subdivide", text="Subdivide")
layout.separator()
- layout.operator("mesh.merge", text="Merge...")
- layout.operator("mesh.remove_doubles")
+ layout.operator("mesh.duplicate_move", text="Duplicate")
- layout.separator()
+ # Vertex Select Commands
+ if select_mode[0]:
+ layout.separator()
- layout.operator("mesh.hide", text="Hide").unselected = False
- layout.operator("mesh.reveal", text="Reveal")
- layout.operator("mesh.select_all", text="Select Inverse").action = 'INVERT'
+ layout.operator("mesh.edge_face_add", text="New Edge/Face from Vertices")
+ layout.operator("mesh.vert_connect_path", text="Connect Vertex Path")
+ layout.operator("mesh.vert_connect", text="Connect Vertex Pairs")
- layout.separator()
+ layout.separator()
- layout.operator("mesh.flip_normals")
- layout.operator("mesh.vertices_smooth", text="Smooth")
- layout.operator("mesh.vertices_smooth_laplacian", text="Laplacian Smooth")
+ layout.operator("mesh.vertices_smooth", text="Smooth")
+ layout.operator("mesh.vertices_smooth_laplacian", text="Smooth Laplacian")
- layout.separator()
+ layout.separator()
+ layout.operator("mesh.merge", text="Merge Vertices...")
+ layout.operator("mesh.remove_doubles", text="Remove Double Vertices")
+ layout.operator("mesh.dissolve_verts")
+ layout.operator("mesh.delete", text="Delete Vertices").type = 'VERT'
- layout.operator("mesh.inset")
- layout.operator("mesh.bevel", text="Bevel")
- layout.operator("mesh.bridge_edge_loops")
+ # Edge Select Commands
+ if select_mode[1]:
+ layout.separator()
- layout.separator()
+ layout.operator("mesh.bridge_edge_loops", text="Bridge Edge Loops")
- layout.operator("mesh.faces_shade_smooth")
- layout.operator("mesh.faces_shade_flat")
+ layout.separator()
+
+ layout.operator("mesh.dissolve_edges")
+ layout.operator("mesh.delete", text="Delete Edges").type = 'EDGE'
+
+ # Face Select Commands
+ if select_mode[2]:
+ layout.separator()
+
+ layout.operator("mesh.faces_shade_smooth")
+ layout.operator("mesh.faces_shade_flat")
+
+ layout.separator()
+
+ layout.operator("mesh.bridge_edge_loops", text="Bridge Faces")
+
+ layout.separator()
+
+ layout.operator("mesh.poke")
+
+ layout.separator()
+
+ props = layout.operator("mesh.quads_convert_to_tris")
+ props.quad_method = props.ngon_method = 'BEAUTY'
+ layout.operator("mesh.tris_convert_to_quads")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_uv_map", text="UV Unwrap Faces...")
+
+ layout.separator()
+
+ layout.operator("mesh.dissolve_faces")
+ layout.operator("mesh.delete", text="Delete Faces").type = 'FACE'
+
+ # General Mesh Commands
layout.separator()
- layout.operator("mesh.blend_from_shape")
- layout.operator("mesh.shape_propagate_to_all")
- layout.operator("mesh.shortest_path_select")
- layout.operator("mesh.sort_elements")
+ layout.menu("VIEW3D_MT_snap", text="Snap...")
+ layout.operator("transform.mirror", text="Mirror")
layout.operator("mesh.symmetrize")
layout.operator("mesh.symmetry_snap")
+ layout.separator()
+
+ layout.operator("mesh.hide", text="Hide").unselected = False
+ layout.operator("mesh.reveal", text="Reveal")
+
class VIEW3D_MT_edit_mesh_select_mode(Menu):
bl_label = "Mesh Select Mode"
@@ -2584,21 +2766,22 @@ class VIEW3D_MT_edit_mesh_extrude(Menu):
_extrude_funcs = {
'VERT': lambda layout:
- layout.operator("mesh.extrude_vertices_move", text="Vertices Only"),
+ layout.operator("mesh.extrude_vertices_move", text="Extrude Vertices"),
'EDGE': lambda layout:
- layout.operator("mesh.extrude_edges_move", text="Edges Only"),
- 'FACE': lambda layout:
- layout.operator("mesh.extrude_faces_move", text="Individual Faces"),
+ layout.operator("mesh.extrude_edges_move", text="Extrude Edges"),
'REGION': lambda layout:
- layout.operator("view3d.edit_mesh_extrude_move_normal", text="Region"),
+ layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces"),
'REGION_VERT_NORMAL': lambda layout:
- layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Region (Vertex Normals)"),
+ layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals"),
+ 'FACE': lambda layout:
+ layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces"),
}
@staticmethod
def extrude_options(context):
+ tool_settings = context.tool_settings
+ select_mode = tool_settings.mesh_select_mode
mesh = context.object.data
- select_mode = context.tool_settings.mesh_select_mode
menu = []
if mesh.total_face_sel:
@@ -2620,45 +2803,43 @@ class VIEW3D_MT_edit_mesh_extrude(Menu):
class VIEW3D_MT_edit_mesh_vertices(Menu):
- bl_label = "Vertices"
+ bl_label = "Vertex"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- with_bullet = bpy.app.build_options.bullet
+ layout.operator("mesh.extrude_vertices_move", text="Extrude Vertices"),
+ layout.operator("mesh.bevel", text="Bevel Vertices").vertex_only = True
- layout.operator("mesh.merge")
- layout.operator("mesh.remove_doubles")
- props = layout.operator("mesh.rip_move")
- props.MESH_OT_rip.use_fill = False
- props = layout.operator("mesh.rip_move", text="Rip Fill")
- props.MESH_OT_rip.use_fill = True
- layout.operator("mesh.rip_edge_move")
- layout.operator("mesh.split")
- layout.operator_menu_enum("mesh.separate", "type")
+ layout.separator()
+
+ layout.operator("mesh.edge_face_add", text="New Edge/Face from Vertices")
layout.operator("mesh.vert_connect_path", text="Connect Vertex Path")
- layout.operator("mesh.vert_connect", text="Connect Vertices")
- layout.operator("transform.vert_slide", text="Slide")
+ layout.operator("mesh.vert_connect", text="Connect Vertex Pairs")
layout.separator()
- layout.operator("mesh.mark_sharp", text="Mark Sharp Edges").use_verts = True
- props = layout.operator("mesh.mark_sharp", text="Clear Sharp Edges")
- props.use_verts = True
- props.clear = True
+ props = layout.operator("mesh.rip_move", text="Rip Vertices")
+ props.MESH_OT_rip.use_fill = False
+ props = layout.operator("mesh.rip_move", text="Rip Vertices and Fill")
+ props.MESH_OT_rip.use_fill = True
+ layout.operator("mesh.rip_edge_move", text="Rip Vertices and Extend")
layout.separator()
- layout.operator("mesh.bevel").vertex_only = True
- if with_bullet:
- layout.operator("mesh.convex_hull")
- layout.operator("mesh.vertices_smooth")
+ layout.operator("transform.vert_slide", text="Slide Vertices")
+ layout.operator("mesh.vertices_smooth", text="Smooth Vertices")
+
+ layout.separator()
layout.operator("mesh.blend_from_shape")
+ layout.operator("mesh.shape_propagate_to_all", text="Propagate to Shapes")
+
+ layout.separator()
- layout.operator("object.vertex_group_smooth")
- layout.operator("mesh.shape_propagate_to_all")
+ layout.operator("mesh.merge", text="Merge Vertices")
+ layout.operator("mesh.remove_doubles", text="Remove Double Vertices")
layout.separator()
@@ -2693,6 +2874,13 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu):
layout.operator("mesh.mark_sharp")
layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
+ layout.operator("mesh.mark_sharp", text="Mark Sharp from Vertices").use_verts = True
+ props = layout.operator("mesh.mark_sharp", text="Clear Sharp from Vertices")
+ props.use_verts = True
+ props.clear = True
+
+ layout.separator()
+
layout.separator()
if with_freestyle:
@@ -2702,21 +2890,22 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu):
class VIEW3D_MT_edit_mesh_edges(Menu):
- bl_label = "Edges"
+ bl_label = "Edge"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("mesh.edge_face_add")
- layout.operator("mesh.subdivide")
- layout.operator("mesh.subdivide_edgering")
- layout.operator("mesh.unsubdivide")
+ layout.operator("mesh.extrude_edges_move", text="Extrude Edges"),
+ layout.operator("mesh.bevel", text="Bevel Edges").vertex_only = False
+ layout.operator("mesh.bridge_edge_loops")
layout.separator()
- layout.menu("VIEW3D_MT_edit_mesh_edges_data")
+ layout.operator("mesh.subdivide")
+ layout.operator("mesh.subdivide_edgering")
+ layout.operator("mesh.unsubdivide")
layout.separator()
@@ -2725,22 +2914,16 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.separator()
- layout.operator("mesh.bevel").vertex_only = False
+ layout.operator("transform.edge_slide")
layout.operator("mesh.edge_split")
- layout.operator("mesh.bridge_edge_loops")
layout.separator()
- layout.operator("transform.edge_slide")
- layout.operator("mesh.loop_multi_select", text="Edge Loops").ring = False
- layout.operator("mesh.loop_multi_select", text="Edge Rings").ring = True
- layout.operator("mesh.loop_to_region")
- layout.operator("mesh.region_to_loop")
+ layout.menu("VIEW3D_MT_edit_mesh_edges_data")
-class VIEW3D_MT_edit_mesh_faces(Menu):
- bl_label = "Faces"
- bl_idname = "VIEW3D_MT_edit_mesh_faces"
+class VIEW3D_MT_edit_mesh_faces_data(Menu):
+ bl_label = "Face Data"
def draw(self, context):
layout = self.layout
@@ -2749,48 +2932,69 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("mesh.flip_normals")
- layout.operator("mesh.edge_face_add")
- layout.operator("mesh.fill")
- layout.operator("mesh.fill_grid")
- layout.operator("mesh.beautify_fill")
- layout.operator("mesh.inset")
- layout.operator("mesh.bevel").vertex_only = False
- layout.operator("mesh.solidify")
- layout.operator("mesh.intersect")
- layout.operator("mesh.intersect_boolean")
- layout.operator("mesh.wireframe")
+ layout.operator("mesh.colors_rotate")
+ layout.operator("mesh.colors_reverse")
+
+ layout.separator()
+
+ layout.operator("mesh.uvs_rotate")
+ layout.operator("mesh.uvs_reverse")
layout.separator()
if with_freestyle:
layout.operator("mesh.mark_freestyle_face").clear = False
layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True
- layout.separator()
+
+class VIEW3D_MT_edit_mesh_faces(Menu):
+ bl_label = "Face"
+ bl_idname = "VIEW3D_MT_edit_mesh_faces"
+
+ def draw(self, context):
+ layout = self.layout
+
+ with_freestyle = bpy.app.build_options.freestyle
+
+ layout.operator_context = 'INVOKE_REGION_WIN'
+
+ layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces"),
+ layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals"),
+ layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces"),
+
+ layout.separator()
+
+ layout.operator("mesh.inset")
layout.operator("mesh.poke")
props = layout.operator("mesh.quads_convert_to_tris")
props.quad_method = props.ngon_method = 'BEAUTY'
layout.operator("mesh.tris_convert_to_quads")
- layout.operator("mesh.face_split_by_edges")
+ layout.operator("mesh.solidify", text="Solidify Faces")
+ layout.operator("mesh.wireframe")
layout.separator()
- layout.operator("mesh.faces_shade_smooth")
- layout.operator("mesh.faces_shade_flat")
+ layout.operator("mesh.fill")
+ layout.operator("mesh.fill_grid")
+ layout.operator("mesh.beautify_fill")
- layout.operator("mesh.normals_make_consistent", text="Recalculate Normals").inside = False
+ layout.separator()
+
+ layout.operator("mesh.intersect")
+ layout.operator("mesh.intersect_boolean")
layout.separator()
- layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False
+ layout.operator("mesh.face_split_by_edges")
layout.separator()
- layout.operator("mesh.uvs_rotate")
- layout.operator("mesh.uvs_reverse")
- layout.operator("mesh.colors_rotate")
- layout.operator("mesh.colors_reverse")
+ layout.operator("mesh.faces_shade_smooth")
+ layout.operator("mesh.faces_shade_flat")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_edit_mesh_faces_data")
class VIEW3D_MT_edit_mesh_normals(Menu):
@@ -2805,6 +3009,37 @@ class VIEW3D_MT_edit_mesh_normals(Menu):
layout.separator()
layout.operator("mesh.flip_normals")
+ layout.operator("mesh.set_normals_from_faces", text="Set From Faces")
+
+
+class VIEW3D_MT_edit_mesh_shading(Menu):
+ bl_label = "Shading"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("mesh.faces_shade_smooth", text="Smooth Faces")
+ layout.operator("mesh.faces_shade_flat", text="Flat Faces")
+
+ layout.separator()
+
+ layout.operator("mesh.mark_sharp", text="Smooth Edges").clear = True
+ layout.operator("mesh.mark_sharp", text="Sharp Edges")
+
+ layout.separator()
+
+ props = layout.operator("mesh.mark_sharp", text="Smooth Vertices")
+ props.use_verts = True
+ props.clear = True
+
+ layout.operator("mesh.mark_sharp", text="Sharp Vertices").use_verts = True
+
+
+class VIEW3D_MT_edit_mesh_weights(Menu):
+ bl_label = "Weights"
+
+ def draw(self, context):
+ VIEW3D_MT_paint_weight.draw_generic(self.layout, is_editmode=True)
class VIEW3D_MT_edit_mesh_clean(Menu):
@@ -2882,14 +3117,6 @@ class VIEW3D_MT_edit_gpencil_delete(Menu):
def draw_curve(self, context):
layout = self.layout
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_edit_curve_delete")
-
- layout.separator()
-
layout.menu("VIEW3D_MT_transform")
layout.menu("VIEW3D_MT_mirror")
layout.menu("VIEW3D_MT_snap")
@@ -2914,15 +3141,9 @@ def draw_curve(self, context):
layout.separator()
- layout.menu("VIEW3D_MT_edit_curve_clean")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_edit_proportional")
-
- layout.separator()
-
layout.menu("VIEW3D_MT_edit_curve_showhide")
+ layout.menu("VIEW3D_MT_edit_curve_clean")
+ layout.menu("VIEW3D_MT_edit_curve_delete")
class VIEW3D_MT_edit_curve(Menu):
@@ -2977,7 +3198,7 @@ class VIEW3D_MT_edit_curve_clean(Menu):
class VIEW3D_MT_edit_curve_specials(Menu):
- bl_label = "Specials"
+ bl_label = "Curve Context Menu"
def draw(self, context):
layout = self.layout
@@ -3024,9 +3245,6 @@ class VIEW3D_MT_edit_font(Menu):
def draw(self, context):
layout = self.layout
- # Break convention of having undo menu here,
- # instead place in "Edit" menu, matching the text menu.
-
layout.menu("VIEW3D_MT_edit_text_chars")
layout.separator()
@@ -3086,14 +3304,6 @@ class VIEW3D_MT_edit_meta(Menu):
def draw(self, context):
layout = self.layout
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
- layout.operator("mball.delete_metaelems", text="Delete...")
-
- layout.separator()
-
layout.menu("VIEW3D_MT_transform")
layout.menu("VIEW3D_MT_mirror")
layout.menu("VIEW3D_MT_snap")
@@ -3104,11 +3314,8 @@ class VIEW3D_MT_edit_meta(Menu):
layout.separator()
- layout.menu("VIEW3D_MT_edit_proportional")
-
- layout.separator()
-
layout.menu("VIEW3D_MT_edit_meta_showhide")
+ layout.operator("mball.delete_metaelems", text="Delete...")
class VIEW3D_MT_edit_meta_showhide(Menu):
@@ -3128,8 +3335,6 @@ class VIEW3D_MT_edit_lattice(Menu):
def draw(self, context):
layout = self.layout
- layout.menu("VIEW3D_MT_undo_redo")
-
layout.separator()
layout.menu("VIEW3D_MT_transform")
@@ -3145,10 +3350,6 @@ class VIEW3D_MT_edit_lattice(Menu):
layout.operator("object.vertex_parent_set")
- layout.separator()
-
- layout.menu("VIEW3D_MT_edit_proportional")
-
class VIEW3D_MT_edit_armature(Menu):
bl_label = "Armature"
@@ -3159,14 +3360,6 @@ class VIEW3D_MT_edit_armature(Menu):
edit_object = context.edit_object
arm = edit_object.data
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
- layout.operator("armature.delete")
-
- layout.separator()
-
layout.menu("VIEW3D_MT_transform_armature")
layout.menu("VIEW3D_MT_mirror")
layout.menu("VIEW3D_MT_snap")
@@ -3213,9 +3406,13 @@ class VIEW3D_MT_edit_armature(Menu):
layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings")
+ layout.separator()
+
+ layout.operator("armature.delete")
+
class VIEW3D_MT_armature_specials(Menu):
- bl_label = "Specials"
+ bl_label = "Armature Context Menu"
def draw(self, context):
layout = self.layout
@@ -3279,18 +3476,10 @@ class VIEW3D_MT_edit_gpencil(Menu):
bl_label = "GPencil"
def draw(self, context):
- toolsettings = context.tool_settings
+ tool_settings = context.tool_settings
layout = self.layout
- layout.menu("VIEW3D_MT_undo_redo")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_edit_gpencil_delete")
-
- layout.separator()
-
layout.menu("VIEW3D_MT_edit_gpencil_transform")
layout.operator("transform.mirror", text="Mirror")
layout.menu("GPENCIL_MT_snap")
@@ -3298,7 +3487,7 @@ class VIEW3D_MT_edit_gpencil(Menu):
layout.separator()
layout.operator("gpencil.brush_paint", text="Sculpt Strokes").wait_for_input = True
- layout.prop_menu_enum(toolsettings.gpencil_sculpt, "tool", text="Sculpt Brush")
+ layout.prop_menu_enum(tool_settings.gpencil_sculpt, "tool", text="Sculpt Brush")
layout.separator()
@@ -3322,10 +3511,6 @@ class VIEW3D_MT_edit_gpencil(Menu):
layout.separator()
- layout.menu("VIEW3D_MT_edit_proportional")
-
- layout.separator()
-
layout.operator("gpencil.reveal")
layout.operator("gpencil.hide", text="Show Active Layer Only").unselected = True
layout.operator("gpencil.hide", text="Hide Active Layer").unselected = False
@@ -3340,6 +3525,10 @@ class VIEW3D_MT_edit_gpencil(Menu):
layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...")
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_edit_gpencil_delete")
+
class VIEW3D_MT_edit_gpencil_transform(Menu):
bl_label = "Transform"
@@ -3373,6 +3562,29 @@ class VIEW3D_MT_edit_gpencil_interpolate(Menu):
layout.operator("gpencil.interpolate_sequence", text="Sequence")
+class VIEW3D_MT_object_mode_pie(Menu):
+ bl_label = "Mode"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator_enum("OBJECT_OT_mode_set", "mode")
+
+
+class VIEW3D_MT_view_pie(Menu):
+ bl_label = "View"
+ bl_idname = "VIEW3D_MT_view_pie"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator_enum("VIEW3D_OT_view_axis", "type")
+ pie.operator("view3d.view_camera", text="View Camera", icon='CAMERA_DATA')
+ pie.operator("view3d.view_selected", text="View Selected", icon='ZOOM_SELECTED')
+
+
# ********** Panel **********
@@ -3400,37 +3612,65 @@ class VIEW3D_PT_view3d_properties(Panel):
view = context.space_data
- col = layout.column()
- col.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
- col.prop(view, "lens")
- col.label(text="Lock to Object:")
- col.prop(view, "lock_object", text="")
- lock_object = view.lock_object
- if lock_object:
- if lock_object.type == 'ARMATURE':
- col.prop_search(view, "lock_bone", lock_object.data,
- "edit_bones" if lock_object.mode == 'EDIT'
- else "bones",
- text="")
- else:
- col.prop(view, "lock_cursor", text="Lock to Cursor")
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
- col = layout.column()
- col.prop(view, "lock_camera")
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+ col = flow.column()
- col = layout.column(align=True)
- col.label(text="Clip:")
- col.prop(view, "clip_start", text="Start")
- col.prop(view, "clip_end", text="End")
+ subcol = col.column()
+ subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
+ subcol.prop(view, "lens", text="Focal Length")
subcol = col.column(align=True)
+ subcol.prop(view, "clip_start", text="Clip Start")
+ subcol.prop(view, "clip_end", text="End")
+
+ subcol.separator()
+
+ col = flow.column()
+
+ subcol = col.column()
subcol.enabled = not view.lock_camera_and_layers
- subcol.label(text="Local Camera:")
- subcol.prop(view, "camera", text="")
+ subcol.prop(view, "camera", text="Local Camera")
+
+ subcol = col.column(align=True)
+ subcol.prop(view, "use_render_border")
+ subcol.active = view.region_3d.view_perspective != 'CAMERA'
+
+
+class VIEW3D_PT_view3d_camera_lock(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+ bl_label = "Camera Lock"
+ bl_parent_id = "VIEW3D_PT_view3d_properties"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ view = context.space_data
col = layout.column(align=True)
- col.prop(view, "use_render_border")
- col.active = view.region_3d.view_perspective != 'CAMERA'
+ subcol = col.column()
+ subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
+
+ subcol.prop(view, "lock_object")
+ lock_object = view.lock_object
+ if lock_object:
+ if lock_object.type == 'ARMATURE':
+ subcol.prop_search(
+ view, "lock_bone", lock_object.data,
+ "edit_bones" if lock_object.mode == 'EDIT'
+ else "bones",
+ text=""
+ )
+ else:
+ subcol.prop(view, "lock_cursor", text="Lock to 3D Cursor")
+
+ col.prop(view, "lock_camera")
class VIEW3D_PT_view3d_cursor(Panel):
@@ -3440,527 +3680,957 @@ class VIEW3D_PT_view3d_cursor(Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
view = context.space_data
+
layout.column().prop(view, "cursor_location", text="Location")
-class VIEW3D_PT_view3d_name(Panel):
+class VIEW3D_PT_object_type_visibility(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Item"
+ bl_region_type = 'HEADER'
+ bl_label = "View Object Types"
+ bl_ui_units_x = 6
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ view = context.space_data
+
+ col = layout.column()
+
+ attr_object_types = (
+ # Geometry
+ "mesh",
+ "curve",
+ "surf",
+ "meta",
+ "font",
+ None,
+ # Other
+ "armature",
+ "lattice",
+ "empty",
+ "camera",
+ "lamp",
+ "light_probe",
+ "speaker",
+ )
+
+ for attr in attr_object_types:
+ if attr is None:
+ col.separator()
+ continue
+
+ attr_v = "show_object_viewport_" f"{attr:s}"
+ attr_s = "show_object_select_" f"{attr:s}"
+
+ icon_s = 'RESTRICT_SELECT_OFF' if getattr(view, attr_s) else 'RESTRICT_SELECT_ON'
+
+ row = col.row(align=True)
+ row.prop(view, attr_v)
+ row.active = getattr(view, attr_v)
+ row.prop(view, attr_s, text="", icon=icon_s, emboss=False)
+
+
+class VIEW3D_PT_shading(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Shading"
+ bl_ui_units_x = 11
+
+ def draw(self, context):
+ pass
+
+
+class VIEW3D_PT_shading_lighting(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Lighting"
+ bl_parent_id = 'VIEW3D_PT_shading'
+
+ def draw(self, context):
+ layout = self.layout
+
+ view = context.space_data
+ shading = view.shading
+
+ col = layout.column()
+ split = col.split(0.9)
+
+ if shading.type == 'SOLID':
+ split.row().prop(shading, "light", expand=True)
+ col = split.column()
+
+ split = layout.split(0.9)
+ col = split.column()
+ sub = col.row()
+ sub.scale_y = 0.6 # smaller matcap/hdri preview
+
+ if shading.light == 'STUDIO':
+ sub.template_icon_view(shading, "studio_light", show_labels=True, scale=3)
+
+ if shading.selected_studio_light.orientation == 'WORLD':
+ col.prop(shading, "studiolight_rotate_z", text="Rotation")
+
+ col = split.column()
+ col.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='PREFERENCES')
+
+ elif shading.light == 'MATCAP':
+ sub.template_icon_view(shading, "studio_light", show_labels=True, scale=3)
+
+ col = split.column()
+ col.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='PREFERENCES')
+ col.operator('VIEW3D_OT_toggle_matcap_flip', emboss=False, text="", icon='ARROW_LEFTRIGHT')
+
+ elif shading.type == 'MATERIAL':
+ col.prop(shading, "use_scene_lights")
+ col.prop(shading, "use_scene_world")
+
+ if not shading.use_scene_world:
+ col = layout.column()
+ split = col.split(0.9)
+
+ col = split.column()
+ sub = col.row()
+ sub.scale_y = 0.6
+ sub.template_icon_view(shading, "studio_light", show_labels=True, scale=3)
+
+ col = split.column()
+ col.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='PREFERENCES')
+
+ if shading.selected_studio_light.orientation == 'WORLD':
+ split = layout.split(0.9)
+ col = split.column()
+ col.prop(shading, "studiolight_rotate_z", text="Rotation")
+ col.prop(shading, "studiolight_background_alpha")
+ col = split.column() # to align properly with above
+
+
+class VIEW3D_PT_shading_color(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Color"
+ bl_parent_id = 'VIEW3D_PT_shading'
@classmethod
def poll(cls, context):
- return (context.active_object is not None)
+ view = context.space_data
+ shading = view.shading
+ return shading.type == 'SOLID'
def draw(self, context):
layout = self.layout
- ob = context.active_object
- row = layout.row()
- row.label(text="", icon='OBJECT_DATA')
- row.prop(ob, "name", text="")
+ view = context.space_data
+ shading = view.shading
- if ob.type == 'ARMATURE' and ob.mode in {'EDIT', 'POSE'}:
- bone = context.active_bone
- if bone:
- row = layout.row()
- row.label(text="", icon='BONE_DATA')
- row.prop(bone, "name", text="")
+ layout.row().prop(shading, "color_type", expand=True)
+ if shading.color_type == 'SINGLE':
+ layout.row().prop(shading, "single_color", text="")
-class VIEW3D_PT_view3d_display(Panel):
+
+class VIEW3D_PT_shading_options(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Display"
- bl_options = {'DEFAULT_CLOSED'}
+ bl_region_type = 'HEADER'
+ bl_label = "Options"
+ bl_parent_id = 'VIEW3D_PT_shading'
+
+ @classmethod
+ def poll(cls, context):
+ view = context.space_data
+ shading = view.shading
+ return shading.type == 'SOLID'
def draw(self, context):
layout = self.layout
view = context.space_data
- scene = context.scene
+ shading = view.shading
col = layout.column()
- col.prop(view, "show_only_render")
- col.prop(view, "show_world")
+
+ is_xray = shading.show_xray
+ is_shadows = shading.show_shadows
+
+ icon_x = 'CHECKBOX_HLT' if is_xray else 'CHECKBOX_DEHLT'
+ row = col.row()
+ row.prop(shading, "show_xray", text="")
+ sub = row.row()
+ sub.active = is_xray
+ sub.prop(shading, "xray_alpha", text="X-Ray")
+
+ icon_s = 'CHECKBOX_HLT' if is_shadows else 'CHECKBOX_DEHLT'
+ row = col.row()
+ row.prop(shading, "show_shadows", text="")
+ row.active = not is_xray
+ sub = row.row(align=True)
+ sub.active = is_shadows
+ sub.prop(shading, "shadow_intensity", text="Shadow")
+ sub.popover(
+ panel="VIEW3D_PT_shading_options_shadow",
+ icon='SCRIPTWIN',
+ text=""
+ )
col = layout.column()
- display_all = not view.show_only_render
- col.active = display_all
- col.prop(view, "show_outline_selected")
- col.prop(view, "show_all_objects_origin")
- col.prop(view, "show_relationship_lines")
+ row = col.row()
+ row.active = not is_xray
+ row.prop(shading, "show_cavity")
+
+ if shading.show_cavity:
+ sub = col.row(align=True)
+ sub.active = not shading.show_xray and shading.show_cavity
+ sub.prop(shading, "cavity_ridge_factor")
+ sub.prop(shading, "cavity_valley_factor")
+ sub.popover(
+ panel="VIEW3D_PT_shading_options_ssao",
+ icon='SCRIPTWIN',
+ text=""
+ )
+
+ row = layout.split()
+ row.prop(shading, "show_object_outline")
+ sub = row.row()
+ sub.active = shading.show_object_outline
+ sub.prop(shading, "object_outline_color", text="")
col = layout.column()
- col.active = display_all
- split = col.split(percentage=0.55)
- split.prop(view, "show_floor", text="Grid Floor")
+ if not shading.light == 'MATCAP':
+ col.prop(shading, "show_specular_highlight")
- row = split.row(align=True)
- row.prop(view, "show_axis_x", text="X", toggle=True)
- row.prop(view, "show_axis_y", text="Y", toggle=True)
- row.prop(view, "show_axis_z", text="Z", toggle=True)
+ col.prop(view, "show_world")
- sub = col.column(align=True)
- sub.active = bool(view.show_floor or view.region_quadviews or not view.region_3d.is_perspective)
- subsub = sub.column(align=True)
- subsub.active = view.show_floor
- subsub.prop(view, "grid_lines", text="Lines")
- sub.prop(view, "grid_scale", text="Scale")
- subsub = sub.column(align=True)
- subsub.active = scene.unit_settings.system == 'NONE'
- subsub.prop(view, "grid_subdivisions", text="Subdivisions")
- layout.separator()
+class VIEW3D_PT_shading_options_shadow(Panel):
+ bl_label = "Shadow Settings"
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
- layout.operator("screen.region_quadview", text="Toggle Quad View")
+ @classmethod
+ def poll(cls, context):
+ return True
- if view.region_quadviews:
- region = view.region_quadviews[2]
- col = layout.column()
- col.prop(region, "lock_rotation")
- row = col.row()
- row.enabled = region.lock_rotation
- row.prop(region, "show_sync_view")
- row = col.row()
- row.enabled = region.lock_rotation and region.show_sync_view
- row.prop(region, "use_box_clip")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ scene = context.scene
+ col = layout.column()
+ col.prop(scene.display, "light_direction")
+ col.prop(scene.display, "shadow_shift")
-class VIEW3D_PT_view3d_stereo(Panel):
+
+class VIEW3D_PT_shading_options_ssao(Panel):
+ bl_label = "SSAO Settings"
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Stereoscopy"
- bl_options = {'DEFAULT_CLOSED'}
+ bl_region_type = 'HEADER'
@classmethod
def poll(cls, context):
+ return True
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
scene = context.scene
- return scene.render.use_multiview
+
+ col = layout.column(align=True)
+ col.prop(scene.display, "matcap_ssao_samples")
+ col.prop(scene.display, "matcap_ssao_distance")
+ col.prop(scene.display, "matcap_ssao_attenuation")
+
+
+class VIEW3D_PT_overlay(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Overlays"
+ bl_ui_units_x = 13
+
+ def draw(self, context):
+ pass
+
+
+class VIEW3D_PT_overlay_manipulators(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Manipulators"
+
+ def draw_header(self, context):
+ view = context.space_data
+ self.layout.prop(view, "show_manipulator", text="")
def draw(self, context):
layout = self.layout
+
view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
+
+ col = layout.column()
+ col.active = display_all
+
+ row = col.row(align=True)
+ row.active = view.show_manipulator
+ row.prop(view, "show_manipulator_navigate", text="Navigate", toggle=True)
+ row.prop(view, "show_manipulator_context", text="Active Object", toggle=True)
+ row.prop(view, "show_manipulator_tool", text="Active Tools", toggle=True)
- basic_stereo = context.scene.render.views_format == 'STEREO_3D'
+
+class VIEW3D_PT_overlay_guides(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Guides"
+
+ def draw(self, context):
+ layout = self.layout
+
+ view = context.space_data
+ overlay = view.overlay
+ shading = view.shading
+ display_all = overlay.show_overlays
col = layout.column()
- col.row().prop(view, "stereo_3d_camera", expand=True)
+ col.active = display_all
- col.label(text="Display:")
- row = col.row()
- row.active = basic_stereo
- row.prop(view, "show_stereo_3d_cameras")
- row = col.row()
- row.active = basic_stereo
- split = row.split()
- split.prop(view, "show_stereo_3d_convergence_plane")
- split = row.split()
- split.prop(view, "stereo_3d_convergence_plane_alpha", text="Alpha")
- split.active = view.show_stereo_3d_convergence_plane
- row = col.row()
- split = row.split()
- split.prop(view, "show_stereo_3d_volume")
- split = row.split()
- split.prop(view, "stereo_3d_volume_alpha", text="Alpha")
+ split = col.split()
+ sub = split.column()
+ sub.prop(overlay, "show_floor", text="Grid")
+
+ if overlay.show_floor:
+ sub = col.column(align=True)
+ sub.active = bool(overlay.show_floor or view.region_quadviews or not view.region_3d.is_perspective)
+ subsub = sub.row(align=True)
+ subsub.active = overlay.show_floor
+ subsub.prop(overlay, "grid_scale", text="Scale")
+ subsub.prop(overlay, "grid_subdivisions", text="Subdivisions")
+
+ sub = split.column()
+ row = sub.row()
+ row.label(text="Axes")
+ subrow = row.row(align=True)
+ subrow.prop(overlay, "show_axis_x", text="X", toggle=True)
+ subrow.prop(overlay, "show_axis_y", text="Y", toggle=True)
+ subrow.prop(overlay, "show_axis_z", text="Z", toggle=True)
-class VIEW3D_PT_view3d_shading(Panel):
+ split = col.split()
+ sub = split.column()
+ sub.prop(overlay, "show_text", text="Text Info")
+ sub = split.column()
+ sub.prop(overlay, "show_cursor", text="3D Cursor")
+
+ if shading.type == 'MATERIAL':
+ col.prop(overlay, "show_look_dev")
+
+
+class VIEW3D_PT_overlay_object(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Shading"
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Objects"
def draw(self, context):
layout = self.layout
+ view = context.space_data
+ overlay = view.overlay
+ shading = view.shading
+ display_all = overlay.show_overlays
+
+ col = layout.column(align=True)
+ col.active = display_all
+
+ split = col.split()
+
+ sub = split.column(align=True)
+ sub.prop(overlay, "show_ornaments", text="Ornaments")
+ sub.prop(overlay, "show_relationship_lines")
+ sub.prop(overlay, "show_outline_selected")
+
+ sub = split.column(align=True)
+ sub.prop(overlay, "show_bones", text="Bones")
+ sub.prop(overlay, "show_motion_paths")
+ sub.prop(overlay, "show_object_origins", text="Origins")
+ subsub = sub.column()
+ subsub.active = overlay.show_object_origins
+ subsub.prop(overlay, "show_object_origins_all", text="Origins (All)")
+
+class VIEW3D_PT_overlay_geometry(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Geometry"
+
+ def draw(self, context):
+ layout = self.layout
view = context.space_data
- scene = context.scene
- gs = scene.game_settings
- obj = context.object
+ overlay = view.overlay
+ display_all = overlay.show_overlays
col = layout.column()
+ col.active = display_all
- if not scene.render.use_shading_nodes:
- col.prop(gs, "material_mode", text="")
-
- if view.viewport_shade == 'SOLID':
- col.prop(view, "show_textured_solid")
- col.prop(view, "use_matcap")
- if view.use_matcap:
- col.template_icon_view(view, "matcap_icon")
- if view.viewport_shade == 'TEXTURED' or context.mode == 'PAINT_TEXTURE':
- if scene.render.use_shading_nodes or gs.material_mode != 'GLSL':
- col.prop(view, "show_textured_shadeless")
-
- col.prop(view, "show_backface_culling")
-
- if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
- if obj and obj.mode == 'EDIT':
- col.prop(view, "show_occlude_wire")
-
- fx_settings = view.fx_settings
-
- if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
- sub = col.column()
- sub.active = view.region_3d.view_perspective == 'CAMERA'
- sub.prop(fx_settings, "use_dof")
- col.prop(fx_settings, "use_ssao", text="Ambient Occlusion")
- if fx_settings.use_ssao:
- ssao_settings = fx_settings.ssao
- subcol = col.column(align=True)
- subcol.prop(ssao_settings, "factor")
- subcol.prop(ssao_settings, "distance_max")
- subcol.prop(ssao_settings, "attenuation")
- subcol.prop(ssao_settings, "samples")
- subcol.prop(ssao_settings, "color")
-
-
-class VIEW3D_PT_view3d_motion_tracking(Panel):
+ row = col.row()
+ row.prop(overlay, "show_wireframes", text="")
+ sub = row.row()
+ sub.active = overlay.show_wireframes
+ sub.prop(overlay, "wireframe_threshold", text="Wireframe")
+
+ col = layout.column(align=True)
+ col.active = display_all
+
+ split = col.split()
+ sub = split.column(align=True)
+ sub.prop(overlay, "show_backface_culling")
+
+ sub = split.column(align=True)
+ #sub.prop(overlay, "show_onion_skins")
+ sub.prop(overlay, "show_face_orientation")
+
+
+class VIEW3D_PT_overlay_motion_tracking(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
bl_label = "Motion Tracking"
- bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
view = context.space_data
-
self.layout.prop(view, "show_reconstruction", text="")
def draw(self, context):
layout = self.layout
-
view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
col = layout.column()
- col.active = view.show_reconstruction
- col.prop(view, "show_camera_path", text="Camera Path")
- col.prop(view, "show_bundle_names", text="3D Marker Names")
- col.label(text="Track Type and Size:")
- row = col.row(align=True)
- row.prop(view, "tracks_draw_type", text="")
- row.prop(view, "tracks_draw_size", text="")
+ col.active = display_all
+
+ if view.show_reconstruction:
+ split = col.split()
+
+ sub = split.column(align=True)
+ sub.active = view.show_reconstruction
+ sub.prop(view, "show_camera_path", text="Camera Path")
+ sub = split.column()
+ sub.prop(view, "show_bundle_names", text="Marker Names")
-class VIEW3D_PT_view3d_meshdisplay(Panel):
+ col = layout.column()
+ col.label(text="Tracks:")
+ row = col.row(align=True)
+ row.prop(view, "tracks_draw_type", text="")
+ row.prop(view, "tracks_draw_size", text="Size")
+
+
+class VIEW3D_PT_overlay_edit_mesh(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Mesh Display"
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Mesh Edit Mode"
@classmethod
def poll(cls, context):
- # The active object check is needed because of local-mode
- return (context.active_object and (context.mode == 'EDIT_MESH'))
+ return context.mode == 'EDIT_MESH'
def draw(self, context):
layout = self.layout
+
+ view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
+ data = context.active_object.data
with_freestyle = bpy.app.build_options.freestyle
- mesh = context.active_object.data
- scene = context.scene
+ col = layout.column()
+ col.active = display_all
- split = layout.split()
+ split = col.split()
- col = split.column()
- col.label(text="Overlays:")
- col.prop(mesh, "show_faces", text="Faces")
- col.prop(mesh, "show_edges", text="Edges")
- col.prop(mesh, "show_edge_crease", text="Creases")
- if with_freestyle:
- col.prop(mesh, "show_edge_seams", text="Seams")
+ sub = split.column()
+ sub.prop(data, "show_edges", text="Edges")
+ sub = split.column()
+ sub.prop(data, "show_faces", text="Faces")
- layout.prop(mesh, "show_weight")
+ row = col.row(align=True)
+ row.prop(data, "show_edge_crease", text="Creases", toggle=True)
+ row.prop(data, "show_edge_sharp", text="Sharp", text_ctxt=i18n_contexts.plural, toggle=True)
+ row.prop(data, "show_edge_bevel_weight", text="Bevel", toggle=True)
- col = split.column()
- col.label()
if not with_freestyle:
- col.prop(mesh, "show_edge_seams", text="Seams")
- col.prop(mesh, "show_edge_sharp", text="Sharp", text_ctxt=i18n_contexts.plural)
- col.prop(mesh, "show_edge_bevel_weight", text="Bevel")
- if with_freestyle:
- col.prop(mesh, "show_freestyle_edge_marks", text="Edge Marks")
- col.prop(mesh, "show_freestyle_face_marks", text="Face Marks")
+ row.prop(data, "show_edge_seams", text="Seams", toggle=True)
- col = layout.column()
- col.separator()
- col.label(text="Normals:")
- row = col.row(align=True)
+class VIEW3D_PT_overlay_edit_mesh_shading(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay_edit_mesh'
+ bl_label = "Shading"
- row.prop(mesh, "show_normal_vertex", text="", icon='VERTEXSEL')
- row.prop(mesh, "show_normal_loop", text="", icon='LOOPSEL')
- row.prop(mesh, "show_normal_face", text="", icon='FACESEL')
+ @classmethod
+ def poll(cls, context):
+ return context.mode == 'EDIT_MESH'
- sub = row.row(align=True)
- sub.active = mesh.show_normal_vertex or mesh.show_normal_face or mesh.show_normal_loop
- sub.prop(scene.tool_settings, "normal_size", text="Size")
+ def draw(self, context):
+ layout = self.layout
- col.separator()
- split = layout.split()
- col = split.column()
- col.label(text="Edge Info:")
- col.prop(mesh, "show_extra_edge_length", text="Length")
- col.prop(mesh, "show_extra_edge_angle", text="Angle")
- col = split.column()
- col.label(text="Face Info:")
- col.prop(mesh, "show_extra_face_area", text="Area")
- col.prop(mesh, "show_extra_face_angle", text="Angle")
- if context.user_preferences.view.show_developer_ui:
- layout.prop(mesh, "show_extra_indices")
-
-
-class VIEW3D_PT_view3d_meshstatvis(Panel):
+ view = context.space_data
+ overlay = view.overlay
+ tool_settings = context.tool_settings
+ display_all = overlay.show_overlays
+ data = context.active_object.data
+ statvis = tool_settings.statvis
+
+ col = layout.column()
+ col.active = display_all
+
+ col.prop(overlay, "show_occlude_wire")
+
+ col.prop(overlay, "show_weight", text="Vertex Group Weights")
+ if overlay.show_weight:
+ row = col.split()
+ row.label(text="Zero Weights")
+ row.prop(tool_settings, "vertex_group_user", text="")
+
+ col.prop(data, "show_statvis", text="Mesh Analysis")
+ if data.show_statvis:
+ col = col.column()
+
+ sub = col.split()
+ sub.active = data.show_statvis
+ sub.label(text="Type")
+ sub.prop(statvis, "type", text="")
+
+ statvis_type = statvis.type
+ if statvis_type == 'OVERHANG':
+ row = col.row(align=True)
+ row.prop(statvis, "overhang_min", text="Minimum")
+ row.prop(statvis, "overhang_max", text="Maximum")
+ col.row().prop(statvis, "overhang_axis", expand=True)
+ elif statvis_type == 'THICKNESS':
+ row = col.row(align=True)
+ row.prop(statvis, "thickness_min", text="Minimum")
+ row.prop(statvis, "thickness_max", text="Maximum")
+ col.prop(statvis, "thickness_samples")
+ elif statvis_type == 'INTERSECT':
+ pass
+ elif statvis_type == 'DISTORT':
+ row = col.row(align=True)
+ row.prop(statvis, "distort_min", text="Minimum")
+ row.prop(statvis, "distort_max", text="Maximum")
+ elif statvis_type == 'SHARP':
+ row = col.row(align=True)
+ row.prop(statvis, "sharp_min", text="Minimum")
+ row.prop(statvis, "sharp_max", text="Maximum")
+
+
+class VIEW3D_PT_overlay_edit_mesh_measurement(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Mesh Analysis"
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay_edit_mesh'
+ bl_label = "Measurement"
@classmethod
def poll(cls, context):
- # The active object check is needed because of local-mode
- return (context.active_object and (context.mode == 'EDIT_MESH'))
+ return context.mode == 'EDIT_MESH'
- def draw_header(self, context):
- mesh = context.active_object.data
+ def draw(self, context):
+ layout = self.layout
- self.layout.prop(mesh, "show_statvis", text="")
+ view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
+ data = context.active_object.data
+
+ col = layout.column()
+ col.active = display_all
+
+ split = col.split()
+
+ sub = split.column()
+ sub.prop(data, "show_extra_edge_length", text="Edge Length")
+ sub.prop(data, "show_extra_edge_angle", text="Edge Angle")
+
+ sub = split.column()
+ sub.prop(data, "show_extra_face_area", text="Face Area")
+ sub.prop(data, "show_extra_face_angle", text="Face Angle")
+
+
+class VIEW3D_PT_overlay_edit_mesh_normals(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay_edit_mesh'
+ bl_label = "Normals"
+
+ @classmethod
+ def poll(cls, context):
+ return context.mode == 'EDIT_MESH'
def draw(self, context):
layout = self.layout
- mesh = context.active_object.data
- statvis = context.tool_settings.statvis
- layout.active = mesh.show_statvis
+ view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
- layout.prop(statvis, "type")
- statvis_type = statvis.type
- if statvis_type == 'OVERHANG':
- row = layout.row(align=True)
- row.prop(statvis, "overhang_min", text="")
- row.prop(statvis, "overhang_max", text="")
- layout.row().prop(statvis, "overhang_axis", expand=True)
- elif statvis_type == 'THICKNESS':
- row = layout.row(align=True)
- row.prop(statvis, "thickness_min", text="")
- row.prop(statvis, "thickness_max", text="")
- layout.prop(statvis, "thickness_samples")
- elif statvis_type == 'INTERSECT':
- pass
- elif statvis_type == 'DISTORT':
- row = layout.row(align=True)
- row.prop(statvis, "distort_min", text="")
- row.prop(statvis, "distort_max", text="")
- elif statvis_type == 'SHARP':
- row = layout.row(align=True)
- row.prop(statvis, "sharp_min", text="")
- row.prop(statvis, "sharp_max", text="")
+ col = layout.column()
+ col.active = display_all
+
+ row = col.row(align=True)
+ row.prop(overlay, "show_vertex_normals", text="", icon='VERTEXSEL')
+ row.prop(overlay, "show_split_normals", text="", icon='LOOPSEL')
+ row.prop(overlay, "show_face_normals", text="", icon='FACESEL')
+
+ sub = row.row(align=True)
+ sub.active = overlay.show_vertex_normals or overlay.show_face_normals or overlay.show_split_normals
+ sub.prop(overlay, "normals_length", text="Size")
-class VIEW3D_PT_view3d_curvedisplay(Panel):
+class VIEW3D_PT_overlay_edit_mesh_freestyle(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Curve Display"
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Freestyle"
@classmethod
def poll(cls, context):
- return (context.mode == 'EDIT_CURVE')
+ return context.mode == 'EDIT_MESH' and bpy.app.build_options.freestyle
def draw(self, context):
layout = self.layout
- curve = context.active_object.data
+ view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
+ data = context.active_object.data
col = layout.column()
+ col.active = display_all
+
row = col.row()
- row.prop(curve, "show_handles", text="Handles")
- row.prop(curve, "show_normal_face", text="Normals")
- col.prop(context.scene.tool_settings, "normal_size", text="Normal Size")
+ row.prop(data, "show_freestyle_edge_marks", text="Edge Marks")
+ row.prop(data, "show_freestyle_face_marks", text="Face Marks")
+ row.prop(data, "show_edge_seams", text="Seams")
-class VIEW3D_PT_background_image(Panel):
+class VIEW3D_PT_overlay_edit_mesh_developer(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Background Images"
- bl_options = {'DEFAULT_CLOSED'}
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay_edit_mesh'
+ bl_label = "Developer"
- def draw_header(self, context):
+ @classmethod
+ def poll(cls, context):
+ return context.mode == 'EDIT_MESH' and context.user_preferences.view.show_developer_ui
+
+ def draw(self, context):
+ layout = self.layout
+
+ view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
+ data = context.active_object.data
+
+ col = layout.column()
+ col.active = display_all
+
+ col.prop(data, "show_extra_indices", text="Indices")
+
+
+class VIEW3D_PT_overlay_edit_curve(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Edit Curve"
+
+ @classmethod
+ def poll(cls, context):
+ return context.mode == 'EDIT_CURVE'
+
+ def draw(self, context):
+ layout = self.layout
view = context.space_data
+ data = context.active_object.data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
+
+ col = layout.column()
+ col.active = display_all
+
+ row = col.row()
+ row.prop(data, "show_handles", text="Handles")
+ row.prop(data, "show_normal_face", text="Normals")
+
+
+class VIEW3D_PT_overlay_sculpt(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_context = ".sculpt_mode"
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Sculpt"
- self.layout.prop(view, "show_background_images", text="")
+ @classmethod
+ def poll(cls, context):
+ return (
+ context.mode == 'SCULPT' and
+ (context.sculpt_object and context.tool_settings.sculpt)
+ )
def draw(self, context):
layout = self.layout
+ tool_settings = context.tool_settings
+ sculpt = tool_settings.sculpt
+ layout.prop(sculpt, "show_diffuse_color")
+ layout.prop(sculpt, "show_mask")
+
+
+class VIEW3D_PT_overlay_pose(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Pose Mode"
+
+ @classmethod
+ def poll(cls, context):
+ return context.mode == 'POSE'
+
+ def draw(self, context):
+ layout = self.layout
view = context.space_data
- use_multiview = context.scene.render.use_multiview
+ overlay = view.overlay
+ display_all = overlay.show_overlays
col = layout.column()
- col.operator("view3d.background_image_add", text="Add Image")
-
- for i, bg in enumerate(view.background_images):
- layout.active = view.show_background_images
- box = layout.box()
- row = box.row(align=True)
- row.prop(bg, "show_expanded", text="", emboss=False)
- if bg.source == 'IMAGE' and bg.image:
- row.prop(bg.image, "name", text="", emboss=False)
- elif bg.source == 'MOVIE_CLIP' and bg.clip:
- row.prop(bg.clip, "name", text="", emboss=False)
- else:
- row.label(text="Not Set")
+ col.active = display_all
+ col.prop(overlay, "show_transparent_bones")
- if bg.show_background_image:
- row.prop(bg, "show_background_image", text="", emboss=False, icon='RESTRICT_VIEW_OFF')
- else:
- row.prop(bg, "show_background_image", text="", emboss=False, icon='RESTRICT_VIEW_ON')
+ row = col.row()
+ row.prop(overlay, "show_bone_select", text="")
+ sub = row.row()
+ sub.active = display_all and overlay.show_bone_select
+ sub.prop(overlay, "bone_select_alpha", text="Fade Geometry")
- row.operator("view3d.background_image_remove", text="", emboss=False, icon='X').index = i
- box.prop(bg, "view_axis", text="Axis")
+class VIEW3D_PT_overlay_edit_armature(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = "Edit Armature"
- if bg.show_expanded:
- row = box.row()
- row.prop(bg, "source", expand=True)
+ @classmethod
+ def poll(cls, context):
+ return context.mode == 'EDIT_ARMATURE'
- has_bg = False
- if bg.source == 'IMAGE':
- row = box.row()
- row.template_ID(bg, "image", open="image.open")
- if bg.image is not None:
- box.template_image(bg, "image", bg.image_user, compact=True)
- has_bg = True
+ def draw(self, context):
+ layout = self.layout
+ view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
- if use_multiview and bg.view_axis in {'CAMERA', 'ALL'}:
- box.prop(bg.image, "use_multiview")
+ col = layout.column()
+ col.active = display_all
+ col.prop(overlay, "show_transparent_bones")
- column = box.column()
- column.active = bg.image.use_multiview
- column.label(text="Views Format:")
- column.row().prop(bg.image, "views_format", expand=True)
+class VIEW3D_PT_overlay_paint(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = ""
- sub = column.box()
- sub.active = bg.image.views_format == 'STEREO_3D'
- sub.template_image_stereo_3d(bg.image.stereo_3d_format)
+ @classmethod
+ def poll(cls, context):
+ return context.mode in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}
- elif bg.source == 'MOVIE_CLIP':
- box.prop(bg, "use_camera_clip")
+ def draw_header(self, context):
+ layout = self.layout
+ layout.label(text={
+ 'PAINT_TEXTURE': "Texture Paint",
+ 'PAINT_VERTEX': "Vertex Paint",
+ 'PAINT_WEIGHT': "Weight Paint",
+ }[context.mode])
- column = box.column()
- column.active = not bg.use_camera_clip
- column.template_ID(bg, "clip", open="clip.open")
+ def draw(self, context):
+ layout = self.layout
+ view = context.space_data
+ overlay = view.overlay
+ display_all = overlay.show_overlays
- if bg.clip:
- column.template_movieclip(bg, "clip", compact=True)
+ col = layout.column()
+ col.active = display_all
- if bg.use_camera_clip or bg.clip:
- has_bg = True
+ col.prop(overlay, {
+ 'PAINT_TEXTURE': "texture_paint_mode_opacity",
+ 'PAINT_VERTEX': "vertex_paint_mode_opacity",
+ 'PAINT_WEIGHT': "weight_paint_mode_opacity",
+ }[context.mode], text="Opacity")
- column = box.column()
- column.active = has_bg
- column.prop(bg.clip_user, "proxy_render_size", text="")
- column.prop(bg.clip_user, "use_render_undistorted")
+ if context.mode in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
+ col.prop(overlay, "show_paint_wire")
- if has_bg:
- col = box.column()
- col.prop(bg, "opacity", slider=True)
- col.row().prop(bg, "draw_depth", expand=True)
- if bg.view_axis in {'CAMERA', 'ALL'}:
- col.row().prop(bg, "frame_method", expand=True)
+class VIEW3D_PT_pivot_point(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Pivot Point"
+ bl_ui_units_x = 8
- box = col.box()
- row = box.row()
- row.prop(bg, "offset_x", text="X")
- row.prop(bg, "offset_y", text="Y")
+ def draw(self, context):
+ toolsettings = context.tool_settings
+ obj = context.active_object
+ mode = context.mode
- row = box.row()
- row.prop(bg, "use_flip_x")
- row.prop(bg, "use_flip_y")
+ layout = self.layout
+ col = layout.column()
+ col.label("Pivot Point")
+ col.prop(toolsettings, "transform_pivot_point", expand=True)
- row = box.row()
- if bg.view_axis != 'CAMERA':
- row.prop(bg, "rotation")
- row.prop(bg, "size")
+ col.separator()
+
+ if (obj is None) or (mode in {'OBJECT', 'POSE', 'WEIGHT_PAINT'}):
+ col.prop(
+ toolsettings,
+ "use_transform_pivot_point_align",
+ text="Center Points Only",
+ )
+
+
+class VIEW3D_PT_snapping(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Snapping"
+
+ def draw(self, context):
+ toolsettings = context.tool_settings
+ snap_elements = toolsettings.snap_elements
+ obj = context.active_object
+ mode = context.mode
+ object_mode = 'OBJECT' if obj is None else obj.mode
+
+ layout = self.layout
+ col = layout.column()
+ col.label("Snapping")
+ col.prop(toolsettings, "snap_elements", expand=True)
+
+ col.separator()
+ if 'INCREMENT' in snap_elements:
+ col.prop(toolsettings, "use_snap_grid_absolute")
+
+ if snap_elements != {'INCREMENT'}:
+ col.label("Target")
+ row = col.row(align=True)
+ row.prop(toolsettings, "snap_target", expand=True)
+
+ if obj:
+ if object_mode == 'EDIT':
+ col.prop(toolsettings, "use_snap_self")
+ if object_mode in {'OBJECT', 'POSE', 'EDIT'}:
+ col.prop(toolsettings, "use_snap_align_rotation", text="Align Rotation")
+
+ if 'FACE' in snap_elements:
+ col.prop(toolsettings, "use_snap_project", text="Project Elements")
+
+ if 'VOLUME' in snap_elements:
+ col.prop(toolsettings, "use_snap_peel_object")
class VIEW3D_PT_transform_orientations(Panel):
bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
+ bl_region_type = 'HEADER'
bl_label = "Transform Orientations"
- bl_options = {'DEFAULT_CLOSED'}
+ bl_ui_units_x = 8
def draw(self, context):
layout = self.layout
+ layout.label("Transform Orientations")
- view = context.space_data
- orientation = view.current_orientation
+ scene = context.scene
+ orientation = scene.current_orientation
- row = layout.row(align=True)
- row.prop(view, "transform_orientation", text="")
- row.operator("transform.create_orientation", text="", icon='ZOOMIN')
+ row = layout.row()
+ col = row.column()
+ col.prop(scene, "transform_orientation", expand=True)
+ row.operator("transform.create_orientation", text="", icon='ZOOMIN', emboss=False).use = True
if orientation:
- row = layout.row(align=True)
+ row = layout.row(align=False)
row.prop(orientation, "name", text="")
- row.operator("transform.delete_orientation", text="", icon='X')
+ row.operator("transform.delete_orientation", text="", icon='X', emboss=False)
-class VIEW3D_PT_etch_a_ton(Panel):
+class VIEW3D_PT_quad_view(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
- bl_label = "Skeleton Sketching"
+ bl_label = "Quad View"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- scene = context.space_data
- ob = context.active_object
- return scene and ob and ob.type == 'ARMATURE' and ob.mode == 'EDIT'
-
- def draw_header(self, context):
- layout = self.layout
- toolsettings = context.scene.tool_settings
-
- layout.prop(toolsettings, "use_bone_sketching", text="")
+ view = context.space_data
+ return view.region_quadviews
def draw(self, context):
layout = self.layout
- toolsettings = context.scene.tool_settings
+ view = context.space_data
+ region = view.region_quadviews[2]
col = layout.column()
+ col.prop(region, "lock_rotation")
+ row = col.row()
+ row.enabled = region.lock_rotation
+ row.prop(region, "show_sync_view")
+ row = col.row()
+ row.enabled = region.lock_rotation and region.show_sync_view
+ row.prop(region, "use_box_clip")
- col.prop(toolsettings, "use_etch_quick")
- col.prop(toolsettings, "use_etch_overdraw")
- col.separator()
+class VIEW3D_PT_view3d_stereo(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+ bl_label = "Stereoscopy"
+ bl_options = {'DEFAULT_CLOSED'}
- col.prop(toolsettings, "etch_convert_mode")
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
- if toolsettings.etch_convert_mode == 'LENGTH':
- col.prop(toolsettings, "etch_length_limit")
- elif toolsettings.etch_convert_mode == 'ADAPTIVE':
- col.prop(toolsettings, "etch_adaptive_limit")
- elif toolsettings.etch_convert_mode == 'FIXED':
- col.prop(toolsettings, "etch_subdivision_number")
- elif toolsettings.etch_convert_mode == 'RETARGET':
- col.prop(toolsettings, "etch_template")
- col.prop(toolsettings, "etch_roll_mode")
+ multiview = scene.render.use_multiview
+ return multiview
- col.separator()
+ def draw(self, context):
+ layout = self.layout
+ view = context.space_data
- colsub = col.column(align=True)
- colsub.prop(toolsettings, "use_etch_autoname")
- sub = colsub.column(align=True)
- sub.enabled = not toolsettings.use_etch_autoname
- sub.prop(toolsettings, "etch_number")
- sub.prop(toolsettings, "etch_side")
+ basic_stereo = context.scene.render.views_format == 'STEREO_3D'
- col.separator()
+ col = layout.column()
+ col.row().prop(view, "stereo_3d_camera", expand=True)
- col.operator("sketch.convert", text="Convert to Bones")
- col.operator("sketch.delete", text="Delete Strokes")
+ col.label(text="Display:")
+ row = col.row()
+ row.active = basic_stereo
+ row.prop(view, "show_stereo_3d_cameras")
+ row = col.row()
+ row.active = basic_stereo
+ split = row.split()
+ split.prop(view, "show_stereo_3d_convergence_plane")
+ split = row.split()
+ split.prop(view, "stereo_3d_convergence_plane_alpha", text="Alpha")
+ split.active = view.show_stereo_3d_convergence_plane
+ row = col.row()
+ split = row.split()
+ split.prop(view, "show_stereo_3d_volume")
+ split = row.split()
+ split.prop(view, "stereo_3d_volume_alpha", text="Alpha")
class VIEW3D_PT_context_properties(Panel):
@@ -3972,10 +4642,10 @@ class VIEW3D_PT_context_properties(Panel):
def _active_context_member(context):
obj = context.object
if obj:
- mode = obj.mode
- if mode == 'POSE':
+ object_mode = obj.mode
+ if object_mode == 'POSE':
return "active_pose_bone"
- elif mode == 'EDIT' and obj.type == 'ARMATURE':
+ elif object_mode == 'EDIT' and obj.type == 'ARMATURE':
return "active_bone"
else:
return "object"
@@ -4047,25 +4717,26 @@ classes = (
INFO_MT_edit_curve_add,
INFO_MT_edit_armature_add,
INFO_MT_armature_add,
- INFO_MT_lamp_add,
+ INFO_MT_light_add,
+ INFO_MT_lightprobe_add,
INFO_MT_camera_add,
INFO_MT_add,
- VIEW3D_MT_undo_redo,
- VIEW3D_MT_object_relations,
VIEW3D_MT_object,
VIEW3D_MT_object_animation,
+ VIEW3D_MT_object_rigid_body,
VIEW3D_MT_object_clear,
VIEW3D_MT_object_specials,
+ VIEW3D_MT_object_shading,
VIEW3D_MT_object_apply,
+ VIEW3D_MT_object_relations,
VIEW3D_MT_object_parent,
VIEW3D_MT_object_track,
- VIEW3D_MT_object_group,
+ VIEW3D_MT_object_collection,
VIEW3D_MT_object_constraints,
VIEW3D_MT_object_quick_effects,
VIEW3D_MT_object_showhide,
VIEW3D_MT_make_single_user,
VIEW3D_MT_make_links,
- VIEW3D_MT_object_game,
VIEW3D_MT_brush,
VIEW3D_MT_brush_paint_modes,
VIEW3D_MT_paint_vertex,
@@ -4101,7 +4772,10 @@ classes = (
VIEW3D_MT_edit_mesh_edges,
VIEW3D_MT_edit_mesh_edges_data,
VIEW3D_MT_edit_mesh_faces,
+ VIEW3D_MT_edit_mesh_faces_data,
VIEW3D_MT_edit_mesh_normals,
+ VIEW3D_MT_edit_mesh_shading,
+ VIEW3D_MT_edit_mesh_weights,
VIEW3D_MT_edit_mesh_clean,
VIEW3D_MT_edit_mesh_delete,
VIEW3D_MT_edit_mesh_showhide,
@@ -4127,21 +4801,42 @@ classes = (
VIEW3D_MT_edit_armature_delete,
VIEW3D_MT_edit_gpencil_transform,
VIEW3D_MT_edit_gpencil_interpolate,
+ VIEW3D_MT_object_mode_pie,
+ VIEW3D_MT_view_pie,
VIEW3D_PT_grease_pencil,
VIEW3D_PT_grease_pencil_palettecolor,
VIEW3D_PT_view3d_properties,
+ VIEW3D_PT_view3d_camera_lock,
VIEW3D_PT_view3d_cursor,
- VIEW3D_PT_view3d_name,
- VIEW3D_PT_view3d_display,
+ VIEW3D_PT_object_type_visibility,
+ VIEW3D_PT_quad_view,
VIEW3D_PT_view3d_stereo,
- VIEW3D_PT_view3d_shading,
- VIEW3D_PT_view3d_motion_tracking,
- VIEW3D_PT_view3d_meshdisplay,
- VIEW3D_PT_view3d_meshstatvis,
- VIEW3D_PT_view3d_curvedisplay,
- VIEW3D_PT_background_image,
+ VIEW3D_PT_shading,
+ VIEW3D_PT_shading_lighting,
+ VIEW3D_PT_shading_color,
+ VIEW3D_PT_shading_options,
+ VIEW3D_PT_shading_options_shadow,
+ VIEW3D_PT_shading_options_ssao,
+ VIEW3D_PT_overlay,
+ VIEW3D_PT_overlay_manipulators,
+ VIEW3D_PT_overlay_guides,
+ VIEW3D_PT_overlay_object,
+ VIEW3D_PT_overlay_geometry,
+ VIEW3D_PT_overlay_motion_tracking,
+ VIEW3D_PT_overlay_edit_mesh,
+ VIEW3D_PT_overlay_edit_mesh_shading,
+ VIEW3D_PT_overlay_edit_mesh_measurement,
+ VIEW3D_PT_overlay_edit_mesh_normals,
+ VIEW3D_PT_overlay_edit_mesh_freestyle,
+ VIEW3D_PT_overlay_edit_mesh_developer,
+ VIEW3D_PT_overlay_edit_curve,
+ VIEW3D_PT_overlay_edit_armature,
+ VIEW3D_PT_overlay_pose,
+ VIEW3D_PT_overlay_paint,
+ VIEW3D_PT_overlay_sculpt,
+ VIEW3D_PT_pivot_point,
+ VIEW3D_PT_snapping,
VIEW3D_PT_transform_orientations,
- VIEW3D_PT_etch_a_ton,
VIEW3D_PT_context_properties,
)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 41f1a64ca51..87c6a3840ae 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -36,8 +36,8 @@ from .properties_paint_common import (
class View3DPanel:
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
# **************** standard tool clusters ******************
@@ -53,419 +53,30 @@ def draw_keyframing_tools(context, layout):
# Used by vertex & weight paint
def draw_vpaint_symmetry(layout, vpaint):
- col = layout.column(align=True)
- col.label(text="Mirror:")
- row = col.row(align=True)
+ split = layout.split()
+
+ col = split.column()
+ col.alignment = 'RIGHT'
+ col.label(text="Mirror")
+
+ col = split.column()
+ row = col.row(align=True)
row.prop(vpaint, "use_symmetry_x", text="X", toggle=True)
row.prop(vpaint, "use_symmetry_y", text="Y", toggle=True)
row.prop(vpaint, "use_symmetry_z", text="Z", toggle=True)
col = layout.column()
+ col.use_property_split = True
col.prop(vpaint, "radial_symmetry", text="Radial")
-# ********** default tools for object-mode ****************
-
-
-class VIEW3D_PT_tools_transform(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "objectmode"
- bl_label = "Transform"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.operator("transform.translate")
- col.operator("transform.rotate")
- col.operator("transform.resize", text="Scale")
-
- col = layout.column(align=True)
- col.operator("transform.mirror", text="Mirror")
-
-
-class VIEW3D_PT_tools_object(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "objectmode"
- bl_label = "Edit"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.operator("object.duplicate_move", text="Duplicate")
- col.operator("object.duplicate_move_linked", text="Duplicate Linked")
-
- col.operator("object.delete")
-
- obj = context.active_object
- if obj:
- obj_type = obj.type
-
- if obj_type in {'MESH', 'CURVE', 'SURFACE', 'ARMATURE'}:
- col = layout.column(align=True)
- col.operator("object.join")
-
- if obj_type in {'MESH', 'CURVE', 'SURFACE', 'ARMATURE', 'FONT', 'LATTICE'}:
- col = layout.column(align=True)
- col.operator_menu_enum("object.origin_set", "type", text="Set Origin")
-
- if obj_type in {'MESH', 'CURVE', 'SURFACE'}:
- 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")
-
- if obj_type == 'MESH':
- col = layout.column(align=True)
- col.label(text="Data Transfer:")
- row = col.row(align=True)
- row.operator("object.data_transfer", text="Data")
- row.operator("object.datalayout_transfer", text="Data Layout")
-
-
-class VIEW3D_PT_tools_add_object(View3DPanel, Panel):
- bl_category = "Create"
- bl_context = "objectmode"
- bl_label = "Add Primitive"
-
- @staticmethod
- def draw_add_mesh(layout, label=False):
- if label:
- layout.label(text="Primitives:")
- layout.operator("mesh.primitive_plane_add", text="Plane", icon='MESH_PLANE')
- layout.operator("mesh.primitive_cube_add", text="Cube", icon='MESH_CUBE')
- layout.operator("mesh.primitive_circle_add", text="Circle", icon='MESH_CIRCLE')
- layout.operator("mesh.primitive_uv_sphere_add", text="UV Sphere", icon='MESH_UVSPHERE')
- layout.operator("mesh.primitive_ico_sphere_add", text="Ico Sphere", icon='MESH_ICOSPHERE')
- layout.operator("mesh.primitive_cylinder_add", text="Cylinder", icon='MESH_CYLINDER')
- layout.operator("mesh.primitive_cone_add", text="Cone", icon='MESH_CONE')
- layout.operator("mesh.primitive_torus_add", text="Torus", icon='MESH_TORUS')
-
- if label:
- layout.label(text="Special:")
- else:
- layout.separator()
- layout.operator("mesh.primitive_grid_add", text="Grid", icon='MESH_GRID')
- layout.operator("mesh.primitive_monkey_add", text="Monkey", icon='MESH_MONKEY')
-
- @staticmethod
- def draw_add_curve(layout, label=False):
-
- if label:
- layout.label(text="Bezier:")
- layout.operator("curve.primitive_bezier_curve_add", text="Bezier", icon='CURVE_BEZCURVE')
- layout.operator("curve.primitive_bezier_circle_add", text="Circle", icon='CURVE_BEZCIRCLE')
-
- if label:
- layout.label(text="Nurbs:")
- else:
- layout.separator()
- layout.operator("curve.primitive_nurbs_curve_add", text="Nurbs Curve", icon='CURVE_NCURVE')
- layout.operator("curve.primitive_nurbs_circle_add", text="Nurbs Circle", icon='CURVE_NCIRCLE')
- layout.operator("curve.primitive_nurbs_path_add", text="Path", icon='CURVE_PATH')
-
- layout.separator()
-
- layout.operator("curve.draw", icon='LINE_DATA')
-
- @staticmethod
- def draw_add_surface(layout):
- layout.operator("surface.primitive_nurbs_surface_curve_add", text="Nurbs Curve", icon='SURFACE_NCURVE')
- layout.operator("surface.primitive_nurbs_surface_circle_add", text="Nurbs Circle", icon='SURFACE_NCIRCLE')
- layout.operator("surface.primitive_nurbs_surface_surface_add", text="Nurbs Surface", icon='SURFACE_NSURFACE')
- layout.operator("surface.primitive_nurbs_surface_cylinder_add", text="Nurbs Cylinder", icon='SURFACE_NCYLINDER')
- layout.operator("surface.primitive_nurbs_surface_sphere_add", text="Nurbs Sphere", icon='SURFACE_NSPHERE')
- layout.operator("surface.primitive_nurbs_surface_torus_add", text="Nurbs Torus", icon='SURFACE_NTORUS')
-
- @staticmethod
- def draw_add_mball(layout):
- layout.operator_enum("object.metaball_add", "type")
-
- @staticmethod
- def draw_add_lamp(layout):
- layout.operator_enum("object.lamp_add", "type")
-
- @staticmethod
- def draw_add_other(layout):
- layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT')
- layout.operator("object.armature_add", text="Armature", icon='OUTLINER_OB_ARMATURE')
- layout.operator("object.add", text="Lattice", icon='OUTLINER_OB_LATTICE').type = 'LATTICE'
- layout.operator("object.empty_add", text="Empty", icon='OUTLINER_OB_EMPTY').type = 'PLAIN_AXES'
- layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
- layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.label(text="Mesh:")
- self.draw_add_mesh(col)
-
- col = layout.column(align=True)
- col.label(text="Curve:")
- self.draw_add_curve(col)
-
- # not used here:
- # draw_add_surface
- # draw_add_mball
-
- col = layout.column(align=True)
- col.label(text="Lamp:")
- self.draw_add_lamp(col)
-
- col = layout.column(align=True)
- col.label(text="Other:")
- self.draw_add_other(col)
-
-
-class VIEW3D_PT_tools_relations(View3DPanel, Panel):
- bl_category = "Relations"
- bl_context = "objectmode"
- bl_label = "Relations"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
-
- col.label(text="Group:")
- col.operator("group.create", text="New Group")
- col.operator("group.objects_add_active", text="Add to Active")
- col.operator("group.objects_remove", text="Remove from Group")
-
- col.separator()
-
- col.label(text="Parent:")
- row = col.row(align=True)
- row.operator("object.parent_set", text="Set")
- row.operator("object.parent_clear", text="Clear")
-
- col.separator()
-
- col.label(text="Object Data:")
- col.operator("object.make_links_data")
- col.operator("object.make_single_user")
-
- col.separator()
-
- col.label(text="Linked Objects:")
- col.operator("object.make_local")
- col.operator("object.proxy_make")
-
-
-class VIEW3D_PT_tools_animation(View3DPanel, Panel):
- bl_category = "Animation"
- bl_context = "objectmode"
- bl_label = "Animation"
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.active_object
- mpath = ob.motion_path if ob else None
-
- draw_keyframing_tools(context, layout)
-
- col = layout.column(align=True)
- col.label(text="Motion Paths:")
- if mpath:
- row = col.row(align=True)
- row.operator("object.paths_update", text="Update")
- row.operator("object.paths_clear", text="", icon='X')
- else:
- col.operator("object.paths_calculate", text="Calculate")
-
- col.separator()
-
- col.label(text="Action:")
- col.operator("nla.bake", text="Bake Action")
-
-
-class VIEW3D_PT_tools_rigid_body(View3DPanel, Panel):
- bl_category = "Physics"
- bl_context = "objectmode"
- bl_label = "Rigid Body Tools"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.label(text="Add/Remove:")
- row = col.row(align=True)
- row.operator("rigidbody.objects_add", text="Add Active").type = 'ACTIVE'
- row.operator("rigidbody.objects_add", text="Add Passive").type = 'PASSIVE'
- row = col.row(align=True)
- row.operator("rigidbody.objects_remove", text="Remove")
-
- col = layout.column(align=True)
- col.label(text="Object Tools:")
- col.operator("rigidbody.shape_change", text="Change Shape")
- col.operator("rigidbody.mass_calculate", text="Calculate Mass")
- col.operator("rigidbody.object_settings_copy", text="Copy from Active")
- col.operator("object.visual_transform_apply", text="Apply Transformation")
- col.operator("rigidbody.bake_to_keyframes", text="Bake To Keyframes")
- col.label(text="Constraints:")
- col.operator("rigidbody.connect", text="Connect")
-
# ********** default tools for editmode_mesh ****************
-class VIEW3D_PT_tools_transform_mesh(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "mesh_edit"
- bl_label = "Transform"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.operator("transform.translate")
- col.operator("transform.rotate")
- col.operator("transform.resize", text="Scale")
- col.operator("transform.shrink_fatten", text="Shrink/Fatten")
- col.operator("transform.push_pull", text="Push/Pull")
-
-
-class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "mesh_edit"
- bl_label = "Mesh Tools"
-
- def draw(self, context):
- layout = self.layout
-
- 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.vertex_random")
-
- col = layout.column(align=True)
- col.label(text="Add:")
-
- 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.inset", text="Inset Faces")
- col.operator("mesh.edge_face_add")
- col.operator("mesh.subdivide")
- col.operator("mesh.loopcut_slide")
- col.operator("mesh.offset_edge_loops_slide")
- col.operator("mesh.duplicate_move", text="Duplicate")
- row = col.row(align=True)
- row.operator("mesh.spin")
- row.operator("mesh.screw")
-
- row = col.row(align=True)
- props = row.operator("mesh.knife_tool", text="Knife")
- props.use_occlude_geometry = True
- props.only_selected = False
- props = row.operator("mesh.knife_tool", text="Select")
- props.use_occlude_geometry = False
- props.only_selected = True
- col.operator("mesh.knife_project")
- col.operator("mesh.bisect")
-
- 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")
-
-
-class VIEW3D_PT_tools_meshweight(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "mesh_edit"
- bl_label = "Weight Tools"
- bl_options = {'DEFAULT_CLOSED'}
-
- # Used for Weight-Paint mode and Edit-Mode
- @staticmethod
- def draw_generic(layout):
- col = layout.column()
- 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")
- col.operator("object.vertex_group_invert", text="Invert")
- col.operator("object.vertex_group_clean", text="Clean")
- col.operator("object.vertex_group_quantize", text="Quantize")
- col.operator("object.vertex_group_levels", text="Levels")
- col.operator("object.vertex_group_smooth", text="Smooth")
- col.operator("object.vertex_group_limit_total", text="Limit Total")
- col.operator("object.vertex_group_fix", text="Fix Deforms")
-
- def draw(self, context):
- layout = self.layout
- self.draw_generic(layout)
-
-
-class VIEW3D_PT_tools_add_mesh_edit(View3DPanel, Panel):
- bl_category = "Create"
- bl_context = "mesh_edit"
- bl_label = "Add Meshes"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
-
- VIEW3D_PT_tools_add_object.draw_add_mesh(col, label=True)
-
-
-class VIEW3D_PT_tools_shading(View3DPanel, Panel):
- bl_category = "Shading / UVs"
- bl_context = "mesh_edit"
- bl_label = "Shading"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.label(text="Faces:")
- row = col.row(align=True)
- row.operator("mesh.faces_shade_smooth", text="Smooth")
- row.operator("mesh.faces_shade_flat", text="Flat")
- col.label(text="Edges:")
- row = col.row(align=True)
- row.operator("mesh.mark_sharp", text="Smooth").clear = True
- row.operator("mesh.mark_sharp", text="Sharp")
- col.label(text="Vertices:")
- row = col.row(align=True)
- props = row.operator("mesh.mark_sharp", text="Smooth")
- props.use_verts = True
- props.clear = True
- row.operator("mesh.mark_sharp", text="Sharp").use_verts = True
-
- 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.set_normals_from_faces", text="Set From Faces")
-
-
-class VIEW3D_PT_tools_uvs(View3DPanel, Panel):
- bl_category = "Shading / UVs"
- bl_context = "mesh_edit"
- bl_label = "UVs"
-
- 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
-
class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
bl_category = "Options"
- bl_context = "mesh_edit"
+ bl_context = ".mesh_edit" # dot on purpose (access from topbar)
bl_label = "Mesh Options"
@classmethod
@@ -493,85 +104,15 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
col.prop(tool_settings, "edge_path_live_unwrap")
col.label("Double Threshold:")
col.prop(tool_settings, "double_threshold", text="")
+ col.prop(tool_settings, "use_mesh_automerge") # , icon='AUTOMERGE_ON'
- if mesh.show_weight:
- col.label("Show Zero Weights:")
- col.row().prop(tool_settings, "vertex_group_user", expand=True)
# ********** default tools for editmode_curve ****************
-class VIEW3D_PT_tools_transform_curve(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "curve_edit"
- bl_label = "Transform"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.operator("transform.translate")
- col.operator("transform.rotate")
- col.operator("transform.resize", text="Scale")
-
- col = layout.column(align=True)
- col.operator("transform.tilt", text="Tilt")
- col.operator("transform.transform", text="Shrink/Fatten").mode = 'CURVE_SHRINKFATTEN'
-
-
-class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "curve_edit"
- bl_label = "Curve Tools"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.label(text="Curve:")
- col.operator("curve.duplicate_move", text="Duplicate")
- col.operator("curve.delete")
- col.operator("curve.cyclic_toggle")
- col.operator("curve.switch_direction")
- col.operator("curve.spline_type_set")
- col.operator("curve.radius_set")
-
- col = layout.column(align=True)
- col.label(text="Handles:")
- row = col.row(align=True)
- row.operator("curve.handle_type_set", text="Auto").type = 'AUTOMATIC'
- row.operator("curve.handle_type_set", text="Vector").type = 'VECTOR'
- row = col.row(align=True)
- row.operator("curve.handle_type_set", text="Align").type = 'ALIGNED'
- row.operator("curve.handle_type_set", text="Free").type = 'FREE_ALIGN'
-
- col = layout.column(align=True)
- col.operator("curve.normals_make_consistent")
-
- col = layout.column(align=True)
- col.label(text="Modeling:")
- col.operator("curve.extrude_move", text="Extrude")
- col.operator("curve.subdivide")
- col.operator("curve.smooth")
- col.operator("transform.vertex_random")
-
-
-class VIEW3D_PT_tools_add_curve_edit(View3DPanel, Panel):
- bl_category = "Create"
- bl_context = "curve_edit"
- bl_label = "Add Curves"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
-
- VIEW3D_PT_tools_add_object.draw_add_curve(col, label=True)
-
-
class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel):
bl_category = "Options"
- bl_context = "curve_edit"
+ bl_context = ".curve_edit" # dot on purpose (access from topbar)
bl_label = "Curve Stroke"
def draw(self, context):
@@ -623,128 +164,12 @@ class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel):
colsub.prop(cps, "surface_plane", expand=True)
-# ********** default tools for editmode_surface ****************
-
-class VIEW3D_PT_tools_transform_surface(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "surface_edit"
- bl_label = "Transform"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.operator("transform.translate")
- col.operator("transform.rotate")
- col.operator("transform.resize", text="Scale")
-
-
-class VIEW3D_PT_tools_surfaceedit(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "surface_edit"
- bl_label = "Surface Tools"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.label(text="Curve:")
- col.operator("curve.duplicate_move", text="Duplicate")
- col.operator("curve.delete")
- col.operator("curve.cyclic_toggle")
- col.operator("curve.switch_direction")
-
- col = layout.column(align=True)
- col.label(text="Modeling:")
- col.operator("curve.extrude", text="Extrude")
- col.operator("curve.spin")
- col.operator("curve.subdivide")
-
- col = layout.column(align=True)
- col.label(text="Deform:")
- col.operator("transform.vertex_random")
-
-
-class VIEW3D_PT_tools_add_surface_edit(View3DPanel, Panel):
- bl_category = "Create"
- bl_context = "surface_edit"
- bl_label = "Add Surfaces"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
-
- VIEW3D_PT_tools_add_object.draw_add_surface(col)
-
-
-# ********** default tools for editmode_text ****************
-
-
-class VIEW3D_PT_tools_textedit(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "text_edit"
- bl_label = "Text Tools"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.label(text="Set Case:")
- col.operator("font.case_set", text="To Upper").case = 'UPPER'
- col.operator("font.case_set", text="To Lower").case = 'LOWER'
-
- col = layout.column(align=True)
- col.label(text="Style:")
- col.operator("font.style_toggle", text="Bold").style = 'BOLD'
- col.operator("font.style_toggle", text="Italic").style = 'ITALIC'
- col.operator("font.style_toggle", text="Underline").style = 'UNDERLINE'
-
-
# ********** default tools for editmode_armature ****************
-class VIEW3D_PT_tools_armatureedit_transform(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "armature_edit"
- bl_label = "Transform"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.operator("transform.translate")
- col.operator("transform.rotate")
- col.operator("transform.resize", text="Scale")
-
-
-class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "armature_edit"
- bl_label = "Armature Tools"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
- col.label(text="Bones:")
- col.operator("armature.bone_primitive_add", text="Add")
- col.operator("armature.duplicate_move", text="Duplicate")
- col.operator("armature.delete", text="Delete")
-
- col = layout.column(align=True)
- col.label(text="Modeling:")
- col.operator("armature.extrude_move")
- col.operator("armature.subdivide", text="Subdivide")
-
- col = layout.column(align=True)
- col.label(text="Deform:")
- col.operator("transform.vertex_random")
-
-
class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
bl_category = "Options"
- bl_context = "armature_edit"
+ bl_context = ".armature_edit" # dot on purpose (access from topbar)
bl_label = "Armature Options"
def draw(self, context):
@@ -753,138 +178,30 @@ class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
self.layout.prop(arm, "use_mirror_x")
-# ********** default tools for editmode_mball ****************
-
-
-class VIEW3D_PT_tools_mballedit(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "mball_edit"
- bl_label = "Meta Tools"
-
- 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)
- col.label(text="Deform:")
- col.operator("transform.vertex_random")
-
-
-class VIEW3D_PT_tools_add_mball_edit(View3DPanel, Panel):
- bl_category = "Create"
- bl_context = "mball_edit"
- bl_label = "Add Metaball"
-
- def draw(self, context):
- layout = self.layout
-
- col = layout.column(align=True)
-
- VIEW3D_PT_tools_add_object.draw_add_mball(col)
-
-
-# ********** default tools for editmode_lattice ****************
-
-
-class VIEW3D_PT_tools_latticeedit(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "lattice_edit"
- bl_label = "Lattice Tools"
-
- 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)
- col.operator("lattice.make_regular")
-
- col = layout.column(align=True)
- col.label(text="Deform:")
- col.operator("transform.vertex_random")
-
-
# ********** default tools for pose-mode ****************
-
-class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "posemode"
- bl_label = "Pose Tools"
-
- 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)
- col.label(text="In-Between:")
- row = col.row(align=True)
- row.operator("pose.push", text="Push")
- row.operator("pose.relax", text="Relax")
- col.operator("pose.breakdown", text="Breakdowner")
-
- col = layout.column(align=True)
- col.label(text="Pose:")
- row = col.row(align=True)
- row.operator("pose.copy", text="Copy")
- row.operator("pose.paste", text="Paste")
-
- row = layout.row(align=True)
- row.operator("pose.propagate", text="Propagate")
- row.menu("VIEW3D_MT_pose_propagate", icon='TRIA_RIGHT', text="")
-
- col = layout.column(align=True)
- col.operator("poselib.pose_add", text="Add To Library")
-
- draw_keyframing_tools(context, layout)
-
- ob = context.object
- avs = ob.pose.animation_visualization
-
- col = layout.column(align=True)
- col.label(text="Motion Paths:")
- if avs.motion_path.has_motion_paths:
- row = col.row(align=True)
- row.operator("pose.paths_update", text="Update")
- row.operator("pose.paths_clear", text="", icon='X')
- else:
- col.operator("pose.paths_calculate", text="Calculate")
-
-
class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
bl_category = "Options"
- bl_context = "posemode"
+ bl_context = ".posemode" # dot on purpose (access from topbar)
bl_label = "Pose Options"
def draw(self, context):
arm = context.active_object.data
self.layout.prop(arm, "use_auto_ik")
+ self.layout.prop(arm, "use_mirror_x")
# ********** default tools for paint modes ****************
class View3DPaintPanel(UnifiedPaintPanel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel):
bl_category = "Tools"
+ bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "Missing Data"
@classmethod
@@ -930,22 +247,19 @@ class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel):
col.label("Missing Canvas", icon='INFO')
col.label("Add or assign a canvas image below")
col.label("Canvas Image:")
- # todo this should be combinded into a single row
- col.template_ID(toolsettings, "canvas", open="image.open")
- col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
+ col.template_ID(toolsettings, "canvas", new="image.new", open="image.open")
if toolsettings.missing_stencil:
col.separator()
col.label("Missing Stencil", icon='INFO')
col.label("Add or assign a stencil image below")
col.label("Stencil Image:")
- # todo this should be combinded into a single row
- col.template_ID(toolsettings, "stencil_image", open="image.open")
- col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
+ col.template_ID(toolsettings, "stencil_image", new="image.new", open="image.open")
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
- bl_category = "Tools"
+ bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_label = "Brush"
@classmethod
@@ -1199,9 +513,6 @@ class TEXTURE_UL_texpaintslots(UIList):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(item, "name", text="", emboss=False, icon_value=icon)
- if (not mat.use_nodes) and context.scene.render.engine in {'BLENDER_RENDER', 'BLENDER_GAME'}:
- mtex_index = mat.texture_paint_slots[index].index
- layout.prop(mat, "use_textures", text="", index=mtex_index)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="")
@@ -1213,16 +524,16 @@ class VIEW3D_MT_tools_projectpaint_uvlayer(Menu):
def draw(self, context):
layout = self.layout
- for i, tex in enumerate(context.active_object.data.uv_textures):
- props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
- props.data_path = "active_object.data.uv_textures.active_index"
+ for i, uv_layer in enumerate(context.active_object.data.uv_layers):
+ props = layout.operator("wm.context_set_int", text=uv_layer.name, translate=False)
+ props.data_path = "active_object.data.uv_layers.active_index"
props.value = i
+# TODO, move to space_view3d.py
class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
- bl_context = "imagepaint"
+ bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "Slots"
- bl_category = "Slots"
@classmethod
def poll(cls, context):
@@ -1262,26 +573,15 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
else:
slot = None
- if (not mat.use_nodes) and context.scene.render.engine in {'BLENDER_RENDER', 'BLENDER_GAME'}:
- row = col.row(align=True)
- row.operator_menu_enum("paint.add_texture_paint_slot", "type")
- row.operator("paint.delete_texture_paint_slot", text="", icon='X')
-
- if slot:
- col.prop(mat.texture_slots[slot.index], "blend_type")
- col.separator()
-
- if slot and slot.index != -1:
+ if slot and slot.is_valid:
col.label("UV Map:")
- col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
+ col.prop_search(slot, "uv_layer", ob.data, "uv_layers", text="")
elif settings.mode == 'IMAGE':
mesh = ob.data
- uv_text = mesh.uv_textures.active.name if mesh.uv_textures.active else ""
+ uv_text = mesh.uv_layers.active.name if mesh.uv_layers.active else ""
col.label("Canvas Image:")
- # todo this should be combinded into a single row
- col.template_ID(settings, "canvas", open="image.open")
- col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
+ col.template_ID(settings, "canvas", new="image.new", open="image.open")
col.label("UV Map:")
col.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False)
@@ -1289,10 +589,10 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
col.operator("image.save_dirty", text="Save All Images")
+# TODO, move to space_view3d.py
class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
- bl_context = "imagepaint"
+ bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "Mask"
- bl_category = "Slots"
@classmethod
def poll(cls, context):
@@ -1306,6 +606,7 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
toolsettings = context.tool_settings
ipaint = toolsettings.image_paint
@@ -1315,23 +616,29 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
col = layout.column()
col.active = ipaint.use_stencil_layer
- stencil_text = mesh.uv_texture_stencil.name if mesh.uv_texture_stencil else ""
- col.label("UV Map:")
- col.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
+ stencil_text = mesh.uv_layer_stencil.name if mesh.uv_layer_stencil else ""
+ split = col.split(0.5)
+ colsub = split.column()
+ colsub.alignment = 'RIGHT'
+ colsub.label("UV Layer")
+ split.column().menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
- col.label("Stencil Image:")
# todo this should be combinded into a single row
- col.template_ID(ipaint, "stencil_image", open="image.open")
- col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
+ split = col.split(0.5)
+ colsub = split.column()
+ colsub.alignment = 'RIGHT'
+ colsub.label("Stencil Image")
+ colsub = split.column()
+ colsub.template_ID(ipaint, "stencil_image", new="image.new", open="image.open")
- col.label("Visualization:")
row = col.row(align=True)
- row.prop(ipaint, "stencil_color", text="")
+ row.prop(ipaint, "stencil_color", text="Display Color")
row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_overlay(Panel, View3DPaintPanel):
- bl_category = "Options"
+ bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_label = "Overlay"
@classmethod
@@ -1396,8 +703,9 @@ class VIEW3D_PT_tools_brush_overlay(Panel, View3DPaintPanel):
sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
- bl_category = "Tools"
+ bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_label = "Texture"
bl_options = {'DEFAULT_CLOSED'}
@@ -1420,9 +728,9 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
brush_texture_settings(col, brush, context.sculpt_object)
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel):
- bl_category = "Tools"
- bl_context = "imagepaint"
+ bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "Texture Mask"
bl_options = {'DEFAULT_CLOSED'}
@@ -1443,8 +751,9 @@ class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel):
brush_mask_texture_settings(col, brush)
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
- bl_category = "Tools"
+ bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_label = "Stroke"
bl_options = {'DEFAULT_CLOSED'}
@@ -1463,12 +772,11 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
settings = self.paint_settings(context)
brush = settings.brush
+ layout.use_property_split = True
col = layout.column()
- col.label(text="Stroke Method:")
-
- col.prop(brush, "stroke_method", text="")
+ col.prop(brush, "stroke_method")
if brush.use_anchor:
col.separator()
@@ -1498,12 +806,16 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
if brush.sculpt_capabilities.has_jitter:
col.separator()
- row = col.row(align=True)
+ colsub = col.split(0.5)
+ row = colsub.row(align=True)
+ row.alignment = 'RIGHT'
+ row.label("Jitter")
+ row = colsub.row(align=True)
row.prop(brush, "use_relative_jitter", icon_only=True)
if brush.use_relative_jitter:
- row.prop(brush, "jitter", slider=True)
+ row.prop(brush, "jitter", slider=True, text="")
else:
- row.prop(brush, "jitter_absolute")
+ row.prop(brush, "jitter_absolute", text="")
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
if brush.sculpt_capabilities.has_smooth_stroke:
@@ -1541,8 +853,9 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
layout.prop(settings, "input_samples")
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
- bl_category = "Tools"
+ bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_label = "Curve"
bl_options = {'DEFAULT_CLOSED'}
@@ -1570,26 +883,31 @@ class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
+# TODO, move to space_view3d.py
class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
- bl_category = "Tools"
+ bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
bl_label = "Dyntopo"
bl_options = {'DEFAULT_CLOSED'}
+ bl_ui_units_x = 12
@classmethod
def poll(cls, context):
return (context.sculpt_object and context.tool_settings.sculpt)
def draw_header(self, context):
+ is_popover = self.is_popover
layout = self.layout
layout.operator(
"sculpt.dynamic_topology_toggle",
icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT',
text="",
- emboss=False,
+ emboss=is_popover,
)
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
toolsettings = context.tool_settings
sculpt = toolsettings.sculpt
@@ -1598,9 +916,10 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
col = layout.column()
col.active = context.sculpt_object.use_dynamic_topology_sculpting
- sub = col.column(align=True)
+
+ sub = col.column()
sub.active = (brush and brush.sculpt_tool != 'MASK')
- if (sculpt.detail_type_method == 'CONSTANT'):
+ if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
row = sub.row(align=True)
row.prop(sculpt, "constant_detail_resolution")
row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
@@ -1608,20 +927,23 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
sub.prop(sculpt, "detail_percent")
else:
sub.prop(sculpt, "detail_size")
- sub.prop(sculpt, "detail_refine_method", text="")
- sub.prop(sculpt, "detail_type_method", text="")
- col.separator()
+ sub.prop(sculpt, "detail_refine_method", text="Refine Method")
+ sub.prop(sculpt, "detail_type_method", text="Detailing")
+
col.prop(sculpt, "use_smooth_shading")
- col.operator("sculpt.optimize")
- if (sculpt.detail_type_method == 'CONSTANT'):
- col.operator("sculpt.detail_flood_fill")
+
col.separator()
+
col.prop(sculpt, "symmetrize_direction")
col.operator("sculpt.symmetrize")
+ col.operator("sculpt.optimize")
+ if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
+ col.operator("sculpt.detail_flood_fill")
+# TODO, move to space_view3d.py
class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
- bl_category = "Options"
+ bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
@@ -1653,8 +975,9 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
self.unified_paint_settings(layout, context)
+# TODO, move to space_view3d.py
class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
- bl_category = "Tools"
+ bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
bl_label = "Symmetry/Lock"
bl_options = {'DEFAULT_CLOSED'}
@@ -1667,35 +990,55 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
sculpt = context.tool_settings.sculpt
- col = layout.column(align=True)
- col.label(text="Mirror:")
+ split = layout.split()
+
+ col = split.column()
+ col.alignment = 'RIGHT'
+ col.label(text="Mirror")
+
+ col = split.column()
+
row = col.row(align=True)
row.prop(sculpt, "use_symmetry_x", text="X", toggle=True)
row.prop(sculpt, "use_symmetry_y", text="Y", toggle=True)
row.prop(sculpt, "use_symmetry_z", text="Z", toggle=True)
- layout.column().prop(sculpt, "radial_symmetry", text="Radial")
- layout.prop(sculpt, "use_symmetry_feather", text="Feather")
+ split = layout.split()
- layout.label(text="Lock:")
+ col = split.column()
+ col.alignment = 'RIGHT'
+ col.label(text="Lock")
- row = layout.row(align=True)
+ col = split.column()
+
+ row = col.row(align=True)
row.prop(sculpt, "lock_x", text="X", toggle=True)
row.prop(sculpt, "lock_y", text="Y", toggle=True)
row.prop(sculpt, "lock_z", text="Z", toggle=True)
- layout.label(text="Tiling:")
+ split = layout.split()
- row = layout.row(align=True)
+ col = split.column()
+ col.alignment = 'RIGHT'
+ col.label(text="Tiling")
+
+ col = split.column()
+
+ row = col.row(align=True)
row.prop(sculpt, "tile_x", text="X", toggle=True)
row.prop(sculpt, "tile_y", text="Y", toggle=True)
row.prop(sculpt, "tile_z", text="Z", toggle=True)
+ layout.use_property_split = True
+
+ layout.prop(sculpt, "use_symmetry_feather", text="Feather")
+ layout.column().prop(sculpt, "radial_symmetry", text="Radial")
layout.column().prop(sculpt, "tile_offset", text="Tile Offset")
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
- bl_category = "Options"
+ bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_label = "Appearance"
@classmethod
@@ -1739,25 +1082,9 @@ class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
# ********** default tools for weight-paint ****************
-class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
- bl_category = "Tools"
- bl_context = "weightpaint"
- bl_label = "Weight Tools"
-
- def draw(self, context):
- layout = self.layout
- VIEW3D_PT_tools_meshweight.draw_generic(layout)
-
- col = layout.column()
- col.operator("paint.weight_gradient")
- props = col.operator("object.data_transfer", text="Transfer Weights")
- props.use_reverse_transfer = True
- props.data_type = 'VGROUP_WEIGHTS'
-
-
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel):
- bl_category = "Tools"
- bl_context = "weightpaint"
+ bl_context = ".weightpaint"
bl_options = {'DEFAULT_CLOSED'}
bl_label = "Symmetry"
@@ -1768,9 +1095,9 @@ class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel):
draw_vpaint_symmetry(layout, wpaint)
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
- bl_category = "Options"
- bl_context = "weightpaint"
+ bl_context = ".weightpaint"
bl_label = "Options"
def draw(self, context):
@@ -1799,9 +1126,9 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
# ********** default tools for vertex-paint ****************
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
- bl_category = "Options"
- bl_context = "vertexpaint"
+ bl_context = ".vertexpaint" # dot on purpose (access from topbar)
bl_label = "Options"
def draw(self, context):
@@ -1815,9 +1142,9 @@ class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
self.unified_paint_settings(col, context)
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel):
- bl_category = "Tools"
- bl_context = "vertexpaint"
+ bl_context = ".vertexpaint" # dot on purpose (access from topbar)
bl_options = {'DEFAULT_CLOSED'}
bl_label = "Symmetry"
@@ -1831,9 +1158,9 @@ class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel):
# ********** default tools for texture-paint ****************
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel):
- bl_category = "Tools"
- bl_context = "imagepaint"
+ bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "External"
bl_options = {'DEFAULT_CLOSED'}
@@ -1853,9 +1180,9 @@ class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel):
col.operator("paint.project_image", text="Apply Camera Image")
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel):
- bl_category = "Tools"
- bl_context = "imagepaint"
+ bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "Symmetry"
bl_options = {'DEFAULT_CLOSED'}
@@ -1865,16 +1192,23 @@ class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel):
toolsettings = context.tool_settings
ipaint = toolsettings.image_paint
- col = layout.column(align=True)
+ split = layout.split()
+
+ col = split.column()
+ col.alignment = 'RIGHT'
+ col.label(text="Mirror")
+
+ col = split.column()
+
row = col.row(align=True)
row.prop(ipaint, "use_symmetry_x", text="X", toggle=True)
row.prop(ipaint, "use_symmetry_y", text="Y", toggle=True)
row.prop(ipaint, "use_symmetry_z", text="Z", toggle=True)
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel):
- bl_category = "Options"
- bl_context = "imagepaint"
+ bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "Project Paint"
@classmethod
@@ -1909,8 +1243,8 @@ class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel):
self.unified_paint_settings(layout, context)
+# TODO, move to space_view3d.py
class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
- bl_category = "Options"
bl_label = "Options"
@classmethod
@@ -1929,17 +1263,17 @@ class VIEW3D_MT_tools_projectpaint_stencil(Menu):
def draw(self, context):
layout = self.layout
- for i, tex in enumerate(context.active_object.data.uv_textures):
- props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
- props.data_path = "active_object.data.uv_texture_stencil_index"
+ for i, uv_layer in enumerate(context.active_object.data.uv_layers):
+ props = layout.operator("wm.context_set_int", text=uv_layer.name, translate=False)
+ props.data_path = "active_object.data.uv_layer_stencil_index"
props.value = i
+# TODO, move to space_view3d.py
class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
"""Default tools for particle mode"""
- bl_context = "particlemode"
+ bl_context = ".particlemode"
bl_label = "Options"
- bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -2038,60 +1372,10 @@ class VIEW3D_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Pa
bl_space_type = 'VIEW_3D'
-# Note: moved here so that it's always in last position in 'Tools' panels!
-class VIEW3D_PT_tools_history(View3DPanel, Panel):
- bl_category = "Tools"
- # No bl_context, we are always available!
- bl_label = "History"
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw(self, context):
- layout = self.layout
- obj = context.object
-
- col = layout.column(align=True)
- row = col.row(align=True)
- row.operator("ed.undo")
- row.operator("ed.redo")
- if obj is None or obj.mode != 'SCULPT':
- # Sculpt mode does not generate an undo menu it seems...
- col.operator("ed.undo_history")
-
- col = layout.column(align=True)
- col.label(text="Repeat:")
- col.operator("screen.repeat_last")
- col.operator("screen.repeat_history", text="History...")
-
-
classes = (
- VIEW3D_PT_tools_transform,
- VIEW3D_PT_tools_object,
- VIEW3D_PT_tools_add_object,
- VIEW3D_PT_tools_relations,
- VIEW3D_PT_tools_animation,
- VIEW3D_PT_tools_rigid_body,
- VIEW3D_PT_tools_transform_mesh,
- VIEW3D_PT_tools_meshedit,
- VIEW3D_PT_tools_meshweight,
- VIEW3D_PT_tools_add_mesh_edit,
- VIEW3D_PT_tools_shading,
- VIEW3D_PT_tools_uvs,
VIEW3D_PT_tools_meshedit_options,
- VIEW3D_PT_tools_transform_curve,
- VIEW3D_PT_tools_curveedit,
- VIEW3D_PT_tools_add_curve_edit,
VIEW3D_PT_tools_curveedit_options_stroke,
- VIEW3D_PT_tools_transform_surface,
- VIEW3D_PT_tools_surfaceedit,
- VIEW3D_PT_tools_add_surface_edit,
- VIEW3D_PT_tools_textedit,
- VIEW3D_PT_tools_armatureedit,
- VIEW3D_PT_tools_armatureedit_transform,
VIEW3D_PT_tools_armatureedit_options,
- VIEW3D_PT_tools_mballedit,
- VIEW3D_PT_tools_add_mball_edit,
- VIEW3D_PT_tools_latticeedit,
- VIEW3D_PT_tools_posemode,
VIEW3D_PT_tools_posemode_options,
VIEW3D_PT_imapaint_tools_missing,
VIEW3D_PT_tools_brush,
@@ -2108,7 +1392,6 @@ classes = (
VIEW3D_PT_sculpt_options,
VIEW3D_PT_sculpt_symmetry,
VIEW3D_PT_tools_brush_appearance,
- VIEW3D_PT_tools_weightpaint,
VIEW3D_PT_tools_weightpaint_symmetry,
VIEW3D_PT_tools_weightpaint_options,
VIEW3D_PT_tools_vertexpaint,
@@ -2124,7 +1407,6 @@ classes = (
VIEW3D_PT_tools_grease_pencil_sculpt,
VIEW3D_PT_tools_grease_pencil_brush,
VIEW3D_PT_tools_grease_pencil_brushcurves,
- VIEW3D_PT_tools_history,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 92411aeb0ef..e6500b7c2c0 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -43,18 +43,10 @@ class CompositorNodeCategory(SortedNodeCategory):
return (context.space_data.tree_type == 'CompositorNodeTree')
-class ShaderNewNodeCategory(SortedNodeCategory):
+class ShaderNodeCategory(SortedNodeCategory):
@classmethod
def poll(cls, context):
- return (context.space_data.tree_type == 'ShaderNodeTree' and
- context.scene.render.use_shading_nodes)
-
-
-class ShaderOldNodeCategory(SortedNodeCategory):
- @classmethod
- def poll(cls, context):
- return (context.space_data.tree_type == 'ShaderNodeTree' and
- not context.scene.render.use_shading_nodes)
+ return (context.space_data.tree_type == 'ShaderNodeTree')
class TextureNodeCategory(SortedNodeCategory):
@@ -142,62 +134,39 @@ def object_shader_nodes_poll(context):
snode.shader_type == 'OBJECT')
+def cycles_shader_nodes_poll(context):
+ return context.engine == 'CYCLES'
+
+
+def eevee_shader_nodes_poll(context):
+ return context.engine == 'BLENDER_EEVEE'
+
+
+def eevee_cycles_shader_nodes_poll(context):
+ return (cycles_shader_nodes_poll(context) or
+ eevee_shader_nodes_poll(context))
+
+
+def object_cycles_shader_nodes_poll(context):
+ return (object_shader_nodes_poll(context) and
+ cycles_shader_nodes_poll(context))
+
+
+def object_eevee_shader_nodes_poll(context):
+ return (object_shader_nodes_poll(context) and
+ eevee_shader_nodes_poll(context))
+
+
+def object_eevee_cycles_shader_nodes_poll(context):
+ return (object_shader_nodes_poll(context) and
+ eevee_cycles_shader_nodes_poll(context))
+
+
# All standard node categories currently used in nodes.
shader_node_categories = [
- # Shader Nodes
- ShaderOldNodeCategory("SH_INPUT", "Input", items=[
- NodeItem("ShaderNodeMaterial"),
- NodeItem("ShaderNodeCameraData"),
- NodeItem("ShaderNodeFresnel"),
- NodeItem("ShaderNodeLayerWeight"),
- NodeItem("ShaderNodeLampData"),
- NodeItem("ShaderNodeValue"),
- NodeItem("ShaderNodeRGB"),
- NodeItem("ShaderNodeTexture"),
- NodeItem("ShaderNodeGeometry"),
- NodeItem("ShaderNodeExtendedMaterial"),
- NodeItem("ShaderNodeParticleInfo"),
- NodeItem("ShaderNodeObjectInfo"),
- NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
- ]),
- ShaderOldNodeCategory("SH_OUTPUT", "Output", items=[
- NodeItem("ShaderNodeOutput"),
- NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
- ]),
- ShaderOldNodeCategory("SH_OP_COLOR", "Color", items=[
- NodeItem("ShaderNodeMixRGB"),
- NodeItem("ShaderNodeRGBCurve"),
- NodeItem("ShaderNodeInvert"),
- NodeItem("ShaderNodeHueSaturation"),
- NodeItem("ShaderNodeGamma"),
- ]),
- ShaderOldNodeCategory("SH_OP_VECTOR", "Vector", items=[
- NodeItem("ShaderNodeNormal"),
- NodeItem("ShaderNodeMapping"),
- NodeItem("ShaderNodeVectorCurve"),
- NodeItem("ShaderNodeVectorTransform"),
- NodeItem("ShaderNodeNormalMap"),
- ]),
- ShaderOldNodeCategory("SH_CONVERTOR", "Converter", items=[
- NodeItem("ShaderNodeValToRGB"),
- NodeItem("ShaderNodeRGBToBW"),
- NodeItem("ShaderNodeMath"),
- NodeItem("ShaderNodeVectorMath"),
- NodeItem("ShaderNodeSqueeze"),
- NodeItem("ShaderNodeSeparateRGB"),
- NodeItem("ShaderNodeCombineRGB"),
- NodeItem("ShaderNodeSeparateHSV"),
- NodeItem("ShaderNodeCombineHSV"),
- ]),
- ShaderOldNodeCategory("SH_GROUP", "Group", items=node_group_items),
- ShaderOldNodeCategory("SH_LAYOUT", "Layout", items=[
- NodeItem("NodeFrame"),
- NodeItem("NodeReroute"),
- ]),
-
- # New Shader Nodes (Cycles)
- ShaderNewNodeCategory("SH_NEW_INPUT", "Input", items=[
+ # Shader Nodes (Cycles and Eevee)
+ ShaderNodeCategory("SH_NEW_INPUT", "Input", items=[
NodeItem("ShaderNodeTexCoord"),
NodeItem("ShaderNodeAttribute"),
NodeItem("ShaderNodeLightPath"),
@@ -218,36 +187,37 @@ shader_node_categories = [
NodeItem("ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll),
NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
]),
- ShaderNewNodeCategory("SH_NEW_OUTPUT", "Output", items=[
- NodeItem("ShaderNodeOutputMaterial", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeOutputLamp", poll=object_shader_nodes_poll),
+ ShaderNodeCategory("SH_NEW_OUTPUT", "Output", items=[
+ NodeItem("ShaderNodeOutputMaterial", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeOutputLight", poll=object_cycles_shader_nodes_poll),
NodeItem("ShaderNodeOutputWorld", poll=world_shader_nodes_poll),
NodeItem("ShaderNodeOutputLineStyle", poll=line_style_shader_nodes_poll),
NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
]),
- ShaderNewNodeCategory("SH_NEW_SHADER", "Shader", items=[
- NodeItem("ShaderNodeMixShader"),
- NodeItem("ShaderNodeAddShader"),
- NodeItem("ShaderNodeBsdfDiffuse", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfPrincipled", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfGlossy", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfTransparent", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfRefraction", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfGlass", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfTranslucent", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfAnisotropic", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfVelvet", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfToon", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeSubsurfaceScattering", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeEmission", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeBsdfHair", poll=object_shader_nodes_poll),
+ ShaderNodeCategory("SH_NEW_SHADER", "Shader", items=[
+ NodeItem("ShaderNodeMixShader", poll=eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeAddShader", poll=eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfDiffuse", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfPrincipled", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfGlossy", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfTransparent", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfRefraction", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfGlass", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfTranslucent", poll=object_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfAnisotropic", poll=object_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfVelvet", poll=object_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfToon", poll=object_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeSubsurfaceScattering", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeEmission", poll=object_eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeBsdfHair", poll=object_cycles_shader_nodes_poll),
NodeItem("ShaderNodeBackground", poll=world_shader_nodes_poll),
- NodeItem("ShaderNodeHoldout", poll=object_shader_nodes_poll),
- NodeItem("ShaderNodeVolumeAbsorption"),
- NodeItem("ShaderNodeVolumeScatter"),
+ NodeItem("ShaderNodeHoldout", poll=object_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeVolumeAbsorption", poll=eevee_cycles_shader_nodes_poll),
+ NodeItem("ShaderNodeVolumeScatter", poll=eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeVolumePrincipled"),
+ NodeItem("ShaderNodeEeveeSpecular", poll=object_eevee_shader_nodes_poll),
]),
- ShaderNewNodeCategory("SH_NEW_TEXTURE", "Texture", items=[
+ ShaderNodeCategory("SH_NEW_TEXTURE", "Texture", items=[
NodeItem("ShaderNodeTexImage"),
NodeItem("ShaderNodeTexEnvironment"),
NodeItem("ShaderNodeTexSky"),
@@ -262,7 +232,7 @@ shader_node_categories = [
NodeItem("ShaderNodeTexPointDensity"),
NodeItem("ShaderNodeTexIES"),
]),
- ShaderNewNodeCategory("SH_NEW_OP_COLOR", "Color", items=[
+ ShaderNodeCategory("SH_NEW_OP_COLOR", "Color", items=[
NodeItem("ShaderNodeMixRGB"),
NodeItem("ShaderNodeRGBCurve"),
NodeItem("ShaderNodeInvert"),
@@ -271,7 +241,7 @@ shader_node_categories = [
NodeItem("ShaderNodeGamma"),
NodeItem("ShaderNodeBrightContrast"),
]),
- ShaderNewNodeCategory("SH_NEW_OP_VECTOR", "Vector", items=[
+ ShaderNodeCategory("SH_NEW_OP_VECTOR", "Vector", items=[
NodeItem("ShaderNodeMapping"),
NodeItem("ShaderNodeBump"),
NodeItem("ShaderNodeDisplacement"),
@@ -281,10 +251,11 @@ shader_node_categories = [
NodeItem("ShaderNodeVectorCurve"),
NodeItem("ShaderNodeVectorTransform"),
]),
- ShaderNewNodeCategory("SH_NEW_CONVERTOR", "Converter", items=[
+ ShaderNodeCategory("SH_NEW_CONVERTOR", "Converter", items=[
NodeItem("ShaderNodeMath"),
NodeItem("ShaderNodeValToRGB"),
NodeItem("ShaderNodeRGBToBW"),
+ NodeItem("ShaderNodeShaderToRGB", poll=object_eevee_shader_nodes_poll),
NodeItem("ShaderNodeVectorMath"),
NodeItem("ShaderNodeSeparateRGB"),
NodeItem("ShaderNodeCombineRGB"),
@@ -295,11 +266,11 @@ shader_node_categories = [
NodeItem("ShaderNodeWavelength"),
NodeItem("ShaderNodeBlackbody"),
]),
- ShaderNewNodeCategory("SH_NEW_SCRIPT", "Script", items=[
+ ShaderNodeCategory("SH_NEW_SCRIPT", "Script", items=[
NodeItem("ShaderNodeScript"),
]),
- ShaderNewNodeCategory("SH_NEW_GROUP", "Group", items=node_group_items),
- ShaderNewNodeCategory("SH_NEW_LAYOUT", "Layout", items=[
+ ShaderNodeCategory("SH_NEW_GROUP", "Group", items=node_group_items),
+ ShaderNodeCategory("SH_NEW_LAYOUT", "Layout", items=[
NodeItem("NodeFrame"),
NodeItem("NodeReroute"),
]),
diff --git a/release/scripts/templates_py/addon_add_object.py b/release/scripts/templates_py/addon_add_object.py
index b74c0f8ee25..d26f3d351bf 100644
--- a/release/scripts/templates_py/addon_add_object.py
+++ b/release/scripts/templates_py/addon_add_object.py
@@ -45,7 +45,7 @@ class OBJECT_OT_add_object(Operator, AddObjectHelper):
bl_label = "Add Mesh Object"
bl_options = {'REGISTER', 'UNDO'}
- scale = FloatVectorProperty(
+ scale: FloatVectorProperty(
name="scale",
default=(1.0, 1.0, 1.0),
subtype='TRANSLATION',
diff --git a/release/scripts/templates_py/background_job.py b/release/scripts/templates_py/background_job.py
index 2f444641a51..020dabeb258 100644
--- a/release/scripts/templates_py/background_job.py
+++ b/release/scripts/templates_py/background_job.py
@@ -42,11 +42,11 @@ def example_function(text, save_path, render_path):
scene.camera = cam_ob # set the active camera
cam_ob.location = 0.0, 0.0, 10.0
- # Lamp
- lamp_data = bpy.data.lamps.new("MyLamp", 'POINT')
- lamp_ob = bpy.data.objects.new(name="MyCam", object_data=lamp_data)
- scene.objects.link(lamp_ob)
- lamp_ob.location = 2.0, 2.0, 5.0
+ # Light
+ light_data = bpy.data.lights.new("MyLight", 'POINT')
+ light_ob = bpy.data.objects.new(name="MyCam", object_data=light_data)
+ scene.objects.link(light_ob)
+ light_ob.location = 2.0, 2.0, 5.0
if save_path:
bpy.ops.wm.save_as_mainfile(filepath=save_path)
diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py
index 0fc888a2d4e..1463915886a 100644
--- a/release/scripts/templates_py/batch_export.py
+++ b/release/scripts/templates_py/batch_export.py
@@ -18,7 +18,7 @@ bpy.ops.object.select_all(action='DESELECT')
for obj in selection:
- obj.select = True
+ obj.select_set(action='SELECT')
# some exporters only use the active object
scene.objects.active = obj
@@ -31,7 +31,7 @@ for obj in selection:
# Can be used for multiple formats
# bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
- obj.select = False
+ obj.select_set(action='DESELECT')
print("written:", fn)
@@ -39,4 +39,4 @@ for obj in selection:
scene.objects.active = obj_active
for obj in selection:
- obj.select = True
+ obj.select_set(action='SELECT')
diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py
index 23d8ee55e72..7e4e89dafeb 100644
--- a/release/scripts/templates_py/custom_nodes.py
+++ b/release/scripts/templates_py/custom_nodes.py
@@ -30,10 +30,15 @@ class MyCustomSocket(NodeSocket):
('DOWN', "Down", "Where your feet are"),
('UP', "Up", "Where your head should be"),
('LEFT', "Left", "Not right"),
- ('RIGHT', "Right", "Not left")
+ ('RIGHT', "Right", "Not left"),
)
- my_enum_prop = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP')
+ my_enum_prop: bpy.props.EnumProperty(
+ name="Direction",
+ description="Just an example",
+ items=my_items,
+ default='UP',
+ )
# Optional function for drawing the socket input value
def draw(self, context, layout, node, text):
@@ -71,8 +76,8 @@ class MyCustomNode(Node, MyCustomTreeNode):
# These work just like custom properties in ID data blocks
# Extensive information can be found under
# http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties
- my_string_prop = bpy.props.StringProperty()
- my_float_prop = bpy.props.FloatProperty(default=3.1415926)
+ my_string_prop: bpy.props.StringProperty()
+ my_float_prop: bpy.props.FloatProperty(default=3.1415926)
# === Optional Functions ===
# Initialization function, called when a new node is created.
diff --git a/release/scripts/templates_py/gamelogic.py b/release/scripts/templates_py/gamelogic.py
deleted file mode 100644
index e3bb4a7bb78..00000000000
--- a/release/scripts/templates_py/gamelogic.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# This script must be assigned to a python controller
-# where it can access the object that owns it and the sensors/actuators that it connects to.
-
-import bge
-
-# support for Vector(), Matrix() types and advanced functions like Matrix.Scale(...) and Matrix.Rotation(...)
-# import mathutils
-
-# for functions like getWindowWidth(), getWindowHeight()
-# import Rasterizer
-
-
-def main():
- cont = bge.logic.getCurrentController()
-
- # The KX_GameObject that owns this controller.
- own = cont.owner
-
- # for scripts that deal with spacial logic
- own_pos = own.worldPosition
-
- # Some example functions, remove to write your own script.
- # check for a positive sensor, will run on any object without errors.
- print("Logic info for KX_GameObject", own.name)
- input = False
-
- for sens in cont.sensors:
- # The sensor can be on another object, we may want to use it
- own_sens = sens.owner
- print(" sensor:", sens.name, end=" ")
- if sens.positive:
- print("(true)")
- input = True
- else:
- print("(false)")
-
- for actu in cont.actuators:
- # The actuator can be on another object, we may want to use it
- own_actu = actu.owner
- print(" actuator:", actu.name)
-
- # This runs the actuator or turns it off
- # note that actuators will continue to run unless explicitly turned off.
- if input:
- cont.activate(actu)
- else:
- cont.deactivate(actu)
-
- # Its also good practice to get sensors and actuators by name
- # rather then index so any changes to their order wont break the script.
-
- # sens_key = cont.sensors["key_sensor"]
- # actu_motion = cont.actuators["motion"]
-
- # Loop through all other objects in the scene
- sce = bge.logic.getCurrentScene()
- print("Scene Objects:", sce.name)
- for ob in sce.objects:
- print(" ", ob.name, ob.worldPosition)
-
- # Example where collision objects are checked for their properties
- # adding to our objects "life" property
- """
- actu_collide = cont.sensors["collision_sens"]
- for ob in actu_collide.hitObjectList:
- # Check to see the object has this property
- if "life" in ob:
- own["life"] += ob["life"]
- ob["life"] = 0
- print(own["life"])
- """
-
-
-main()
diff --git a/release/scripts/templates_py/gamelogic_module.py b/release/scripts/templates_py/gamelogic_module.py
deleted file mode 100644
index 88c8cf0d75b..00000000000
--- a/release/scripts/templates_py/gamelogic_module.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This module can be accessed by a python controller with
-# its execution method set to 'Module'
-# * Set the module string to "gamelogic_module.main" (without quotes)
-# * When renaming the script it MUST have a .py extension
-# * External text modules are supported as long as they are at
-# the same location as the blendfile or one of its libraries.
-
-import bge
-
-# variables defined here will only be set once when the
-# module is first imported. Set object specific vars
-# inside the function if you intend to use the module
-# with multiple objects.
-
-
-def main(cont):
- own = cont.owner
-
- sens = cont.sensors['mySensor']
- actu = cont.actuators['myActuator']
-
- if sens.positive:
- cont.activate(actu)
- else:
- cont.deactivate(actu)
-
-# dont call main(bge.logic.getCurrentController()), the py controller will
diff --git a/release/scripts/templates_py/gamelogic_simple.py b/release/scripts/templates_py/gamelogic_simple.py
deleted file mode 100644
index 31cb1885717..00000000000
--- a/release/scripts/templates_py/gamelogic_simple.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import bge
-
-
-def main():
-
- cont = bge.logic.getCurrentController()
- own = cont.owner
-
- sens = cont.sensors['mySensor']
- actu = cont.actuators['myActuator']
-
- if sens.positive:
- cont.activate(actu)
- else:
- cont.deactivate(actu)
-
-
-main()
diff --git a/release/scripts/templates_py/manipulator_custom_geometry.py b/release/scripts/templates_py/manipulator_custom_geometry.py
new file mode 100644
index 00000000000..de324a909db
--- /dev/null
+++ b/release/scripts/templates_py/manipulator_custom_geometry.py
@@ -0,0 +1,158 @@
+# Example of a custom widget that defines it's own geometry.
+#
+# Usage: Select a light in the 3D view and drag the arrow at it's rear
+# to change it's energy value.
+#
+import bpy
+from bpy.types import (
+ Manipulator,
+ ManipulatorGroup,
+)
+
+# Coordinates (each one is a triangle).
+custom_shape_verts = (
+ (3.0, 1.0, -1.0), (2.0, 2.0, -1.0), (3.0, 3.0, -1.0),
+ (1.0, 3.0, 1.0), (3.0, 3.0, -1.0), (1.0, 3.0, -1.0),
+ (3.0, 3.0, 1.0), (3.0, 1.0, -1.0), (3.0, 3.0, -1.0),
+ (2.0, 0.0, 1.0), (3.0, 1.0, -1.0), (3.0, 1.0, 1.0),
+ (2.0, 0.0, -1.0), (2.0, 2.0, 1.0), (2.0, 2.0, -1.0),
+ (2.0, 2.0, -1.0), (0.0, 2.0, 1.0), (0.0, 2.0, -1.0),
+ (1.0, 3.0, 1.0), (2.0, 2.0, 1.0), (3.0, 3.0, 1.0),
+ (0.0, 2.0, -1.0), (1.0, 3.0, 1.0), (1.0, 3.0, -1.0),
+ (2.0, 2.0, 1.0), (3.0, 1.0, 1.0), (3.0, 3.0, 1.0),
+ (2.0, 2.0, -1.0), (1.0, 3.0, -1.0), (3.0, 3.0, -1.0),
+ (-3.0, -1.0, -1.0), (-2.0, -2.0, -1.0), (-3.0, -3.0, -1.0),
+ (-1.0, -3.0, 1.0), (-3.0, -3.0, -1.0), (-1.0, -3.0, -1.0),
+ (-3.0, -3.0, 1.0), (-3.0, -1.0, -1.0), (-3.0, -3.0, -1.0),
+ (-2.0, 0.0, 1.0), (-3.0, -1.0, -1.0), (-3.0, -1.0, 1.0),
+ (-2.0, 0.0, -1.0), (-2.0, -2.0, 1.0), (-2.0, -2.0, -1.0),
+ (-2.0, -2.0, -1.0), (0.0, -2.0, 1.0), (0.0, -2.0, -1.0),
+ (-1.0, -3.0, 1.0), (-2.0, -2.0, 1.0), (-3.0, -3.0, 1.0),
+ (0.0, -2.0, -1.0), (-1.0, -3.0, 1.0), (-1.0, -3.0, -1.0),
+ (-2.0, -2.0, 1.0), (-3.0, -1.0, 1.0), (-3.0, -3.0, 1.0),
+ (-2.0, -2.0, -1.0), (-1.0, -3.0, -1.0), (-3.0, -3.0, -1.0),
+ (1.0, -1.0, 0.0), (-1.0, -1.0, 0.0), (0.0, 0.0, -5.0),
+ (-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (0.0, 0.0, 5.0),
+ (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (0.0, 0.0, 5.0),
+ (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0), (0.0, 0.0, 5.0),
+ (-1.0, 1.0, 0.0), (-1.0, -1.0, 0.0), (0.0, 0.0, 5.0),
+ (-1.0, -1.0, 0.0), (-1.0, 1.0, 0.0), (0.0, 0.0, -5.0),
+ (-1.0, 1.0, 0.0), (1.0, 1.0, 0.0), (0.0, 0.0, -5.0),
+ (1.0, 1.0, 0.0), (1.0, -1.0, 0.0), (0.0, 0.0, -5.0),
+ (3.0, 1.0, -1.0), (2.0, 0.0, -1.0), (2.0, 2.0, -1.0),
+ (1.0, 3.0, 1.0), (3.0, 3.0, 1.0), (3.0, 3.0, -1.0),
+ (3.0, 3.0, 1.0), (3.0, 1.0, 1.0), (3.0, 1.0, -1.0),
+ (2.0, 0.0, 1.0), (2.0, 0.0, -1.0), (3.0, 1.0, -1.0),
+ (2.0, 0.0, -1.0), (2.0, 0.0, 1.0), (2.0, 2.0, 1.0),
+ (2.0, 2.0, -1.0), (2.0, 2.0, 1.0), (0.0, 2.0, 1.0),
+ (1.0, 3.0, 1.0), (0.0, 2.0, 1.0), (2.0, 2.0, 1.0),
+ (0.0, 2.0, -1.0), (0.0, 2.0, 1.0), (1.0, 3.0, 1.0),
+ (2.0, 2.0, 1.0), (2.0, 0.0, 1.0), (3.0, 1.0, 1.0),
+ (2.0, 2.0, -1.0), (0.0, 2.0, -1.0), (1.0, 3.0, -1.0),
+ (-3.0, -1.0, -1.0), (-2.0, 0.0, -1.0), (-2.0, -2.0, -1.0),
+ (-1.0, -3.0, 1.0), (-3.0, -3.0, 1.0), (-3.0, -3.0, -1.0),
+ (-3.0, -3.0, 1.0), (-3.0, -1.0, 1.0), (-3.0, -1.0, -1.0),
+ (-2.0, 0.0, 1.0), (-2.0, 0.0, -1.0), (-3.0, -1.0, -1.0),
+ (-2.0, 0.0, -1.0), (-2.0, 0.0, 1.0), (-2.0, -2.0, 1.0),
+ (-2.0, -2.0, -1.0), (-2.0, -2.0, 1.0), (0.0, -2.0, 1.0),
+ (-1.0, -3.0, 1.0), (0.0, -2.0, 1.0), (-2.0, -2.0, 1.0),
+ (0.0, -2.0, -1.0), (0.0, -2.0, 1.0), (-1.0, -3.0, 1.0),
+ (-2.0, -2.0, 1.0), (-2.0, 0.0, 1.0), (-3.0, -1.0, 1.0),
+ (-2.0, -2.0, -1.0), (0.0, -2.0, -1.0), (-1.0, -3.0, -1.0),
+)
+
+
+class MyCustomShapeWidget(Manipulator):
+ bl_idname = "VIEW3D_WT_auto_facemap"
+ bl_target_properties = (
+ {"id": "offset", "type": 'FLOAT', "array_length": 1},
+ )
+
+ __slots__ = (
+ "custom_shape",
+ "init_mouse_y",
+ "init_value",
+ )
+
+ def _update_offset_matrix(self):
+ # offset behind the light
+ self.matrix_offset.col[3][2] = self.target_get_value("offset") / -10.0
+
+ def draw(self, context):
+ self._update_offset_matrix()
+ self.draw_custom_shape(self.custom_shape)
+
+ def draw_select(self, context, select_id):
+ self._update_offset_matrix()
+ self.draw_custom_shape(self.custom_shape, select_id=select_id)
+
+ def setup(self):
+ if not hasattr(self, "custom_shape"):
+ self.custom_shape = self.new_custom_shape('TRIS', custom_shape_verts)
+
+ def invoke(self, context, event):
+ self.init_mouse_y = event.mouse_y
+ self.init_value = self.target_get_value("offset")
+ return {'RUNNING_MODAL'}
+
+ def exit(self, context, cancel):
+ context.area.header_text_set()
+ if cancel:
+ self.target_set_value("offset", self.init_value)
+
+ def modal(self, context, event, tweak):
+ delta = (event.mouse_y - self.init_mouse_y) / 10.0
+ if 'SNAP' in tweak:
+ delta = round(delta)
+ if 'PRECISE' in tweak:
+ delta /= 10.0
+ value = self.init_value + delta
+ self.target_set_value("offset", value)
+ context.area.header_text_set("My Manipulator: %.4f" % value)
+ return {'RUNNING_MODAL'}
+
+
+class MyCustomShapeWidgetGroup(ManipulatorGroup):
+ bl_idname = "OBJECT_WGT_light_test"
+ bl_label = "Test Light Widget"
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'WINDOW'
+ bl_options = {'3D', 'PERSISTENT'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (ob and ob.type == 'LIGHT')
+
+ def setup(self, context):
+ # Assign the 'offset' target property to the light energy.
+ ob = context.object
+ mpr = self.manipulators.new(MyCustomShapeWidget.bl_idname)
+ mpr.target_set_prop("offset", ob.data, "energy")
+ mpr.matrix_basis = ob.matrix_world.normalized()
+
+ mpr.color = 1.0, 0.5, 1.0
+ mpr.alpha = 0.5
+
+ mpr.color_highlight = 1.0, 1.0, 1.0
+ mpr.alpha_highlight = 0.5
+
+ # units are large, so shrink to something more reasonable.
+ mpr.scale_basis = 0.1
+ mpr.use_draw_modal = True
+
+ self.energy_widget = mpr
+
+ def refresh(self, context):
+ ob = context.object
+ mpr = self.energy_widget
+ mpr.matrix_basis = ob.matrix_world.normalized()
+
+
+classes = (
+ MyCustomShapeWidget,
+ MyCustomShapeWidgetGroup,
+)
+
+for cls in classes:
+ bpy.utils.register_class(cls)
diff --git a/release/scripts/templates_py/manipulator_operator.py b/release/scripts/templates_py/manipulator_operator.py
new file mode 100644
index 00000000000..61796489a95
--- /dev/null
+++ b/release/scripts/templates_py/manipulator_operator.py
@@ -0,0 +1,234 @@
+# Example of an operator which uses manipulators to control its properties.
+#
+# Usage: Run this script, then in mesh edit-mode press Spacebar
+# to activate the operator "Select Side of Plane"
+# The manipulators can then be used to adjust the plane in the 3D view.
+#
+import bpy
+import bmesh
+
+from bpy.types import (
+ Operator,
+ ManipulatorGroup,
+)
+
+from bpy.props import (
+ FloatVectorProperty,
+)
+
+
+def main(context, plane_co, plane_no):
+ obj = context.active_object
+ matrix = obj.matrix_world.copy()
+ me = obj.data
+ bm = bmesh.from_edit_mesh(me)
+
+ plane_dot = plane_no.dot(plane_co)
+
+ for v in bm.verts:
+ co = matrix * v.co
+ v.select = (plane_no.dot(co) > plane_dot)
+ bm.select_flush_mode()
+
+ bmesh.update_edit_mesh(me)
+
+
+class SelectSideOfPlane(Operator):
+ """UV Operator description"""
+ bl_idname = "mesh.select_side_of_plane"
+ bl_label = "Select Side of Plane"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ plane_co: FloatVectorProperty(
+ size=3,
+ default=(0, 0, 0),
+ )
+ plane_no: FloatVectorProperty(
+ size=3,
+ default=(0, 0, 1),
+ )
+
+ @classmethod
+ def poll(cls, context):
+ return (context.mode == 'EDIT_MESH')
+
+ def invoke(self, context, event):
+
+ if not self.properties.is_property_set("plane_co"):
+ self.plane_co = context.scene.cursor_location
+
+ if not self.properties.is_property_set("plane_no"):
+ if context.space_data.type == 'VIEW_3D':
+ rv3d = context.space_data.region_3d
+ view_inv = rv3d.view_matrix.to_3x3()
+ # view y axis
+ self.plane_no = view_inv[1].normalized()
+
+ self.execute(context)
+
+ if context.space_data.type == 'VIEW_3D':
+ wm = context.window_manager
+ wm.manipulator_group_type_add(SelectSideOfPlaneManipulatorGroup.bl_idname)
+
+ return {'FINISHED'}
+
+ def execute(self, context):
+ from mathutils import Vector
+ main(context, Vector(self.plane_co), Vector(self.plane_no))
+ return {'FINISHED'}
+
+
+# Manipulators for plane_co, plane_no
+class SelectSideOfPlaneManipulatorGroup(ManipulatorGroup):
+ bl_idname = "MESH_WGT_select_side_of_plane"
+ bl_label = "Side of Plane Manipulator"
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'WINDOW'
+ bl_options = {'3D'}
+
+ # Helper functions
+ @staticmethod
+ def my_target_operator(context):
+ wm = context.window_manager
+ op = wm.operators[-1] if wm.operators else None
+ if isinstance(op, SelectSideOfPlane):
+ return op
+ return None
+
+ @staticmethod
+ def my_view_orientation(context):
+ rv3d = context.space_data.region_3d
+ view_inv = rv3d.view_matrix.to_3x3()
+ return view_inv.normalized()
+
+ @classmethod
+ def poll(cls, context):
+ op = cls.my_target_operator(context)
+ if op is None:
+ wm = context.window_manager
+ wm.manipulator_group_type_remove(SelectSideOfPlaneManipulatorGroup.bl_idname)
+ return False
+ return True
+
+ def setup(self, context):
+ from mathutils import Matrix, Vector
+
+ # ----
+ # Grab
+
+ def grab_get_cb():
+ op = SelectSideOfPlaneManipulatorGroup.my_target_operator(context)
+ return op.plane_co
+
+ def grab_set_cb(value):
+ op = SelectSideOfPlaneManipulatorGroup.my_target_operator(context)
+ op.plane_co = value
+ # XXX, this may change!
+ op.execute(context)
+
+ mpr = self.manipulators.new("MANIPULATOR_WT_grab_3d")
+ mpr.target_set_handler("offset", get=grab_get_cb, set=grab_set_cb)
+
+ mpr.use_draw_value = True
+
+ mpr.color = 0.8, 0.8, 0.8
+ mpr.alpha = 0.5
+
+ mpr.color_highlight = 1.0, 1.0, 1.0
+ mpr.alpha_highlight = 1.0
+
+ mpr.scale_basis = 0.2
+
+ self.widget_grab = mpr
+
+ # ----
+ # Dial
+
+ def direction_get_cb():
+ op = SelectSideOfPlaneManipulatorGroup.my_target_operator(context)
+
+ no_a = self.widget_dial.matrix_basis.col[1].xyz
+ no_b = Vector(op.plane_no)
+
+ no_a = (no_a * self.view_inv).xy.normalized()
+ no_b = (no_b * self.view_inv).xy.normalized()
+ return no_a.angle_signed(no_b)
+
+ def direction_set_cb(value):
+ op = SelectSideOfPlaneManipulatorGroup.my_target_operator(context)
+ matrix_rotate = Matrix.Rotation(-value, 3, self.rotate_axis)
+ no = matrix_rotate * self.widget_dial.matrix_basis.col[1].xyz
+ op.plane_no = no
+ op.execute(context)
+
+ mpr = self.manipulators.new("MANIPULATOR_WT_dial_3d")
+ mpr.target_set_handler("offset", get=direction_get_cb, set=direction_set_cb)
+ mpr.draw_options = {'ANGLE_START_Y'}
+
+ mpr.use_draw_value = True
+
+ mpr.color = 0.8, 0.8, 0.8
+ mpr.alpha = 0.5
+
+ mpr.color_highlight = 1.0, 1.0, 1.0
+ mpr.alpha_highlight = 1.0
+
+ self.widget_dial = mpr
+
+ def draw_prepare(self, context):
+ from mathutils import Vector
+
+ view_inv = self.my_view_orientation(context)
+
+ self.view_inv = view_inv
+ self.rotate_axis = view_inv[2].xyz
+ self.rotate_up = view_inv[1].xyz
+
+ op = self.my_target_operator(context)
+
+ co = Vector(op.plane_co)
+ no = Vector(op.plane_no).normalized()
+
+ # Grab
+ no_z = no
+ no_y = no_z.orthogonal()
+ no_x = no_z.cross(no_y)
+
+ matrix = self.widget_grab.matrix_basis
+ matrix.identity()
+ matrix.col[0].xyz = no_x
+ matrix.col[1].xyz = no_y
+ matrix.col[2].xyz = no_z
+ matrix.col[3].xyz = co
+
+ # Dial
+ no_z = self.rotate_axis
+ no_y = (no - (no.project(no_z))).normalized()
+ no_x = self.rotate_axis.cross(no_y)
+
+ matrix = self.widget_dial.matrix_basis
+ matrix.identity()
+ matrix.col[0].xyz = no_x
+ matrix.col[1].xyz = no_y
+ matrix.col[2].xyz = no_z
+ matrix.col[3].xyz = co
+
+
+classes = (
+ SelectSideOfPlane,
+ SelectSideOfPlaneManipulatorGroup,
+)
+
+
+def register():
+ for cls in classes:
+ bpy.utils.register_class(cls)
+
+
+def unregister():
+ for cls in reversed(classes):
+ bpy.utils.unregister_class(cls)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/templates_py/manipulator_operator_target.py b/release/scripts/templates_py/manipulator_operator_target.py
new file mode 100644
index 00000000000..ba53b5e10ff
--- /dev/null
+++ b/release/scripts/templates_py/manipulator_operator_target.py
@@ -0,0 +1,50 @@
+# Example of a manipulator that activates an operator
+# using the predefined dial manipulator to change the camera roll.
+#
+# Usage: Run this script and select a camera in the 3D view.
+#
+import bpy
+from bpy.types import (
+ ManipulatorGroup,
+)
+
+
+class MyCameraWidgetGroup(ManipulatorGroup):
+ bl_idname = "OBJECT_WGT_test_camera"
+ bl_label = "Object Camera Test Widget"
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'WINDOW'
+ bl_options = {'3D', 'PERSISTENT'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (ob and ob.type == 'CAMERA')
+
+ def setup(self, context):
+ # Run an operator using the dial manipulator
+ ob = context.object
+ mpr = self.manipulators.new("MANIPULATOR_WT_dial_3d")
+ props = mpr.target_set_operator("transform.rotate")
+ props.constraint_axis = False, False, True
+ props.constraint_orientation = 'LOCAL'
+ props.release_confirm = True
+
+ mpr.matrix_basis = ob.matrix_world.normalized()
+ mpr.line_width = 3
+
+ mpr.color = 0.8, 0.8, 0.8
+ mpr.alpha = 0.5
+
+ mpr.color_highlight = 1.0, 1.0, 1.0
+ mpr.alpha_highlight = 1.0
+
+ self.roll_widget = mpr
+
+ def refresh(self, context):
+ ob = context.object
+ mpr = self.roll_widget
+ mpr.matrix_basis = ob.matrix_world.normalized()
+
+
+bpy.utils.register_class(MyCameraWidgetGroup)
diff --git a/release/scripts/templates_py/manipulator_simple.py b/release/scripts/templates_py/manipulator_simple.py
new file mode 100644
index 00000000000..cb10a8b94bb
--- /dev/null
+++ b/release/scripts/templates_py/manipulator_simple.py
@@ -0,0 +1,47 @@
+# Example of a group that edits a single property
+# using the predefined manipulator arrow.
+#
+# Usage: Select a light in the 3D view and drag the arrow at it's rear
+# to change it's energy value.
+#
+import bpy
+from bpy.types import (
+ ManipulatorGroup,
+)
+
+
+class MyLightWidgetGroup(ManipulatorGroup):
+ bl_idname = "OBJECT_WGT_light_test"
+ bl_label = "Test Light Widget"
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'WINDOW'
+ bl_options = {'3D', 'PERSISTENT'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (ob and ob.type == 'LIGHT')
+
+ def setup(self, context):
+ # Arrow manipulator has one 'offset' property we can assign to the light energy.
+ ob = context.object
+ mpr = self.manipulators.new("MANIPULATOR_WT_arrow_3d")
+ mpr.target_set_prop("offset", ob.data, "energy")
+ mpr.matrix_basis = ob.matrix_world.normalized()
+ mpr.draw_style = 'BOX'
+
+ mpr.color = 1.0, 0.5, 0.0
+ mpr.alpha = 0.5
+
+ mpr.color_highlight = 1.0, 0.5, 1.0
+ mpr.alpha_highlight = 0.5
+
+ self.energy_widget = mpr
+
+ def refresh(self, context):
+ ob = context.object
+ mpr = self.energy_widget
+ mpr.matrix_basis = ob.matrix_world.normalized()
+
+
+bpy.utils.register_class(MyLightWidgetGroup)
diff --git a/release/scripts/templates_py/operator_file_export.py b/release/scripts/templates_py/operator_file_export.py
index 8a1eb4ae54c..4ea817d3507 100644
--- a/release/scripts/templates_py/operator_file_export.py
+++ b/release/scripts/templates_py/operator_file_export.py
@@ -25,7 +25,7 @@ class ExportSomeData(Operator, ExportHelper):
# ExportHelper mixin class uses this
filename_ext = ".txt"
- filter_glob = StringProperty(
+ filter_glob: StringProperty(
default="*.txt",
options={'HIDDEN'},
maxlen=255, # Max internal buffer length, longer would be clamped.
@@ -33,13 +33,13 @@ class ExportSomeData(Operator, ExportHelper):
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
- use_setting = BoolProperty(
+ use_setting: BoolProperty(
name="Example Boolean",
description="Example Tooltip",
default=True,
)
- type = EnumProperty(
+ type: EnumProperty(
name="Example Enum",
description="Choose between two items",
items=(
diff --git a/release/scripts/templates_py/operator_file_import.py b/release/scripts/templates_py/operator_file_import.py
index 9856b6a9040..b932b008c49 100644
--- a/release/scripts/templates_py/operator_file_import.py
+++ b/release/scripts/templates_py/operator_file_import.py
@@ -28,7 +28,7 @@ class ImportSomeData(Operator, ImportHelper):
# ImportHelper mixin class uses this
filename_ext = ".txt"
- filter_glob = StringProperty(
+ filter_glob: StringProperty(
default="*.txt",
options={'HIDDEN'},
maxlen=255, # Max internal buffer length, longer would be clamped.
@@ -36,13 +36,13 @@ class ImportSomeData(Operator, ImportHelper):
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
- use_setting = BoolProperty(
+ use_setting: BoolProperty(
name="Example Boolean",
description="Example Tooltip",
default=True,
)
- type = EnumProperty(
+ type: EnumProperty(
name="Example Enum",
description="Choose between two items",
items=(
diff --git a/release/scripts/templates_py/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py
index 407956a0fda..6b39ef7bbba 100644
--- a/release/scripts/templates_py/operator_mesh_add.py
+++ b/release/scripts/templates_py/operator_mesh_add.py
@@ -49,25 +49,25 @@ class AddBox(bpy.types.Operator):
bl_label = "Add Box"
bl_options = {'REGISTER', 'UNDO'}
- width = FloatProperty(
+ width: FloatProperty(
name="Width",
description="Box Width",
min=0.01, max=100.0,
default=1.0,
)
- height = FloatProperty(
+ height: FloatProperty(
name="Height",
description="Box Height",
min=0.01, max=100.0,
default=1.0,
)
- depth = FloatProperty(
+ depth: FloatProperty(
name="Depth",
description="Box Depth",
min=0.01, max=100.0,
default=1.0,
)
- layers = BoolVectorProperty(
+ layers: BoolVectorProperty(
name="Layers",
description="Object Layers",
size=20,
@@ -75,15 +75,15 @@ class AddBox(bpy.types.Operator):
)
# generic transform props
- view_align = BoolProperty(
+ view_align: BoolProperty(
name="Align to View",
default=False,
)
- location = FloatVectorProperty(
+ location: FloatVectorProperty(
name="Location",
subtype='TRANSLATION',
)
- rotation = FloatVectorProperty(
+ rotation: FloatVectorProperty(
name="Rotation",
subtype='EULER',
)
diff --git a/release/scripts/templates_py/operator_modal.py b/release/scripts/templates_py/operator_modal.py
index 88e5ee80590..c242e3b67b9 100644
--- a/release/scripts/templates_py/operator_modal.py
+++ b/release/scripts/templates_py/operator_modal.py
@@ -7,8 +7,8 @@ class ModalOperator(bpy.types.Operator):
bl_idname = "object.modal_operator"
bl_label = "Simple Modal Operator"
- first_mouse_x = IntProperty()
- first_value = FloatProperty()
+ first_mouse_x: IntProperty()
+ first_value: FloatProperty()
def modal(self, context, event):
if event.type == 'MOUSEMOVE':
diff --git a/release/scripts/templates_py/operator_modal_view3d.py b/release/scripts/templates_py/operator_modal_view3d.py
index 65bab3489b4..9d371446829 100644
--- a/release/scripts/templates_py/operator_modal_view3d.py
+++ b/release/scripts/templates_py/operator_modal_view3d.py
@@ -8,7 +8,7 @@ class ViewOperator(bpy.types.Operator):
bl_idname = "view3d.modal_operator"
bl_label = "Simple View Operator"
- offset = FloatVectorProperty(
+ offset: FloatVectorProperty(
name="Offset",
size=3,
)
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
index c4d661b4c1f..e3b63813fc4 100644
--- a/release/scripts/templates_py/operator_modal_view3d_raycast.py
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -67,7 +67,7 @@ def main(context, event):
# now we have the object under the mouse cursor,
# we could do lots of stuff but for the example just select.
if best_obj is not None:
- best_obj.select = True
+ best_obj.select_set(action='SELECT')
context.scene.objects.active = best_obj
diff --git a/release/scripts/templates_py/ui_list.py b/release/scripts/templates_py/ui_list.py
index 92e1b29d2ae..f6b82356a78 100644
--- a/release/scripts/templates_py/ui_list.py
+++ b/release/scripts/templates_py/ui_list.py
@@ -7,8 +7,10 @@ class MESH_UL_mylist(bpy.types.UIList):
# E.g. VGROUP_EMPTY = 1 << 0
# Custom properties, saved with .blend file. E.g.
- # use_filter_empty = bpy.props.BoolProperty(name="Filter Empty", default=False, options=set(),
- # description="Whether to filter empty vertex groups")
+ # use_filter_empty: bpy.props.BoolProperty(
+ # name="Filter Empty", default=False, options=set(),
+ # description="Whether to filter empty vertex groups",
+ # )
# Called for each drawn item.
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
diff --git a/release/scripts/templates_py/ui_list_simple.py b/release/scripts/templates_py/ui_list_simple.py
index e911a0dd236..79c14c17c7e 100644
--- a/release/scripts/templates_py/ui_list_simple.py
+++ b/release/scripts/templates_py/ui_list_simple.py
@@ -28,18 +28,6 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList):
layout.prop(ma, "name", text="", emboss=False, icon_value=icon)
else:
layout.label(text="", translate=False, icon_value=icon)
- # And now we can add other UI stuff...
- # Here, we add nodes info if this material uses (old!) shading nodes.
- if ma and not context.scene.render.use_shading_nodes:
- manode = ma.active_node_material
- if manode:
- # The static method UILayout.icon returns the integer value of the icon ID "computed" for the given
- # RNA object.
- layout.label(text="Node %s" % manode.name, translate=False, icon_value=layout.icon(manode))
- elif ma.use_nodes:
- layout.label(text="Node <none>", translate=False)
- else:
- layout.label(text="")
# 'GRID' layout type should be as compact as possible (typically a single icon!).
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'