Merge commit 'f4128711758e92a755001e51a88d3d4f67100974' into filebrowser_redesign

This commit is contained in:
Julian Eisel 2019-09-02 15:57:33 +02:00
commit 8f976022ff
29 changed files with 2733 additions and 1870 deletions

View File

@ -21,7 +21,7 @@
bl_info = {
"name": "Import Images as Planes",
"author": "Florian Meyer (tstscr), mont29, matali, Ted Schundler (SpkyElctrc)",
"version": (3, 3, 0),
"version": (3, 3, 1),
"blender": (2, 80, 0),
"location": "File > Import > Images as Planes or Add > Mesh > Images as Planes",
"description": "Imports images and creates planes with the appropriate aspect ratio. "
@ -1021,7 +1021,16 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper):
node_tree.links.new(core_shader.inputs[0], tex_image.outputs[0])
if self.use_transparency:
node_tree.links.new(core_shader.inputs[18], tex_image.outputs[1])
if self.shader == 'PRINCIPLED':
node_tree.links.new(core_shader.inputs[18], tex_image.outputs[1])
else:
bsdf_transparent = node_tree.nodes.new('ShaderNodeBsdfTransparent')
mix_shader = node_tree.nodes.new('ShaderNodeMixShader')
node_tree.links.new(mix_shader.inputs[0], tex_image.outputs[1])
node_tree.links.new(mix_shader.inputs[1], bsdf_transparent.outputs[0])
node_tree.links.new(mix_shader.inputs[2], core_shader.outputs[0])
core_shader = mix_shader
node_tree.links.new(out_node.inputs[0], core_shader.outputs[0])

View File

@ -21,7 +21,7 @@
bl_info = {
"name": "FBX format",
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier",
"version": (4, 15, 0),
"version": (4, 15, 1),
"blender": (2, 80, 0),
"location": "File > Import-Export",
"description": "FBX IO meshes, UV's, vertex colors, materials, textures, cameras, lamps and actions",

View File

@ -649,7 +649,9 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset):
bl_obj = item.bl_obj
transform_data = item.fbx_transform_data
rot_prev = bl_obj.rotation_euler.copy()
rot_eul_prev = bl_obj.rotation_euler.copy()
rot_quat_prev = bl_obj.rotation_quaternion.copy()
# Pre-compute inverted local rest matrix of the bone, if relevant.
restmat_inv = item.get_bind_matrix().inverted_safe() if item.is_bone else None
@ -683,13 +685,15 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset):
# Now we have a virtual matrix of transform from AnimCurves, we can insert keyframes!
loc, rot, sca = mat.decompose()
if rot_mode == 'QUATERNION':
pass # nothing to do!
if rot_quat_prev.dot(rot) < 0.0:
rot = -rot
rot_quat_prev = rot
elif rot_mode == 'AXIS_ANGLE':
vec, ang = rot.to_axis_angle()
rot = ang, vec.x, vec.y, vec.z
else: # Euler
rot = rot.to_euler(rot_mode, rot_prev)
rot_prev = rot
rot = rot.to_euler(rot_mode, rot_eul_prev)
rot_eul_prev = rot
for fc, value in zip(blen_curves, chain(loc, rot, sca)):
fc.keyframe_points.insert(frame, value, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR'

View File

@ -15,7 +15,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
"version": (0, 9, 53),
"version": (0, 9, 54),
'blender': (2, 80, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',

View File

@ -187,10 +187,11 @@ def __get_channel_groups(blender_action: bpy.types.Action, blender_object: bpy.t
else:
try:
target = gltf2_blender_get.get_object_from_datapath(blender_object, object_path)
if blender_object.type == "MESH":
if blender_object.type == "MESH" and object_path.startswith("key_blocks"):
shape_key = blender_object.data.shape_keys.path_resolve(object_path)
if shape_key.mute is True:
continue
target = blender_object.data.shape_keys
except ValueError as e:
# if the object is a mesh and the action target path can not be resolved, we know that this is a morph
# animation.

View File

@ -529,7 +529,7 @@ class RenderPovSettingsScene(PropertyGroup):
name="Nearest Count",
description="Number of old ambient values blended together to "
"create a new interpolated value",
min=1, max=20, default=5)
min=1, max=20, default=1)
radio_normal: BoolProperty(
name="Normals", description="Radiosity estimation can be affected by normals",
@ -990,6 +990,11 @@ class RenderPovSettingsMaterial(PropertyGroup):
name="Alpha",
description="Alpha transparency of the material",
min=0.0, max=1.0, soft_min=0.0, soft_max=1.0, default=1.0, precision=3)
specular_alpha: FloatProperty(
name="Specular alpha",
description="Alpha transparency for specular areas",
min=0.0, max=1.0, soft_min=0.0, soft_max=1.0, default=1.0, precision=3)
ambient: FloatProperty(
name="Ambient",
@ -1409,8 +1414,8 @@ class RenderPovSettingsMaterial(PropertyGroup):
refraction_type: EnumProperty(
items=[
("1", "Fake Caustics", "use fake caustics"),
("2", "Photons Caustics", "use photons for refractive caustics")],
("1", "Z Transparency Fake Caustics", "use fake caustics"),
("2", "Raytrace Photons Caustics", "use photons for refractive caustics")],
name="Refraction Type:",
description="use fake caustics (fast) or true photons for refractive Caustics",
default="1")
@ -1709,15 +1714,66 @@ class MaterialSubsurfaceScattering(PropertyGroup):
name="Texture",
description="Texture scattering blend factor",
min=0.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.0, precision=3)
class MaterialStrandSettings(PropertyGroup):
bl_description = "Strand settings for the material",
blend_distance: FloatProperty(
name="Distance",
description="Worldspace distance over which to blend in the surface normal",
min=0.0, max=10.0, soft_min=0.0, soft_max=10.0, default=0.0, precision=3)
root_size: FloatProperty(
name="Root",
description="Start size of strands in pixels or Blender units",
min=0.25, default=1.0, precision=5)
shape: FloatProperty(
name="Shape",
description="Positive values make strands rounder, negative ones make strands spiky",
min=-0.9, max=0.9, default=0.0, precision=3)
size_min: FloatProperty(
name="Minimum",
description="Minimum size of strands in pixels",
min=0.001, max=10.0, default=1.0, precision=3)
tip_size: FloatProperty(
name="Tip",
description="End size of strands in pixels or Blender units",
min=0.0, default=1.0, precision=5)
use_blender_units: BoolProperty(
name="Blender Units",
description="Use Blender units for widths instead of pixels",
default=False)
use_surface_diffuse: BoolProperty(
name="Surface diffuse",
description="Make diffuse shading more similar to shading the surface",
default=False)
use_tangent_shading: BoolProperty(
name="Tangent Shading",
description="Use direction of strands as normal for tangent-shading",
default=True)
uv_layer: StringProperty(
name="UV Layer",
#icon="GROUP_UVS",
description="Name of UV map to override",
default="")
width_fade: FloatProperty(
name="Width Fade",
description="Transparency along the width of the strand",
min=0.0, max=2.0, default=0.0, precision=3)
# halo
# Halo settings for the material
# Type: MaterialHalo, (readonly, never None)
# alpha¶
# Alpha transparency of the material
# Type: float in [0, 1], default 0.0
# ambient
@ -1912,10 +1968,6 @@ class MaterialSubsurfaceScattering(PropertyGroup):
# Shadow raytracing bias to prevent terminator problems on shadow boundary
# Type: float in [0, 0.25], default 0.0
# specular_alpha
# Alpha transparency for specular areas
# Type: float in [0, 1], default 0.0
# specular_color
@ -4298,6 +4350,7 @@ classes = (
MaterialRaytraceTransparency,
MaterialRaytraceMirror,
MaterialSubsurfaceScattering,
MaterialStrandSettings,
RenderPovSettingsObject,
RenderPovSettingsScene,
RenderPovSettingsText,
@ -4337,6 +4390,7 @@ def register():
bpy.types.Material.pov_raytrace_transparency = PointerProperty(type=MaterialRaytraceTransparency)
bpy.types.Material.pov = PointerProperty(type=RenderPovSettingsMaterial)
bpy.types.Material.pov_subsurface_scattering = PointerProperty(type=MaterialSubsurfaceScattering)
bpy.types.Material.strand = PointerProperty(type= MaterialStrandSettings)
bpy.types.Material.pov_raytrace_mirror = PointerProperty(type=MaterialRaytraceMirror)
bpy.types.Texture.pov = PointerProperty(type=RenderPovSettingsTexture)
bpy.types.Object.pov = PointerProperty(type=RenderPovSettingsObject)
@ -4353,6 +4407,7 @@ def unregister():
del bpy.types.Scene.pov
del bpy.types.Material.pov
del bpy.types.Material.pov_subsurface_scattering
del bpy.types.Material.strand
del bpy.types.Material.pov_raytrace_mirror
del bpy.types.Material.pov_raytrace_transparency
#del bpy.types.Modifier.pov

View File

@ -1697,10 +1697,10 @@ def write_pov(filename, scene=None, info_callback=None):
material = None
if material:
diffuse_color = material.diffuse_color
trans = 1.0 - material.alpha
trans = 1.0 - material.pov.alpha
if material.use_transparency and material.transparency_method == 'RAYTRACE':
povFilter = material.pov_raytrace_transparency.filter * (1.0 - material.alpha)
trans = (1.0 - material.alpha) - povFilter
trans = (1.0 - material.pov.alpha) - povFilter
else:
povFilter = 0.0
material_finish = materialNames[material.name]
@ -1762,10 +1762,10 @@ def write_pov(filename, scene=None, info_callback=None):
if material:
diffuse_color = material.diffuse_color
trans = 1.0 - material.alpha
trans = 1.0 - material.pov.alpha
if material.use_transparency and material.transparency_method == 'RAYTRACE':
povFilter = material.pov_raytrace_transparency.filter * (1.0 - material.alpha)
trans = (1.0 - material.alpha) - povFilter
trans = (1.0 - material.pov.alpha) - povFilter
else:
povFilter = 0.0
@ -2085,9 +2085,9 @@ def write_pov(filename, scene=None, info_callback=None):
renderEmitter = True
if hasattr(ob, 'particle_systems'):
renderEmitter = False
if ob.show_instancer_for_render:
renderEmitter = True
for pSys in ob.particle_systems:
if pSys.settings.use_render_emitter:
renderEmitter = True
for mod in [m for m in ob.modifiers if (m is not None) and (m.type == 'PARTICLE_SYSTEM')]:
if (pSys.settings.render_type == 'PATH') and mod.show_render and (pSys.name == mod.particle_system.name):
tstart = time.time()
@ -2113,11 +2113,16 @@ def write_pov(filename, scene=None, info_callback=None):
strandEnd = 0.01
strandShape = 0.0
# Set the number of particles to render count rather than 3d view display
pSys.set_resolution(scene, ob, 'RENDER')
#pSys.set_resolution(scene, ob, 'RENDER') # DEPRECATED
# When you render, the entire dependency graph will be
# evaluated at render resolution, including the particles.
# In the viewport it will be at viewport resolution.
# So there is no need fo render engines to use this function anymore,
# it's automatic now.
steps = pSys.settings.display_step
steps = 3 ** steps # or (power of 2 rather than 3) + 1 # Formerly : len(particle.hair_keys)
totalNumberOfHairs = ( len(pSys.particles) + len(pSys.child_particles) )
totalNumberOfHairs = ( pSys.settings.count + pSys.settings.rendered_child_count )
#hairCounter = 0
file.write('#declare HairArray = array[%i] {\n' % totalNumberOfHairs)
for pindex in range(0, totalNumberOfHairs):
@ -2135,7 +2140,7 @@ def write_pov(filename, scene=None, info_callback=None):
file.write('linear_spline ')
file.write('%i,\n' % (steps))
#changing world coordinates to object local coordinates by multiplying with inverted matrix
initCo = ob.matrix_world.inverted()*(pSys.co_hair(ob, pindex, 0))
initCo = ob.matrix_world.inverted() @ (pSys.co_hair(ob, particle_no = pindex, step = 0))
if ob.material_slots[pSys.settings.material - 1].material and ob.active_material is not None:
pmaterial = ob.material_slots[pSys.settings.material-1].material
for th in pmaterial.texture_slots:
@ -2159,7 +2164,7 @@ def write_pov(filename, scene=None, info_callback=None):
#only overwrite variable for each competing texture for now
initColor=th.texture.evaluate((initCo[0],initCo[1],initCo[2]))
for step in range(0, steps):
co = ob.matrix_world.inverted()*(pSys.co_hair(ob, pindex, step))
co = ob.matrix_world.inverted() @ (pSys.co_hair(ob, particle_no = pindex, step = step))
#for controlPoint in particle.hair_keys:
if pSys.settings.clump_factor != 0:
hDiameter = pSys.settings.clump_factor / 200.0 * random.uniform(0.5, 1)
@ -2256,8 +2261,12 @@ def write_pov(filename, scene=None, info_callback=None):
print('Number of tufts (particle systems)', len(ob.particle_systems))
# Set back the displayed number of particles to preview count
pSys.set_resolution(scene, ob, 'PREVIEW')
# pSys.set_resolution(scene, ob, 'PREVIEW') #DEPRECATED
# When you render, the entire dependency graph will be
# evaluated at render resolution, including the particles.
# In the viewport it will be at viewport resolution.
# So there is no need fo render engines to use this function anymore,
# it's automatic now.
if renderEmitter == False:
continue #don't render mesh, skip to next object.

View File

@ -745,7 +745,7 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
string_strip_hyphen, safety, col, os, preview_dir, unpacked_images):
material_finish = materialNames[mater.name]
if mater.pov.use_transparency:
trans = 1.0 - mater.alpha
trans = 1.0 - mater.pov.alpha
else:
trans = 0.0
if ((mater.specular_color.s == 0.0) or (mater.pov.diffuse_shader == 'MINNAERT')):
@ -754,9 +754,9 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
else:
colored_specular_found = True
if mater.pov.use_transparency and mater.transparency_method == 'RAYTRACE':
povFilter = mater.raytrace_transparency.filter * (1.0 - mater.alpha)
trans = (1.0 - mater.alpha) - povFilter
if mater.pov.use_transparency and mater.pov.transparency_method == 'RAYTRACE':
povFilter = mater.pov_raytrace_transparency.filter * (1.0 - mater.pov.alpha)
trans = (1.0 - mater.pov.alpha) - povFilter
else:
povFilter = 0.0

View File

@ -265,6 +265,11 @@ def check_material(mat):
return True
return False
def simple_material(mat):
if (mat is not None) and (not mat.use_nodes):
return True
return False
def check_add_mesh_extra_objects():
if "add_mesh_extra_objects" in bpy.context.preferences.addons.keys():
return True
@ -1385,7 +1390,7 @@ class MATERIAL_PT_POV_sss(MaterialButtonsPanel, Panel):
sub.prop(sss, "back")
col.separator()
col.prop(sss, "error_threshold", text="Error")
class MATERIAL_PT_povray_activate_node(MaterialButtonsPanel, Panel):
bl_label = "Activate Node Settings"
bl_context = "material"
@ -1517,6 +1522,70 @@ class MATERIAL_PT_POV_mirror(MaterialButtonsPanel, Panel):
sub.prop(raym, "gloss_threshold", text="Threshold")
sub.prop(raym, "gloss_samples", text="Samples")
sub.prop(raym, "gloss_anisotropic", text="Anisotropic")
class MATERIAL_PT_POV_transp(MaterialButtonsPanel, Panel):
bl_label = "Transparency"
COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
mat = context.material
engine = context.scene.render.engine
return check_material(mat) and (mat.pov.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.pov, "use_transparency", text="")
def draw(self, context):
layout = self.layout
base_mat = context.material
mat = context.material#FORMERLY active_node_mat(context.material)
rayt = mat.pov_raytrace_transparency
if simple_material(base_mat):
row = layout.row()
row.active = mat.pov.use_transparency
row.prop(mat.pov, "transparency_method", expand=True)
split = layout.split()
split.active = base_mat.pov.use_transparency
col = split.column()
col.prop(mat.pov, "alpha")
row = col.row()
row.active = (base_mat.pov.transparency_method != 'MASK') and (not mat.pov.use_shadeless)
row.prop(mat.pov, "specular_alpha", text="Specular")
col = split.column()
col.active = (not mat.pov.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.pov.transparency_method == 'RAYTRACE':
layout.separator()
split = layout.split()
split.active = base_mat.pov.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_povray_reflection(MaterialButtonsPanel, Panel):
bl_label = "POV-Ray Reflection"
@ -1646,7 +1715,52 @@ class MATERIAL_PT_povray_caustics(MaterialButtonsPanel, Panel):
col.label(text="Caustics override is on, ")
col.label(text="but you didn't chose any !")
class MATERIAL_PT_strand(MaterialButtonsPanel, Panel):
bl_label = "Strand"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'POVRAY_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.pov.use_shadeless)
sub.prop(tan, "use_tangent_shading")
col.prop(tan, "shape")
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="")
else:
col.prop(tan, "uv_layer", text="")
col.separator()
sub = col.column()
sub.active = (not mat.pov.use_shadeless)
sub.label("Surface diffuse:")
sub = col.column()
sub.prop(tan, "blend_distance", text="Distance")
class MATERIAL_PT_povray_replacement_text(MaterialButtonsPanel, Panel):
bl_label = "Custom POV Code"
COMPAT_ENGINES = {'POVRAY_RENDER'}
@ -3085,9 +3199,11 @@ classes = (
MATERIAL_PT_POV_sss,
MATERIAL_MT_POV_sss_presets,
AddPresetSSS,
MATERIAL_PT_strand,
MATERIAL_PT_povray_activate_node,
MATERIAL_PT_povray_active_node,
MATERIAL_PT_POV_mirror,
MATERIAL_PT_POV_transp,
MATERIAL_PT_povray_reflection,
#MATERIAL_PT_POV_interior,
MATERIAL_PT_povray_fade_color,

View File

@ -0,0 +1,135 @@
# ##### 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 #####
# Modified by Meta-Androcto
""" Copyright 2011 GPL licence applies"""
bl_info = {
"name": "Dynamic Brush Menus",
"description": "Fast access to brushes & tools in Sculpt and Paint Modes",
"author": "Ryan Inch (Imaginer)",
"version": (1, 1, 7),
"blender": (2, 80, 0),
"location": "Spacebar in Sculpt/Paint Modes",
"warning": '',
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/3D_interaction/Advanced_UI_Menus",
"category": "3D View"}
if "bpy" in locals():
import importlib
importlib.reload(utils_core)
importlib.reload(brush_menu)
importlib.reload(brushes)
importlib.reload(curve_menu)
importlib.reload(dyntopo_menu)
importlib.reload(stroke_menu)
importlib.reload(symmetry_menu)
importlib.reload(texture_menu)
else:
from . import utils_core
from . import brush_menu
from . import brushes
from . import curve_menu
from . import dyntopo_menu
from . import stroke_menu
from . import symmetry_menu
from . import texture_menu
import bpy
from bpy.types import AddonPreferences
from bpy.props import (
EnumProperty,
IntProperty,
)
addon_files = (
brush_menu,
brushes,
curve_menu,
dyntopo_menu,
stroke_menu,
symmetry_menu,
texture_menu,
)
class VIEW3D_MT_Brushes_Pref(AddonPreferences):
bl_idname = __name__
column_set: IntProperty(
name="Number of Columns",
description="Number of columns used for the brushes menu",
default=2,
min=1,
max=10
)
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.prop(self, "column_set", slider=True)
# New hotkeys and registration
addon_keymaps = []
def register():
# register all files
for addon_file in addon_files:
addon_file.register()
# set the add-on name variable to access the preferences
utils_core.get_addon_name = __name__
# register preferences
bpy.utils.register_class(VIEW3D_MT_Brushes_Pref)
# register hotkeys
wm = bpy.context.window_manager
modes = ('Sculpt', 'Vertex Paint', 'Weight Paint', 'Image Paint', 'Particle')
for mode in modes:
km = wm.keyconfigs.addon.keymaps.new(name=mode)
kmi = km.keymap_items.new('wm.call_menu', 'SPACE', 'PRESS')
kmi.properties.name = "VIEW3D_MT_sv3_brush_options"
addon_keymaps.append((km, kmi))
def unregister():
# unregister all files
for addon_file in addon_files:
addon_file.unregister()
# unregister preferences
bpy.utils.unregister_class(VIEW3D_MT_Brushes_Pref)
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
if __name__ == "__main__":
register()

View File

@ -0,0 +1,630 @@
# gpl author: Ryan Inch (Imaginer)
import bpy
from bpy.types import (
Operator,
Menu,
)
from bpy.props import BoolProperty
from . import utils_core
from . import brushes
from bl_ui.properties_paint_common import UnifiedPaintPanel
class BrushOptionsMenu(Menu):
bl_label = "Brush Options"
bl_idname = "VIEW3D_MT_sv3_brush_options"
@classmethod
def poll(self, context):
return utils_core.get_mode() in (
'SCULPT', 'VERTEX_PAINT',
'WEIGHT_PAINT', 'TEXTURE_PAINT',
'PARTICLE_EDIT'
)
def draw(self, context):
mode = utils_core.get_mode()
layout = self.layout
if mode == 'SCULPT':
self.sculpt(mode, layout, context)
elif mode in ('VERTEX_PAINT', 'WEIGHT_PAINT'):
self.vw_paint(mode, layout, context)
elif mode == 'TEXTURE_PAINT':
self.texpaint(mode, layout, context)
else:
self.particle(layout, context)
def sculpt(self, mode, layout, context):
has_brush = utils_core.get_brush_link(context, types="brush")
icons = brushes.brush_icon[mode][has_brush.sculpt_tool] if \
has_brush else "BRUSH_DATA"
layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
icon=icons)
layout.row().menu(BrushRadiusMenu.bl_idname)
if has_brush:
# if the active brush is unlinked these menus don't do anything
layout.row().menu(BrushStrengthMenu.bl_idname)
layout.row().menu(BrushAutosmoothMenu.bl_idname)
layout.row().menu(BrushModeMenu.bl_idname)
layout.row().menu("VIEW3D_MT_sv3_texture_menu")
layout.row().menu("VIEW3D_MT_sv3_stroke_options")
layout.row().menu("VIEW3D_MT_sv3_brush_curve_menu")
layout.row().menu("VIEW3D_MT_sv3_dyntopo")
layout.row().menu("VIEW3D_MT_sv3_master_symmetry_menu")
def vw_paint(self, mode, layout, context):
has_brush = utils_core.get_brush_link(context, types="brush")
icons = brushes.brush_icon[mode][has_brush.vertex_tool] if \
has_brush else "BRUSH_DATA"
layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
if mode == 'VERTEX_PAINT':
layout.row().operator(ColorPickerPopup.bl_idname, icon="COLOR")
layout.row().separator()
layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
icon=icons)
if mode == 'VERTEX_PAINT':
layout.row().menu(BrushRadiusMenu.bl_idname)
if has_brush:
# if the active brush is unlinked these menus don't do anything
layout.row().menu(BrushStrengthMenu.bl_idname)
layout.row().menu(BrushModeMenu.bl_idname)
layout.row().menu("VIEW3D_MT_sv3_texture_menu")
layout.row().menu("VIEW3D_MT_sv3_stroke_options")
layout.row().menu("VIEW3D_MT_sv3_brush_curve_menu")
if mode == 'WEIGHT_PAINT':
layout.row().menu(BrushWeightMenu.bl_idname)
layout.row().menu(BrushRadiusMenu.bl_idname)
if has_brush:
# if the active brush is unlinked these menus don't do anything
layout.row().menu(BrushStrengthMenu.bl_idname)
layout.row().menu(BrushModeMenu.bl_idname)
layout.row().menu("VIEW3D_MT_sv3_stroke_options")
layout.row().menu("VIEW3D_MT_sv3_brush_curve_menu")
def texpaint(self, mode, layout, context):
toolsettings = context.tool_settings.image_paint
has_brush = utils_core.get_brush_link(context, types="brush")
icons = brushes.brush_icon[mode][has_brush.image_tool] if \
has_brush else "BRUSH_DATA"
if context.image_paint_object and not toolsettings.detect_data():
if toolsettings.missing_uvs or toolsettings.missing_materials or \
toolsettings.missing_texture:
layout.row().label(text="Missing Data", icon='ERROR')
layout.row().operator_menu_enum("paint.add_texture_paint_slot", \
"type", \
icon='ADD', \
text="Add Texture Paint Slot")
return
elif toolsettings.missing_stencil:
layout.row().label(text="Missing Data", icon='ERROR')
layout.row().label(text="See Mask Properties", icon='FORWARD')
layout.row().separator()
layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
icon=icons)
return
else:
layout.row().label(text="Missing Data", icon="INFO")
else:
layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
if has_brush and has_brush.image_tool in {'DRAW', 'FILL'} and \
has_brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'}:
layout.row().operator(ColorPickerPopup.bl_idname, icon="COLOR")
layout.row().separator()
layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
icon=icons)
if has_brush:
# if the active brush is unlinked these menus don't do anything
if has_brush and has_brush.image_tool in {'MASK'}:
layout.row().menu(BrushWeightMenu.bl_idname, text="Mask Value")
if has_brush and has_brush.image_tool not in {'FILL'}:
layout.row().menu(BrushRadiusMenu.bl_idname)
layout.row().menu(BrushStrengthMenu.bl_idname)
if has_brush and has_brush.image_tool in {'DRAW'}:
layout.row().menu(BrushModeMenu.bl_idname)
layout.row().menu("VIEW3D_MT_sv3_texture_menu")
layout.row().menu("VIEW3D_MT_sv3_stroke_options")
layout.row().menu("VIEW3D_MT_sv3_brush_curve_menu")
layout.row().menu("VIEW3D_MT_sv3_master_symmetry_menu")
def particle(self, layout, context):
particle_edit = context.tool_settings.particle_edit
layout.operator("wm.toolbar", text="Tools", icon='TOOL_SETTINGS')
layout.row().menu("VIEW3D_MT_sv3_brushes_menu",
icon="BRUSH_DATA")
layout.row().menu(BrushRadiusMenu.bl_idname)
if particle_edit.tool != 'ADD':
layout.row().menu(BrushStrengthMenu.bl_idname)
else:
layout.row().menu(ParticleCountMenu.bl_idname)
layout.row().separator()
layout.row().prop(particle_edit, "use_default_interpolate", toggle=True)
layout.row().prop(particle_edit.brush, "steps", slider=True)
layout.row().prop(particle_edit, "default_key_count", slider=True)
if particle_edit.tool == 'LENGTH':
layout.row().separator()
layout.row().menu(ParticleLengthMenu.bl_idname)
if particle_edit.tool == 'PUFF':
layout.row().separator()
layout.row().menu(ParticlePuffMenu.bl_idname)
layout.row().prop(particle_edit.brush, "use_puff_volume", toggle=True)
class BrushRadiusMenu(Menu):
bl_label = "Radius"
bl_idname = "VIEW3D_MT_sv3_brush_radius_menu"
bl_description = "Change the size of the brushes"
def init(self):
if utils_core.get_mode() == 'PARTICLE_EDIT':
settings = (("100", 100),
("70", 70),
("50", 50),
("30", 30),
("20", 20),
("10", 10))
datapath = "tool_settings.particle_edit.brush.size"
proppath = bpy.context.tool_settings.particle_edit.brush
else:
settings = (("200", 200),
("150", 150),
("100", 100),
("50", 50),
("35", 35),
("10", 10))
datapath = "tool_settings.unified_paint_settings.size"
proppath = bpy.context.tool_settings.unified_paint_settings
return settings, datapath, proppath
def draw(self, context):
settings, datapath, proppath = self.init()
layout = self.layout
# add the top slider
layout.row().prop(proppath, "size", slider=True)
layout.row().separator()
# add the rest of the menu items
for i in range(len(settings)):
utils_core.menuprop(
layout.row(), settings[i][0], settings[i][1],
datapath, icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON'
)
class BrushStrengthMenu(Menu):
bl_label = "Strength"
bl_idname = "VIEW3D_MT_sv3_brush_strength_menu"
def init(self):
mode = utils_core.get_mode()
settings = (("1.0", 1.0),
("0.7", 0.7),
("0.5", 0.5),
("0.3", 0.3),
("0.2", 0.2),
("0.1", 0.1))
proppath = utils_core.get_brush_link(bpy.context, types="brush")
if mode == 'SCULPT':
datapath = "tool_settings.sculpt.brush.strength"
elif mode == 'VERTEX_PAINT':
datapath = "tool_settings.vertex_paint.brush.strength"
elif mode == 'WEIGHT_PAINT':
datapath = "tool_settings.weight_paint.brush.strength"
elif mode == 'TEXTURE_PAINT':
datapath = "tool_settings.image_paint.brush.strength"
else:
datapath = "tool_settings.particle_edit.brush.strength"
proppath = bpy.context.tool_settings.particle_edit.brush
return settings, datapath, proppath
def draw(self, context):
settings, datapath, proppath = self.init()
layout = self.layout
# add the top slider
if proppath:
layout.row().prop(proppath, "strength", slider=True)
layout.row().separator()
# add the rest of the menu items
for i in range(len(settings)):
utils_core.menuprop(
layout.row(), settings[i][0], settings[i][1],
datapath, icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON'
)
else:
layout.row().label(text="No brushes available", icon="INFO")
class BrushModeMenu(Menu):
bl_label = "Brush Mode"
bl_idname = "VIEW3D_MT_sv3_brush_mode_menu"
def init(self):
mode = utils_core.get_mode()
has_brush = utils_core.get_brush_link(bpy.context, types="brush")
if mode == 'SCULPT':
enum = has_brush.bl_rna.properties['sculpt_plane'].enum_items if \
has_brush else None
path = "tool_settings.sculpt.brush.sculpt_plane"
elif mode == 'VERTEX_PAINT':
enum = has_brush.bl_rna.properties['blend'].enum_items if \
has_brush else None
path = "tool_settings.vertex_paint.brush.blend"
elif mode == 'WEIGHT_PAINT':
enum = has_brush.bl_rna.properties['blend'].enum_items if \
has_brush else None
path = "tool_settings.weight_paint.brush.blend"
elif mode == 'TEXTURE_PAINT':
enum = has_brush.bl_rna.properties['blend'].enum_items if \
has_brush else None
path = "tool_settings.image_paint.brush.blend"
else:
enum = None
path = ""
return enum, path
def draw(self, context):
enum, path = self.init()
layout = self.layout
colum_n = utils_core.addon_settings()
layout.row().label(text="Brush Mode")
layout.row().separator()
if enum:
if utils_core.get_mode() != 'SCULPT':
column_flow = layout.column_flow(columns=colum_n)
# add all the brush modes to the menu
for brush in enum:
utils_core.menuprop(
column_flow.row(), brush.name,
brush.identifier, path, icon='RADIOBUT_OFF',
disable=True, disable_icon='RADIOBUT_ON'
)
else:
# add all the brush modes to the menu
for brush in enum:
utils_core.menuprop(
layout.row(), brush.name,
brush.identifier, path, icon='RADIOBUT_OFF',
disable=True, disable_icon='RADIOBUT_ON'
)
else:
layout.row().label(text="No brushes available", icon="INFO")
class BrushAutosmoothMenu(Menu):
bl_label = "Autosmooth"
bl_idname = "VIEW3D_MT_sv3_brush_autosmooth_menu"
def init(self):
settings = (("1.0", 1.0),
("0.7", 0.7),
("0.5", 0.5),
("0.3", 0.3),
("0.2", 0.2),
("0.1", 0.1))
return settings
def draw(self, context):
settings = self.init()
layout = self.layout
has_brush = utils_core.get_brush_link(context, types="brush")
if has_brush:
# add the top slider
layout.row().prop(has_brush, "auto_smooth_factor", slider=True)
layout.row().separator()
# add the rest of the menu items
for i in range(len(settings)):
utils_core.menuprop(
layout.row(), settings[i][0], settings[i][1],
"tool_settings.sculpt.brush.auto_smooth_factor",
icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON'
)
else:
layout.row().label(text="No Smooth options available", icon="INFO")
class BrushWeightMenu(Menu):
bl_label = "Weight"
bl_idname = "VIEW3D_MT_sv3_brush_weight_menu"
def init(self):
settings = (("1.0", 1.0),
("0.7", 0.7),
("0.5", 0.5),
("0.3", 0.3),
("0.2", 0.2),
("0.1", 0.1))
if utils_core.get_mode() == 'WEIGHT_PAINT':
brush = bpy.context.tool_settings.unified_paint_settings
brushstr = "tool_settings.unified_paint_settings.weight"
name = "Weight"
else:
brush = bpy.context.tool_settings.image_paint.brush
brushstr = "tool_settings.image_paint.brush.weight"
name = "Mask Value"
return settings, brush, brushstr, name
def draw(self, context):
settings, brush, brushstr, name = self.init()
layout = self.layout
if brush:
# add the top slider
layout.row().prop(brush, "weight", text=name, slider=True)
layout.row().separator()
# add the rest of the menu items
for i in range(len(settings)):
utils_core.menuprop(
layout.row(), settings[i][0], settings[i][1],
brushstr,
icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON'
)
else:
layout.row().label(text="No brush available", icon="INFO")
class ParticleCountMenu(Menu):
bl_label = "Count"
bl_idname = "VIEW3D_MT_sv3_particle_count_menu"
def init(self):
settings = (("50", 50),
("25", 25),
("10", 10),
("5", 5),
("3", 3),
("1", 1))
return settings
def draw(self, context):
settings = self.init()
layout = self.layout
# add the top slider
layout.row().prop(context.tool_settings.particle_edit.brush,
"count", slider=True)
layout.row().separator()
# add the rest of the menu items
for i in range(len(settings)):
utils_core.menuprop(
layout.row(), settings[i][0], settings[i][1],
"tool_settings.particle_edit.brush.count",
icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON'
)
class ParticleLengthMenu(Menu):
bl_label = "Length Mode"
bl_idname = "VIEW3D_MT_sv3_particle_length_menu"
def draw(self, context):
layout = self.layout
path = "tool_settings.particle_edit.brush.length_mode"
# add the menu items
for item in context.tool_settings.particle_edit.brush. \
bl_rna.properties['length_mode'].enum_items:
utils_core.menuprop(
layout.row(), item.name, item.identifier, path,
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON'
)
class ParticlePuffMenu(Menu):
bl_label = "Puff Mode"
bl_idname = "VIEW3D_MT_sv3_particle_puff_menu"
def draw(self, context):
layout = self.layout
path = "tool_settings.particle_edit.brush.puff_mode"
# add the menu items
for item in context.tool_settings.particle_edit.brush. \
bl_rna.properties['puff_mode'].enum_items:
utils_core.menuprop(
layout.row(), item.name, item.identifier, path,
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON'
)
class FlipColorsAll(Operator):
"""Switch between Foreground and Background colors"""
bl_label = "Flip Colors"
bl_idname = "view3d.sv3_flip_colors_all"
bl_description = "Switch between Foreground and Background colors"
is_tex: BoolProperty(
default=False,
options={'HIDDEN'}
)
def execute(self, context):
try:
if self.is_tex is False:
color = context.tool_settings.vertex_paint.brush.color
secondary_color = context.tool_settings.vertex_paint.brush.secondary_color
orig_prim = color.hsv
orig_sec = secondary_color.hsv
color.hsv = orig_sec
secondary_color.hsv = orig_prim
else:
color = context.tool_settings.image_paint.brush.color
secondary_color = context.tool_settings.image_paint.brush.secondary_color
orig_prim = color.hsv
orig_sec = secondary_color.hsv
color.hsv = orig_sec
secondary_color.hsv = orig_prim
return {'FINISHED'}
except Exception as e:
utils_core.error_handlers(self, "view3d.sv3_flip_colors_all", e,
"Flip Colors could not be completed")
return {'CANCELLED'}
class ColorPickerPopup(Operator):
"""Open Color Picker"""
bl_label = "Color"
bl_idname = "view3d.sv3_color_picker_popup"
bl_description = "Open Color Picker"
bl_options = {'REGISTER'}
@classmethod
def poll(self, context):
return utils_core.get_mode() in (
'VERTEX_PAINT',
'TEXTURE_PAINT'
)
def check(self, context):
return True
def init(self):
if utils_core.get_mode() == 'TEXTURE_PAINT':
settings = bpy.context.tool_settings.image_paint
brush = getattr(settings, "brush", None)
else:
settings = bpy.context.tool_settings.vertex_paint
brush = settings.brush
brush = getattr(settings, "brush", None)
return settings, brush
def draw(self, context):
layout = self.layout
settings, brush = self.init()
if brush:
layout.row().template_color_picker(brush, "color", value_slider=True)
prim_sec_row = layout.row(align=True)
prim_sec_row.prop(brush, "color", text="")
prim_sec_row.prop(brush, "secondary_color", text="")
if utils_core.get_mode() == 'VERTEX_PAINT':
prim_sec_row.operator(
FlipColorsAll.bl_idname,
icon='FILE_REFRESH', text=""
).is_tex = False
else:
prim_sec_row.operator(
FlipColorsAll.bl_idname,
icon='FILE_REFRESH', text=""
).is_tex = True
if settings.palette:
layout.column().template_palette(settings, "palette", color=True)
layout.row().template_ID(settings, "palette", new="palette.new")
else:
layout.row().label(text="No brushes currently available", icon="INFO")
return
def execute(self, context):
return context.window_manager.invoke_popup(self, width=180)
classes = (
BrushOptionsMenu,
BrushRadiusMenu,
BrushStrengthMenu,
BrushModeMenu,
BrushAutosmoothMenu,
BrushWeightMenu,
ParticleCountMenu,
ParticleLengthMenu,
ParticlePuffMenu,
FlipColorsAll,
ColorPickerPopup
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)

View File

@ -0,0 +1,163 @@
# gpl author: Ryan Inch (Imaginer)
import bpy
from bpy.types import Menu
from . import utils_core
from bl_ui.properties_paint_common import UnifiedPaintPanel
# Particle Tools
particle_tools = (
("Comb", 'COMB'),
("Smooth", 'SMOOTH'),
("Add", 'ADD'),
("Length", 'LENGTH'),
("Puff", 'PUFF'),
("Cut", 'CUT'),
("Weight", 'WEIGHT')
)
# Brush Datapaths
brush_datapath = {
'SCULPT': "tool_settings.sculpt.brush",
'VERTEX_PAINT': "tool_settings.vertex_paint.brush",
'WEIGHT_PAINT': "tool_settings.weight_paint.brush",
'TEXTURE_PAINT': "tool_settings.image_paint.brush",
'PARTICLE_EDIT': "tool_settings.particle_edit.tool"
}
# Brush Icons
brush_icon = {
'SCULPT': {
"BLOB": 'BRUSH_BLOB',
"CLAY": 'BRUSH_CLAY',
"CLAY_STRIPS": 'BRUSH_CLAY_STRIPS',
"CREASE": 'BRUSH_CREASE',
"DRAW": 'BRUSH_SCULPT_DRAW',
"FILL": 'BRUSH_FILL',
"FLATTEN": 'BRUSH_FLATTEN',
"GRAB": 'BRUSH_GRAB',
"INFLATE": 'BRUSH_INFLATE',
"LAYER": 'BRUSH_LAYER',
"MASK": 'BRUSH_MASK',
"NUDGE": 'BRUSH_NUDGE',
"PINCH": 'BRUSH_PINCH',
"ROTATE": 'BRUSH_ROTATE',
"SCRAPE": 'BRUSH_SCRAPE',
"SIMPLIFY": 'BRUSH_DATA',
"SMOOTH": 'BRUSH_SMOOTH',
"SNAKE_HOOK": 'BRUSH_SNAKE_HOOK',
"THUMB": 'BRUSH_THUMB'
},
'VERTEX_PAINT': {
"AVERAGE": 'BRUSH_BLUR',
"BLUR": 'BRUSH_BLUR',
"DRAW": 'BRUSH_MIX',
"SMEAR": 'BRUSH_BLUR'
},
'WEIGHT_PAINT': {
"AVERAGE": 'BRUSH_BLUR',
"BLUR": 'BRUSH_BLUR',
"DRAW": 'BRUSH_MIX',
"SMEAR": 'BRUSH_BLUR'
},
'TEXTURE_PAINT': {
"CLONE": 'BRUSH_CLONE',
"DRAW": 'BRUSH_TEXDRAW',
"FILL": 'BRUSH_TEXFILL',
"MASK": 'BRUSH_TEXMASK',
"SMEAR": 'BRUSH_SMEAR',
"SOFTEN": 'BRUSH_SOFTEN'
}
}
class BrushesMenu(Menu):
bl_label = "Brush"
bl_idname = "VIEW3D_MT_sv3_brushes_menu"
def draw(self, context):
mode = utils_core.get_mode()
layout = self.layout
settings = UnifiedPaintPanel.paint_settings(context)
colum_n = utils_core.addon_settings()
layout.row().label(text="Brush")
layout.row().separator()
has_brush = utils_core.get_brush_link(context, types="brush")
current_brush = eval("bpy.context.{}".format(brush_datapath[mode])) if has_brush else None
# get the current brush's name
if current_brush and utils_core.get_mode() != 'PARTICLE_EDIT':
current_brush = current_brush.name
if mode == 'PARTICLE_EDIT':
# if you are in particle edit mode add the menu items for particle mode
for tool in particle_tools:
utils_core.menuprop(
layout.row(), tool[0], tool[1], brush_datapath[mode],
icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON'
)
else:
column_flow = layout.column_flow(columns=colum_n)
# iterate over all the brushes
for item in bpy.data.brushes:
if mode == 'SCULPT':
if item.use_paint_sculpt:
# if you are in sculpt mode and the brush
# is a sculpt brush add the brush to the menu
utils_core.menuprop(
column_flow.row(), item.name,
'bpy.data.brushes["%s"]' % item.name,
brush_datapath[mode], icon=brush_icon[mode][item.sculpt_tool],
disable=True, custom_disable_exp=(item.name, current_brush),
path=True
)
if mode == 'VERTEX_PAINT':
if item.use_paint_vertex:
# if you are in vertex paint mode and the brush
# is a vertex paint brush add the brush to the menu
utils_core.menuprop(
column_flow.row(), item.name,
'bpy.data.brushes["%s"]' % item.name,
brush_datapath[mode], icon=brush_icon[mode][item.vertex_tool],
disable=True, custom_disable_exp=(item.name, current_brush),
path=True
)
if mode == 'WEIGHT_PAINT':
if item.use_paint_weight:
# if you are in weight paint mode and the brush
# is a weight paint brush add the brush to the menu
utils_core.menuprop(
column_flow.row(), item.name,
'bpy.data.brushes["%s"]' % item.name,
brush_datapath[mode], icon=brush_icon[mode][item.vertex_tool],
disable=True, custom_disable_exp=(item.name, current_brush),
path=True
)
if utils_core.get_mode() == 'TEXTURE_PAINT':
if item.use_paint_image:
# if you are in texture paint mode and the brush
# is a texture paint brush add the brush to the menu
utils_core.menuprop(
column_flow.row(), item.name,
'bpy.data.brushes["%s"]' % item.name,
brush_datapath[mode], icon=brush_icon[mode][item.image_tool],
disable=True, custom_disable_exp=(item.name, current_brush),
path=True
)
def register():
bpy.utils.register_class(BrushesMenu)
def unregister():
bpy.utils.unregister_class(BrushesMenu)

View File

@ -0,0 +1,88 @@
# gpl author: Ryan Inch (Imaginer)
import bpy
from bpy.types import (
Operator,
Menu,
)
from . import utils_core
class BrushCurveMenu(Menu):
bl_label = "Curve"
bl_idname = "VIEW3D_MT_sv3_brush_curve_menu"
@classmethod
def poll(self, context):
return utils_core.get_mode() in (
'SCULPT', 'VERTEX_PAINT',
'WEIGHT_PAINT', 'TEXTURE_PAINT',
'PARTICLE_EDIT'
)
def draw(self, context):
layout = self.layout
curves = (("Smooth", "SMOOTH", "SMOOTHCURVE"),
("Sphere", "ROUND", "SPHERECURVE"),
("Root", "ROOT", "ROOTCURVE"),
("Sharp", "SHARP", "SHARPCURVE"),
("Linear", "LINE", "LINCURVE"),
("Constant", "MAX", "NOCURVE"))
# add the top slider
layout.row().operator(CurvePopup.bl_idname, icon="RNDCURVE")
layout.row().separator()
# add the rest of the menu items
for curve in curves:
item = layout.row().operator("brush.curve_preset",
text=curve[0], icon=curve[2])
item.shape = curve[1]
class CurvePopup(Operator):
"""Edit Falloff Curve"""
bl_label = "Adjust Curve"
bl_idname = "view3d.sv3_curve_popup"
bl_description = "Edit Falloff Curve"
bl_options = {'REGISTER'}
@classmethod
def poll(self, context):
return utils_core.get_mode() in (
'SCULPT', 'VERTEX_PAINT',
'WEIGHT_PAINT', 'TEXTURE_PAINT'
)
def draw(self, context):
layout = self.layout
has_brush = utils_core.get_brush_link(context, types="brush")
if utils_core.get_mode() == 'SCULPT' or \
utils_core.get_mode() == 'VERTEX_PAINT' or \
utils_core.get_mode() == 'WEIGHT_PAINT' or \
utils_core.get_mode() == 'TEXTURE_PAINT':
if has_brush:
layout.column().template_curve_mapping(has_brush,
"curve", brush=True)
else:
layout.row().label(text="No brushes available", icon="INFO")
else:
layout.row().label(text="No brushes available", icon="INFO")
def execute(self, context):
return context.window_manager.invoke_popup(self, width=180)
classes = (
BrushCurveMenu,
CurvePopup
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)

View File

@ -0,0 +1,172 @@
# gpl author: Ryan Inch (Imaginer)
import bpy
from bpy.types import Menu
from . import utils_core
class DynTopoMenu(Menu):
bl_label = "Dyntopo"
bl_idname = "VIEW3D_MT_sv3_dyntopo"
@classmethod
def poll(self, context):
return utils_core.get_mode() == 'SCULPT'
def draw(self, context):
layout = self.layout
if context.object.use_dynamic_topology_sculpting:
layout.row().operator("sculpt.dynamic_topology_toggle",
text="Disable Dynamic Topology")
layout.row().separator()
layout.row().menu(DynDetailMenu.bl_idname)
layout.row().menu(DetailMethodMenu.bl_idname)
layout.row().separator()
layout.row().operator("sculpt.optimize")
if context.tool_settings.sculpt.detail_type_method == 'CONSTANT':
layout.row().operator("sculpt.detail_flood_fill")
layout.row().menu(SymmetrizeMenu.bl_idname)
layout.row().prop(context.tool_settings.sculpt,
"use_smooth_shading", toggle=True)
else:
row = layout.row()
row.operator_context = 'INVOKE_DEFAULT'
row.operator("sculpt.dynamic_topology_toggle",
text="Enable Dynamic Topology")
class DynDetailMenu(Menu):
bl_label = "Detail Size"
bl_idname = "VIEW3D_MT_sv3_dyn_detail"
def init(self):
settings = (("40", 40),
("30", 30),
("20", 20),
("10", 10),
("5", 5),
("1", 1))
if bpy.context.tool_settings.sculpt.detail_type_method == 'RELATIVE':
datapath = "tool_settings.sculpt.detail_size"
slider_setting = "detail_size"
elif bpy.context.tool_settings.sculpt.detail_type_method == 'CONSTANT':
datapath = "tool_settings.sculpt.constant_detail_resolution"
slider_setting = "constant_detail_resolution"
else:
datapath = "tool_settings.sculpt.detail_percent"
slider_setting = "detail_percent"
settings = (("100", 100),
("75", 75),
("50", 50),
("25", 25),
("10", 10),
("5", 5))
return settings, datapath, slider_setting
def draw(self, context):
settings, datapath, slider_setting = self.init()
layout = self.layout
# add the top slider
layout.row().prop(context.tool_settings.sculpt,
slider_setting, slider=True)
layout.row().separator()
# add the rest of the menu items
for i in range(len(settings)):
utils_core.menuprop(
layout.row(), settings[i][0], settings[i][1], datapath,
icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON'
)
class DetailMethodMenu(Menu):
bl_label = "Detail Method"
bl_idname = "VIEW3D_MT_sv3_detail_method_menu"
def draw(self, context):
layout = self.layout
refine_path = "tool_settings.sculpt.detail_refine_method"
type_path = "tool_settings.sculpt.detail_type_method"
refine_items = (("Subdivide Edges", 'SUBDIVIDE'),
("Collapse Edges", 'COLLAPSE'),
("Subdivide Collapse", 'SUBDIVIDE_COLLAPSE'))
type_items = (("Relative Detail", 'RELATIVE'),
("Constant Detail", 'CONSTANT'),
("Brush Detail", 'BRUSH'))
layout.row().label(text="Refine")
layout.row().separator()
# add the refine menu items
for item in refine_items:
utils_core.menuprop(
layout.row(), item[0], item[1],
refine_path, disable=True,
icon='RADIOBUT_OFF',
disable_icon='RADIOBUT_ON'
)
layout.row().label(text="")
layout.row().label(text="Type")
layout.row().separator()
# add the type menu items
for item in type_items:
utils_core.menuprop(
layout.row(), item[0], item[1],
type_path, disable=True,
icon='RADIOBUT_OFF', disable_icon='RADIOBUT_ON'
)
class SymmetrizeMenu(Menu):
bl_label = "Symmetrize"
bl_idname = "VIEW3D_MT_sv3_symmetrize_menu"
def draw(self, context):
layout = self.layout
path = "tool_settings.sculpt.symmetrize_direction"
# add the the symmetrize operator to the menu
layout.row().operator("sculpt.symmetrize")
layout.row().separator()
# add the rest of the menu items
for item in context.tool_settings.sculpt. \
bl_rna.properties['symmetrize_direction'].enum_items:
utils_core.menuprop(
layout.row(), item.name, item.identifier,
path, disable=True,
icon='RADIOBUT_OFF', disable_icon='RADIOBUT_ON'
)
classes = (
DynTopoMenu,
DynDetailMenu,
DetailMethodMenu,
SymmetrizeMenu
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)

View File

@ -0,0 +1,200 @@
# gpl author: Ryan Inch (Imaginer)
import bpy
from bpy.types import Menu
from . import utils_core
from .brushes import brush_datapath
# stroke methods: 'AIRBRUSH' 'ANCHORED' 'SPACE' 'DRAG_DOT' 'DOTS' 'LINE' 'CURVE'
class PaintCurvesMenu(Menu):
bl_label = "Paint Curves"
bl_idname = "VIEW3D_MT_sv3_paint_curves_menu"
def draw(self, context):
mode = utils_core.get_mode()
layout = self.layout
colum_n = utils_core.addon_settings()
layout.row().label(text="Paint Curves")
layout.row().separator()
has_brush = utils_core.get_brush_link(context, types="brush")
has_current_curve = has_brush.paint_curve if has_brush else None
current_curve = has_current_curve.name if has_current_curve else ''
column_flow = layout.column_flow(columns=colum_n)
if len(bpy.data.paint_curves) != 0:
for x, item in enumerate(bpy.data.paint_curves):
utils_core.menuprop(
column_flow.row(),
item.name,
'bpy.data.paint_curves["%s"]' % item.name,
brush_datapath[mode] + ".paint_curve",
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON',
custom_disable_exp=(item.name, current_curve),
path=True
)
else:
layout.row().label(text="No Paint Curves Available", icon="INFO")
class StrokeOptionsMenu(Menu):
bl_label = "Stroke Options"
bl_idname = "VIEW3D_MT_sv3_stroke_options"
@classmethod
def poll(self, context):
return utils_core.get_mode() in (
'SCULPT', 'VERTEX_PAINT',
'WEIGHT_PAINT', 'TEXTURE_PAINT',
'PARTICLE_EDIT'
)
def init(self):
has_brush = utils_core.get_brush_link(bpy.context, types="brush")
if utils_core.get_mode() == 'SCULPT':
settings = bpy.context.tool_settings.sculpt
elif utils_core.get_mode() == 'VERTEX_PAINT':
settings = bpy.context.tool_settings.vertex_paint
elif utils_core.get_mode() == 'WEIGHT_PAINT':
settings = bpy.context.tool_settings.weight_paint
elif utils_core.get_mode() == 'TEXTURE_PAINT':
settings = bpy.context.tool_settings.image_paint
else:
settings = None
stroke_method = has_brush.stroke_method if has_brush else None
return settings, has_brush, stroke_method
def draw(self, context):
settings, brush, stroke_method = self.init()
layout = self.layout
layout.row().menu(StrokeMethodMenu.bl_idname)
layout.row().separator()
if stroke_method:
if stroke_method in ('SPACE', 'LINE') and brush:
layout.row().prop(brush, "spacing",
text=utils_core.PIW + "Spacing", slider=True)
elif stroke_method == 'AIRBRUSH' and brush:
layout.row().prop(brush, "rate",
text=utils_core.PIW + "Rate", slider=True)
elif stroke_method == 'ANCHORED' and brush:
layout.row().prop(brush, "use_edge_to_edge")
elif stroke_method == 'CURVE' and brush:
has_current_curve = brush.paint_curve if brush else None
current_curve = has_current_curve.name if has_current_curve else 'No Curve Selected'
layout.row().menu(PaintCurvesMenu.bl_idname, text=current_curve,
icon='CURVE_BEZCURVE')
layout.row().operator("paintcurve.new", icon='ADD')
layout.row().operator("paintcurve.draw")
layout.row().separator()
layout.row().prop(brush, "spacing",
text=utils_core.PIW + "Spacing",
slider=True)
else:
pass
if utils_core.get_mode() == 'SCULPT' and stroke_method in ('DRAG_DOT', 'ANCHORED'):
pass
else:
if brush:
layout.row().prop(brush, "jitter",
text=utils_core.PIW + "Jitter", slider=True)
layout.row().prop(settings, "input_samples",
text=utils_core.PIW + "Input Samples", slider=True)
if stroke_method in ('DOTS', 'SPACE', 'AIRBRUSH') and brush:
layout.row().separator()
layout.row().prop(brush, "use_smooth_stroke", toggle=True)
if brush.use_smooth_stroke:
layout.row().prop(brush, "smooth_stroke_radius",
text=utils_core.PIW + "Radius", slider=True)
layout.row().prop(brush, "smooth_stroke_factor",
text=utils_core.PIW + "Factor", slider=True)
else:
layout.row().label(text="No Stroke Options available", icon="INFO")
class StrokeMethodMenu(Menu):
bl_label = "Stroke Method"
bl_idname = "VIEW3D_MT_sv3_stroke_method"
def init(self):
has_brush = utils_core.get_brush_link(bpy.context, types="brush")
if utils_core.get_mode() == 'SCULPT':
path = "tool_settings.sculpt.brush.stroke_method"
elif utils_core.get_mode() == 'VERTEX_PAINT':
path = "tool_settings.vertex_paint.brush.stroke_method"
elif utils_core.get_mode() == 'WEIGHT_PAINT':
path = "tool_settings.weight_paint.brush.stroke_method"
elif utils_core.get_mode() == 'TEXTURE_PAINT':
path = "tool_settings.image_paint.brush.stroke_method"
else:
path = ""
return has_brush, path
def draw(self, context):
brush, path = self.init()
layout = self.layout
layout.row().label(text="Stroke Method")
layout.row().separator()
if brush:
# add the menu items dynamically based on values in enum property
for tool in brush.bl_rna.properties['stroke_method'].enum_items:
if tool.identifier in ('ANCHORED', 'DRAG_DOT') and \
utils_core.get_mode() in ('VERTEX_PAINT',
'WEIGHT_PAINT'):
continue
utils_core.menuprop(
layout.row(), tool.name, tool.identifier, path,
icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON'
)
else:
layout.row().label(text="No Stroke Method available", icon="INFO")
classes = (
PaintCurvesMenu,
StrokeOptionsMenu,
StrokeMethodMenu
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)

View File

@ -0,0 +1,80 @@
# gpl author: Ryan Inch (Imaginer)
import bpy
from bpy.types import Menu
from . import utils_core
class MasterSymmetryMenu(Menu):
bl_label = "Symmetry Options"
bl_idname = "VIEW3D_MT_sv3_master_symmetry_menu"
@classmethod
def poll(self, context):
return utils_core.get_mode() in (
'SCULPT',
'TEXTURE_PAINT'
)
def draw(self, context):
layout = self.layout
if utils_core.get_mode() == 'TEXTURE_PAINT':
layout.row().prop(context.tool_settings.image_paint,
"use_symmetry_x", toggle=True)
layout.row().prop(context.tool_settings.image_paint,
"use_symmetry_y", toggle=True)
layout.row().prop(context.tool_settings.image_paint,
"use_symmetry_z", toggle=True)
else:
layout.row().menu(SymmetryMenu.bl_idname)
layout.row().menu(SymmetryRadialMenu.bl_idname)
layout.row().prop(context.tool_settings.sculpt,
"use_symmetry_feather", toggle=True)
class SymmetryMenu(Menu):
bl_label = "Symmetry"
bl_idname = "VIEW3D_MT_sv3_symmetry_menu"
def draw(self, context):
layout = self.layout
layout.row().label(text="Symmetry")
layout.row().separator()
layout.row().prop(context.tool_settings.sculpt,
"use_symmetry_x", toggle=True)
layout.row().prop(context.tool_settings.sculpt,
"use_symmetry_y", toggle=True)
layout.row().prop(context.tool_settings.sculpt,
"use_symmetry_z", toggle=True)
class SymmetryRadialMenu(Menu):
bl_label = "Radial"
bl_idname = "VIEW3D_MT_sv3_symmetry_radial_menu"
def draw(self, context):
layout = self.layout
layout.row().label(text="Radial")
layout.row().separator()
layout.column().prop(context.tool_settings.sculpt,
"radial_symmetry", text="", slider=True)
classes = (
MasterSymmetryMenu,
SymmetryMenu,
SymmetryRadialMenu
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)

View File

@ -0,0 +1,415 @@
# gpl author: Ryan Inch (Imaginer)
import bpy
from bpy.types import Menu
from . import utils_core
class TextureMenu(Menu):
bl_label = "Texture Options"
bl_idname = "VIEW3D_MT_sv3_texture_menu"
@classmethod
def poll(self, context):
return utils_core.get_mode() in (
'SCULPT',
'VERTEX_PAINT',
'TEXTURE_PAINT'
)
def draw(self, context):
layout = self.layout
if utils_core.get_mode() == 'SCULPT':
self.sculpt(layout, context)
elif utils_core.get_mode() == 'VERTEX_PAINT':
self.vertpaint(layout, context)
else:
self.texpaint(layout, context)
def sculpt(self, layout, context):
has_brush = utils_core.get_brush_link(context, types="brush")
tex_slot = has_brush.texture_slot if has_brush else None
# Menus
layout.row().menu(Textures.bl_idname)
layout.row().menu(TextureMapMode.bl_idname)
layout.row().separator()
# Checkboxes
if tex_slot:
if tex_slot.map_mode != '3D':
if tex_slot.map_mode in ('RANDOM', 'VIEW_PLANE', 'AREA_PLANE'):
layout.row().prop(tex_slot, "use_rake", toggle=True)
layout.row().prop(tex_slot, "use_random", toggle=True)
# Sliders
layout.row().prop(tex_slot, "angle",
text=utils_core.PIW + "Angle", slider=True)
if tex_slot.tex_paint_map_mode in ('RANDOM', 'VIEW_PLANE') and tex_slot.use_random:
layout.row().prop(tex_slot, "random_angle",
text=utils_core.PIW + "Random Angle", slider=True)
# Operator
if tex_slot.tex_paint_map_mode == 'STENCIL':
if has_brush.texture and has_brush.texture.type == 'IMAGE':
layout.row().operator("brush.stencil_fit_image_aspect")
layout.row().operator("brush.stencil_reset_transform")
else:
layout.row().label(text="No Texture Slot available", icon="INFO")
def vertpaint(self, layout, context):
has_brush = utils_core.get_brush_link(context, types="brush")
tex_slot = has_brush.texture_slot if has_brush else None
# Menus
layout.row().menu(Textures.bl_idname)
layout.row().menu(TextureMapMode.bl_idname)
# Checkboxes
if tex_slot:
if tex_slot.tex_paint_map_mode != '3D':
if tex_slot.tex_paint_map_mode in ('RANDOM', 'VIEW_PLANE'):
layout.row().prop(tex_slot, "use_rake", toggle=True)
layout.row().prop(tex_slot, "use_random", toggle=True)
# Sliders
layout.row().prop(tex_slot, "angle",
text=utils_core.PIW + "Angle", slider=True)
if tex_slot.tex_paint_map_mode in ('RANDOM', 'VIEW_PLANE') and tex_slot.use_random:
layout.row().prop(tex_slot, "random_angle",
text=utils_core.PIW + "Random Angle", slider=True)
# Operator
if tex_slot.tex_paint_map_mode == 'STENCIL':
if has_brush.texture and has_brush.texture.type == 'IMAGE':
layout.row().operator("brush.stencil_fit_image_aspect")
layout.row().operator("brush.stencil_reset_transform")
else:
layout.row().label(text="No Texture Slot available", icon="INFO")
def texpaint(self, layout, context):
has_brush = utils_core.get_brush_link(context, types="brush")
tex_slot = has_brush.texture_slot if has_brush else None
mask_tex_slot = has_brush.mask_texture_slot if has_brush else None
# Texture Section
layout.row().label(text="Texture", icon='TEXTURE')
# Menus
layout.row().menu(Textures.bl_idname)
layout.row().menu(TextureMapMode.bl_idname)
# Checkboxes
if tex_slot:
if tex_slot.tex_paint_map_mode != '3D':
if tex_slot.tex_paint_map_mode in ('RANDOM', 'VIEW_PLANE'):
layout.row().prop(tex_slot, "use_rake", toggle=True)
layout.row().prop(tex_slot, "use_random", toggle=True)
# Sliders
layout.row().prop(tex_slot, "angle",
text=utils_core.PIW + "Angle", slider=True)
if tex_slot.tex_paint_map_mode in ('RANDOM', 'VIEW_PLANE') and tex_slot.use_random:
layout.row().prop(tex_slot, "random_angle",
text=utils_core.PIW + "Random Angle", slider=True)
# Operator
if tex_slot.tex_paint_map_mode == 'STENCIL':
if has_brush.texture and has_brush.texture.type == 'IMAGE':
layout.row().operator("brush.stencil_fit_image_aspect")
layout.row().operator("brush.stencil_reset_transform")
else:
layout.row().label(text="No Texture Slot available", icon="INFO")
layout.row().separator()
# Texture Mask Section
layout.row().label(text="Texture Mask", icon='MOD_MASK')
# Menus
layout.row().menu(MaskTextures.bl_idname)
layout.row().menu(MaskMapMode.bl_idname)
layout.row().menu(MaskPressureModeMenu.bl_idname)
# Checkboxes
if mask_tex_slot:
if mask_tex_slot.mask_map_mode in ('RANDOM', 'VIEW_PLANE'):
layout.row().prop(mask_tex_slot, "use_rake", toggle=True)
layout.row().prop(mask_tex_slot, "use_random", toggle=True)
# Sliders
layout.row().prop(mask_tex_slot, "angle",
text=utils_core.PIW + "Angle", icon_value=5, slider=True)
if mask_tex_slot.mask_map_mode in ('RANDOM', 'VIEW_PLANE') and mask_tex_slot.use_random:
layout.row().prop(mask_tex_slot, "random_angle",
text=utils_core.PIW + "Random Angle", slider=True)
# Operator
if mask_tex_slot.mask_map_mode == 'STENCIL':
if has_brush.mask_texture and has_brush.mask_texture.type == 'IMAGE':
layout.row().operator("brush.stencil_fit_image_aspect")
prop = layout.row().operator("brush.stencil_reset_transform")
prop.mask = True
else:
layout.row().label(text="Mask Texture not available", icon="INFO")
class Textures(Menu):
bl_label = "Brush Texture"
bl_idname = "VIEW3D_MT_sv3_texture_list"
def init(self):
if utils_core.get_mode() == 'SCULPT':
datapath = "tool_settings.sculpt.brush.texture"
elif utils_core.get_mode() == 'VERTEX_PAINT':
datapath = "tool_settings.vertex_paint.brush.texture"
elif utils_core.get_mode() == 'TEXTURE_PAINT':
datapath = "tool_settings.image_paint.brush.texture"
else:
datapath = ""
return datapath
def draw(self, context):
datapath = self.init()
has_brush = utils_core.get_brush_link(context, types="brush")
current_texture = eval("bpy.context.{}".format(datapath)) if \
has_brush else None
layout = self.layout
# get the current texture's name
if current_texture:
current_texture = current_texture.name
layout.row().label(text="Brush Texture")
layout.row().separator()
# add an item to set the texture to None
utils_core.menuprop(layout.row(), "None", "None",
datapath, icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON',
custom_disable_exp=(None, current_texture),
path=True)
# add the menu items
for item in bpy.data.textures:
utils_core.menuprop(layout.row(), item.name,
'bpy.data.textures["%s"]' % item.name,
datapath, icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON',
custom_disable_exp=(item.name, current_texture),
path=True)
class TextureMapMode(Menu):
bl_label = "Brush Mapping"
bl_idname = "VIEW3D_MT_sv3_texture_map_mode"
def draw(self, context):
layout = self.layout
has_brush = utils_core.get_brush_link(context, types="brush")
layout.row().label(text="Brush Mapping")
layout.row().separator()
if has_brush:
if utils_core.get_mode() == 'SCULPT':
path = "tool_settings.sculpt.brush.texture_slot.map_mode"
# add the menu items
for item in has_brush. \
texture_slot.bl_rna.properties['map_mode'].enum_items:
utils_core.menuprop(
layout.row(), item.name, item.identifier, path,
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON'
)
elif utils_core.get_mode() == 'VERTEX_PAINT':
path = "tool_settings.vertex_paint.brush.texture_slot.tex_paint_map_mode"
# add the menu items
for item in has_brush. \
texture_slot.bl_rna.properties['tex_paint_map_mode'].enum_items:
utils_core.menuprop(
layout.row(), item.name, item.identifier, path,
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON'
)
else:
path = "tool_settings.image_paint.brush.texture_slot.tex_paint_map_mode"
# add the menu items
for item in has_brush. \
texture_slot.bl_rna.properties['tex_paint_map_mode'].enum_items:
utils_core.menuprop(
layout.row(), item.name, item.identifier, path,
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON'
)
else:
layout.row().label(text="No brushes available", icon="INFO")
class MaskTextures(Menu):
bl_label = "Mask Texture"
bl_idname = "VIEW3D_MT_sv3_mask_texture_list"
def draw(self, context):
layout = self.layout
datapath = "tool_settings.image_paint.brush.mask_texture"
has_brush = utils_core.get_brush_link(context, types="brush")
current_texture = eval("bpy.context.{}".format(datapath)) if \
has_brush else None
layout.row().label(text="Mask Texture")
layout.row().separator()
if has_brush:
# get the current texture's name
if current_texture:
current_texture = current_texture.name
# add an item to set the texture to None
utils_core.menuprop(
layout.row(), "None", "None",
datapath, icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON',
custom_disable_exp=(None, current_texture),
path=True
)
# add the menu items
for item in bpy.data.textures:
utils_core.menuprop(
layout.row(), item.name, 'bpy.data.textures["%s"]' % item.name,
datapath, icon='RADIOBUT_OFF', disable=True,
disable_icon='RADIOBUT_ON',
custom_disable_exp=(item.name, current_texture),
path=True
)
else:
layout.row().label(text="No brushes available", icon="INFO")
class MaskMapMode(Menu):
bl_label = "Mask Mapping"
bl_idname = "VIEW3D_MT_sv3_mask_map_mode"
def draw(self, context):
layout = self.layout
path = "tool_settings.image_paint.brush.mask_texture_slot.mask_map_mode"
has_brush = utils_core.get_brush_link(context, types="brush")
layout.row().label(text="Mask Mapping")
layout.row().separator()
if has_brush:
items = has_brush. \
mask_texture_slot.bl_rna.properties['mask_map_mode'].enum_items
# add the menu items
for item in items:
utils_core.menuprop(
layout.row(), item.name, item.identifier, path,
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON'
)
else:
layout.row().label(text="No brushes available", icon="INFO")
class TextureAngleSource(Menu):
bl_label = "Texture Angle Source"
bl_idname = "VIEW3D_MT_sv3_texture_angle_source"
def draw(self, context):
layout = self.layout
has_brush = utils_core.get_brush_link(context, types="brush")
if has_brush:
if utils_core.get_mode() == 'SCULPT':
items = has_brush. \
bl_rna.properties['texture_angle_source_random'].enum_items
path = "tool_settings.sculpt.brush.texture_angle_source_random"
elif utils_core.get_mode() == 'VERTEX_PAINT':
items = has_brush. \
bl_rna.properties['texture_angle_source_random'].enum_items
path = "tool_settings.vertex_paint.brush.texture_angle_source_random"
else:
items = has_brush. \
bl_rna.properties['texture_angle_source_random'].enum_items
path = "tool_settings.image_paint.brush.texture_angle_source_random"
# add the menu items
for item in items:
utils_core.menuprop(
layout.row(), item[0], item[1], path,
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON'
)
else:
layout.row().label(text="No brushes available", icon="INFO")
class MaskPressureModeMenu(Menu):
bl_label = "Mask Pressure Mode"
bl_idname = "VIEW3D_MT_sv3_mask_pressure_mode_menu"
def draw(self, context):
layout = self.layout
path = "tool_settings.image_paint.brush.use_pressure_masking"
layout.row().label(text="Mask Pressure Mode")
layout.row().separator()
# add the menu items
for item in context.tool_settings.image_paint.brush. \
bl_rna.properties['use_pressure_masking'].enum_items:
utils_core.menuprop(
layout.row(), item.name, item.identifier, path,
icon='RADIOBUT_OFF',
disable=True,
disable_icon='RADIOBUT_ON'
)
classes = (
TextureMenu,
Textures,
TextureMapMode,
MaskTextures,
MaskMapMode,
TextureAngleSource,
MaskPressureModeMenu
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)

View File

@ -0,0 +1,105 @@
# gpl author: Ryan Inch (Imaginer)
import bpy
get_addon_name = 'space_view3d_brush_menus'
# Property Icon Width
PIW = ' '
# check for (currently) brushes being linked
def get_brush_link(context, types="brush"):
tool_settings = context.tool_settings
has_brush = None
if get_mode() == 'SCULPT':
datapath = tool_settings.sculpt
elif get_mode() == 'VERTEX_PAINT':
datapath = tool_settings.vertex_paint
elif get_mode() == 'WEIGHT_PAINT':
datapath = tool_settings.weight_paint
elif get_mode() == 'TEXTURE_PAINT':
datapath = tool_settings.image_paint
else:
datapath = None
if types == "brush":
has_brush = getattr(datapath, "brush", None)
return has_brush
# Addon settings
def addon_settings():
# separate function just for more convenience
addon = bpy.context.preferences.addons[get_addon_name]
colum_n = addon.preferences.column_set if addon else 1
return colum_n
def error_handlers(self, op_name, error, reports="ERROR", func=False):
if self and reports:
self.report({'WARNING'}, reports + " (See Console for more info)")
is_func = "Function" if func else "Operator"
print("\n[Sculpt/Paint Brush Menus]\n{}: {}\nError: {}\n".format(is_func, op_name, error))
# Object modes:
# 'OBJECT' 'EDIT' 'SCULPT'
# 'VERTEX_PAINT' 'WEIGHT_PAINT' 'TEXTURE_PAINT'
# 'PARTICLE_EDIT' 'POSE' 'GPENCIL_EDIT'
def get_mode():
return bpy.context.object.mode
def menuprop(item, name, value, data_path,
icon='NONE', disable=False, disable_icon=None,
custom_disable_exp=None, method=None, path=False):
# disable the ui
if disable:
disabled = False
# used if you need a custom expression to disable the ui
if custom_disable_exp:
if custom_disable_exp[0] == custom_disable_exp[1]:
item.enabled = False
disabled = True
# check if the ui should be disabled for numbers
elif isinstance(eval("bpy.context.{}".format(data_path)), float):
if round(eval("bpy.context.{}".format(data_path)), 2) == value:
item.enabled = False
disabled = True
# check if the ui should be disabled for anything else
else:
if eval("bpy.context.{}".format(data_path)) == value:
item.enabled = False
disabled = True
# change the icon to the disable_icon if the ui has been disabled
if disable_icon and disabled:
icon = disable_icon
# creates the menu item
prop = item.operator("wm.context_set_value", text=name, icon=icon)
# sets what the menu item changes
if path:
prop.value = value
value = eval(value)
elif type(value) == str:
prop.value = "'{}'".format(value)
else:
prop.value = '{}'.format(value)
# sets the path to what is changed
prop.data_path = data_path

View File

@ -196,25 +196,6 @@ class PIE_OT_VertsEdgesFaces(Operator):
return {'FINISHED'}
# Grease Pencil Interactive Mode
class PIE_OT_InteractiveModeGreasePencil(Operator):
bl_idname = "view3d.pie_interactive_mode_grease_pencil"
bl_label = "Edit Strokes"
bl_description = "Toggle Edit Strokes for Grease Pencil"
@classmethod
def poll(cls, context):
return (context.gpencil_data is not None)
def execute(self, context):
try:
bpy.ops.gpencil.editmode_toggle()
except:
self.report({'WARNING'},
"It is not possible to enter into the interactive mode")
return {'FINISHED'}
# Menus
class PIE_MT_ObjectEditotherModes(Menu):
"""Edit/Object Others modes"""
@ -267,13 +248,12 @@ class PIE_MT_ObjectEditMode(Menu):
# 9 - TOP - RIGHT
pie.operator("class.pievertexpaint", text="Vertex Paint", icon='VPAINT_HLT')
# 1 - BOTTOM - LEFT
pie.separator()
# 3 - BOTTOM - RIGHT
if context.object.particle_systems:
pie.operator("class.pieparticleedit", text="Particle Edit", icon='PARTICLEMODE')
else:
pie.separator()
# 3 - BOTTOM - RIGHT
if context.gpencil_data:
pie.operator("view3d.pie_interactive_mode_grease_pencil", icon="GREASEPENCIL")
elif ob and ob.type == 'MESH' and ob.mode in {'EDIT'}:
pie = layout.menu_pie()
@ -290,13 +270,12 @@ class PIE_MT_ObjectEditMode(Menu):
# 9 - TOP - RIGHT
pie.operator("class.pievertexpaint", text="Vertex Paint", icon='VPAINT_HLT')
# 1 - BOTTOM - LEFT
pie.separator()
# 3 - BOTTOM - RIGHT
if context.object.particle_systems:
pie.operator("class.pieparticleedit", text="Particle Edit", icon='PARTICLEMODE')
else:
pie.separator()
# 3 - BOTTOM - RIGHT
if context.gpencil_data:
pie.operator("view3d.pie_interactive_mode_grease_pencil", icon="GREASEPENCIL")
elif ob and ob.type == 'CURVE':
pie = layout.menu_pie()
@ -315,8 +294,7 @@ class PIE_MT_ObjectEditMode(Menu):
# 1 - BOTTOM - LEFT
pie.separator()
# 3 - BOTTOM - RIGHT
if context.gpencil_data:
pie.operator("view3d.pie_interactive_mode_grease_pencil", icon="GREASEPENCIL")
pie.separator()
elif ob and ob.type == 'ARMATURE':
pie = layout.menu_pie()
@ -335,8 +313,7 @@ class PIE_MT_ObjectEditMode(Menu):
# 1 - BOTTOM - LEFT
pie.separator()
# 3 - BOTTOM - RIGHT
if context.gpencil_data:
pie.operator("view3d.pie_interactive_mode_grease_pencil", icon="GREASEPENCIL")
pie.separator()
elif ob and ob.type == 'FONT':
pie = layout.menu_pie()
@ -348,8 +325,7 @@ class PIE_MT_ObjectEditMode(Menu):
pie.separator()
pie.separator()
# 3 - BOTTOM - RIGHT
if context.gpencil_data:
pie.operator("view3d.pie_interactive_mode_grease_pencil", icon="GREASEPENCIL")
pie.separator()
elif ob and ob.type == 'SURFACE':
pie = layout.menu_pie()
@ -361,8 +337,7 @@ class PIE_MT_ObjectEditMode(Menu):
pie.separator()
pie.separator()
# 3 - BOTTOM - RIGHT
if context.gpencil_data:
pie.operator("view3d.pie_interactive_mode_grease_pencil", icon="GREASEPENCIL")
pie.separator()
elif ob and ob.type == 'META':
pie = layout.menu_pie()
@ -374,8 +349,7 @@ class PIE_MT_ObjectEditMode(Menu):
pie.separator()
pie.separator()
# 3 - BOTTOM - RIGHT
if context.gpencil_data:
pie.operator("view3d.pie_interactive_mode_grease_pencil", icon="GREASEPENCIL")
pie.separator()
elif ob and ob.type == 'LATTICE':
pie = layout.menu_pie()
@ -429,7 +403,6 @@ classes = (
PIE_OT_ClassWeightPaint,
PIE_OT_ClassVertexPaint,
PIE_OT_ClassParticleEdit,
PIE_OT_InteractiveModeGreasePencil,
PIE_OT_VertsEdgesFaces,
PIE_OT_SetObjectModePie,
)

File diff suppressed because it is too large Load Diff

View File

@ -31,20 +31,6 @@ from bpy.props import (
from bl_ui.properties_paint_common import UnifiedPaintPanel
# Animation Menus
class VIEW3D_MT_KeyframeMenu(Menu):
bl_label = "Keyframe"
def draw(self, context):
layout = self.layout
layout.operator("anim.keyframe_insert_menu",
text="Insert Keyframe...")
layout.operator("anim.keyframe_delete_v3d",
text="Delete Keyframe...")
layout.operator("anim.keying_set_active_set",
text="Change Keying Set...")
# Animation Player (Thanks to marvin.k.breuer) #
class VIEW3D_MT_Animation_Player(Menu):
@ -67,14 +53,13 @@ class VIEW3D_MT_Animation_Player(Menu):
layout.operator("screen.frame_jump", text="Jump REW", icon='REW').end = False
layout.separator()
layout.menu("VIEW3D_MT_KeyframeMenu", text="Keyframes", icon='DECORATE_ANIMATE')
layout.menu("VIEW3D_MT_object_animation", text="Keyframes", icon='DECORATE_ANIMATE')
# List The Classes #
classes = (
VIEW3D_MT_KeyframeMenu,
VIEW3D_MT_Animation_Player,
)

View File

@ -27,6 +27,7 @@ from bpy.props import (
BoolProperty,
StringProperty,
)
from .object_menus import *
@ -39,73 +40,33 @@ class VIEW3D_MT_Edit_Curve(Menu):
toolsettings = context.tool_settings
layout.operator("curve.extrude_move")
layout.operator("curve.spin")
layout.operator_menu_enum("curve.spline_type_set", "type")
layout.menu("VIEW3D_MT_mirror")
layout.operator("curve.make_segment")
layout.menu("VIEW3D_MT_edit_curve_segments")
layout.separator()
layout.operator("curve.duplicate_move")
layout.operator("curve.split")
layout.operator("curve.separate")
layout.operator("curve.make_segment")
layout.operator("curve.cyclic_toggle")
layout.operator("curve.spin")
layout.separator()
layout.operator("curve.delete", text="Delete...")
layout.menu("VIEW3D_MT_edit_curve_showhide")
layout.menu("VIEW3D_MT_edit_curve_clean")
layout.separator()
layout.menu("VIEW3D_MT_edit_curve_segments")
# layout.prop_menu_enum(toolsettings, "proportional_edit",
# icon="PROP_CON")
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff",
icon="SMOOTHCURVE")
layout.menu("VIEW3D_MT_edit_curve_showhide")
class VIEW3D_MT_EditCurveCtrlpoints(Menu):
bl_label = "Control Points"
def draw(self, context):
layout = self.layout
edit_object = context.edit_object
if edit_object.type == 'CURVE':
layout.operator("transform.transform").mode = 'TILT'
layout.operator("curve.tilt_clear")
layout.operator("curve.separate")
layout.operator_menu_enum("curve.handle_type_set", "type")
layout.menu("VIEW3D_MT_hook")
class VIEW3D_MT_EditCurveSegments(Menu):
bl_label = "Curve Segments"
def draw(self, context):
layout = self.layout
layout.operator("curve.subdivide")
layout.operator("curve.switch_direction")
class VIEW3D_MT_EditCurveSpecials(Menu):
bl_label = "Specials"
def draw(self, context):
layout = self.layout
layout.operator("curve.subdivide")
layout.separator()
layout.operator("curve.switch_direction")
layout.operator("curve.spline_weight_set")
layout.operator("curve.radius_set")
layout.separator()
layout.operator("curve.smooth")
layout.operator("curve.smooth_weight")
layout.operator("curve.smooth_radius")
layout.operator("curve.smooth_tilt")
# List The Classes #
classes = (
VIEW3D_MT_Edit_Curve,
VIEW3D_MT_EditCurveCtrlpoints,
VIEW3D_MT_EditCurveSegments,
VIEW3D_MT_EditCurveSpecials,
)

View File

@ -32,95 +32,8 @@ from .object_menus import *
from .snap_origin_cursor import *
# ********** Edit Mirror **********
class VIEW3D_MT_MirrorMenuEM(Menu):
bl_label = "Mirror"
def draw(self, context):
layout = self.layout
props = layout.operator("transform.mirror", text="X Local")
props.constraint_axis = (True, False, False)
props.orient_type = 'LOCAL'
props = layout.operator("transform.mirror", text="Y Local")
props.constraint_axis = (False, True, False)
props.orient_type = 'LOCAL'
props = layout.operator("transform.mirror", text="Z Local")
props.constraint_axis = (False, False, True)
props.orient_type = 'LOCAL'
layout.separator()
layout.operator("object.vertex_group_mirror")
# ********** Normals / Auto Smooth Menu **********
# Thanks to marvin.k.breuer for the Autosmooth part of the menu
class VIEW3D_MT_AutoSmooth(Menu):
bl_label = "Normals / Auto Smooth"
def draw(self, context):
layout = self.layout
obj = context.object
obj_data = context.active_object.data
# moved the VIEW3D_MT_edit_mesh_normals contents here under an Edit mode check
if obj and obj.type == 'MESH' and obj.mode in {'EDIT'}:
layout.operator("mesh.normals_make_consistent",
text="Recalculate Outside").inside = False
layout.operator("mesh.normals_make_consistent",
text="Recalculate Inside").inside = True
layout.operator("mesh.flip_normals")
layout.separator()
layout.separator()
layout.prop(obj_data, "use_auto_smooth", text="Normals: Auto Smooth")
# Auto Smooth Angle - two tab spaces to align it with the rest of the menu
layout.prop(obj_data, "auto_smooth_angle",
text=" Auto Smooth Angle")
# Edit Mode Menu's #
# ********** Edit Mesh **********
class VIEW3D_MT_Edit_Mesh(Menu):
bl_label = "Mesh"
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
view = context.space_data
layout.menu("VIEW3D_MT_edit_mesh_vertices", icon='VERTEXSEL')
layout.menu("VIEW3D_MT_edit_mesh_edges", icon='EDGESEL')
layout.menu("VIEW3D_MT_edit_mesh_faces", icon='FACESEL')
layout.separator()
layout.operator("mesh.duplicate_move")
layout.separator()
layout.menu("VIEW3D_MT_edit_mesh_clean", icon='AUTO')
# layout.prop(view, "use_occlude_geometry")
layout.separator()
layout.menu("VIEW3D_MT_AutoSmooth", icon='META_DATA')
layout.operator("mesh.loopcut_slide",
text="Loopcut", icon='UV_EDGESEL')
layout.separator()
layout.operator("mesh.symmetrize")
layout.operator("mesh.symmetry_snap")
layout.separator()
layout.operator("mesh.bisect")
layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...")
layout.separator()
# layout.prop_menu_enum(toolsettings, "proportional_edit")
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
layout.separator()
layout.prop(toolsettings, "use_mesh_automerge")
# Double Threshold - two tab spaces to align it with the rest of the menu
layout.prop(toolsettings, "double_threshold", text="Double Threshold")
layout.separator()
layout.menu("VIEW3D_MT_edit_mesh_showhide")
# ********** Edit Multiselect **********
class VIEW3D_MT_Edit_Multi(Menu):
bl_label = "Mode Select"
@ -167,156 +80,6 @@ class VIEW3D_MT_EditM_Edge(Menu):
layout.operator("mesh.region_to_loop")
# ********** Edit Mesh Cursor **********
class VIEW3D_MT_EditCursorMenu(Menu):
bl_label = "Snap Cursor"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("object.setorigintoselected",
text="Origin to Selected V/F/E")
layout.separator()
layout.menu("VIEW3D_MT_Snap_Origin")
layout.menu("VIEW3D_MT_Snap_Context")
layout.separator()
layout.operator("view3d.snap_cursor_to_selected",
text="Cursor to Selected")
layout.operator("view3d.snap_cursor_to_center",
text="Cursor to World Origin")
layout.operator("view3d.snap_cursor_to_grid",
text="Cursor to Grid")
layout.operator("view3d.snap_cursor_to_active",
text="Cursor to Active")
layout.operator("view3d.snap_cursor_to_edge_intersection",
text="Cursor to Edge Intersection")
layout.separator()
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor").use_offset = False
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor (Keep Offset)").use_offset = True
layout.operator("view3d.snap_selected_to_grid",
text="Selection to Grid")
# ********** Edit Mesh UV **********
class VIEW3D_MT_UV_Map(Menu):
bl_label = "UV Mapping"
def draw(self, context):
layout = self.layout
layout.operator("uv.unwrap")
layout.separator()
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("uv.smart_project")
layout.operator("uv.lightmap_pack")
layout.operator("uv.follow_active_quads")
layout.operator_context = 'EXEC_REGION_WIN'
layout.operator("uv.cube_project")
layout.operator("uv.cylinder_project")
layout.operator("uv.sphere_project")
layout.operator_context = 'INVOKE_REGION_WIN'
layout.separator()
layout.operator("uv.project_from_view").scale_to_bounds = False
layout.operator("uv.project_from_view", text="Project from View (Bounds)").scale_to_bounds = True
layout.separator()
layout.operator("uv.reset")
# ********** Edit Mesh Transform **********
class VIEW3D_MT_TransformMenuEdit(Menu):
bl_label = "Transform"
def draw(self, context):
layout = self.layout
layout.operator("transform.translate", text="Move")
layout.operator("transform.rotate", text="Rotate")
layout.operator("transform.resize", text="Scale")
layout.separator()
layout.operator("transform.tosphere", text="To Sphere")
layout.operator("transform.shear", text="Shear")
layout.operator("transform.bend", text="Bend")
layout.operator("transform.push_pull", text="Push/Pull")
layout.operator("transform.vertex_warp", text="Warp")
layout.operator("transform.vertex_random", text="Randomize")
layout.separator()
layout.operator("transform.translate", text="Move Texture Space").texture_space = True
layout.operator("transform.resize", text="Scale Texture Space").texture_space = True
layout.separator()
layout.operator_context = 'EXEC_REGION_WIN'
layout.operator("transform.transform",
text="Align to Transform Orientation").mode = 'ALIGN'
layout.operator_context = 'EXEC_AREA'
layout.operator("object.origin_set",
text="Geometry to Origin").type = 'GEOMETRY_ORIGIN'
# Edit Select #
class VIEW3D_MT_Select_Edit_Mesh(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.separator()
layout.operator("mesh.select_all").action = 'TOGGLE'
layout.operator("mesh.select_all", text="Inverse").action = 'INVERT'
layout.operator("mesh.select_linked", text="Linked")
layout.operator("mesh.faces_select_linked_flat",
text="Linked Flat Faces")
layout.operator("mesh.select_random", text="Random")
layout.operator("mesh.select_nth", text="Every N Number of Verts")
layout.separator()
layout.menu("VIEW3D_MT_Edit_Mesh_Select_Trait")
layout.menu("VIEW3D_MT_Edit_Mesh_Select_Similar")
layout.menu("VIEW3D_MT_Edit_Mesh_Select_More_Less")
layout.separator()
layout.operator("mesh.select_mirror", text="Mirror")
layout.operator("mesh.edges_select_sharp", text="Sharp Edges")
layout.operator("mesh.select_axis", text="Side of Active")
layout.operator("mesh.shortest_path_select", text="Shortest Path")
layout.separator()
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")
class VIEW3D_MT_Edit_Mesh_Select_Similar(Menu):
bl_label = "Select Similar"
def draw(self, context):
layout = self.layout
layout.operator_enum("mesh.select_similar", "type")
layout.operator("mesh.select_similar_region", text="Face Regions")
class VIEW3D_MT_Edit_Mesh_Select_Trait(Menu):
bl_label = "Select All by Trait"
def draw(self, context):
layout = self.layout
if context.scene.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")
layout.operator("mesh.select_face_by_sides", text="By Number of Verts")
layout.operator("mesh.select_ungrouped", text="Ungrouped Verts")
class VIEW3D_MT_Edit_Mesh_Select_More_Less(Menu):
bl_label = "Select More/Less"
def draw(self, context):
layout = self.layout
layout.operator("mesh.select_more", text="More")
layout.operator("mesh.select_less", text="Less")
layout.separator()
layout.operator("mesh.select_next_item", text="Next Active")
layout.operator("mesh.select_prev_item", text="Previous Active")
# multiple edit select modes.
class VIEW3D_OT_selecteditVertex(Operator):
bl_idname = "selectedit.vertex"
@ -433,21 +196,26 @@ class VIEW3D_OT_selecteditVertsEdgesFaces(Operator):
return {'FINISHED'}
# ********** Normals / Auto Smooth Menu **********
# Thanks to marvin.k.breuer for the Autosmooth part of the menu
def menu_func(self, context):
layout = self.layout
obj = context.object
obj_data = context.active_object.data
layout.separator()
layout.prop(obj_data, "use_auto_smooth", text="Normals: Auto Smooth")
# Auto Smooth Angle - two tab spaces to align it with the rest of the menu
layout.prop(obj_data, "auto_smooth_angle",
text=" Auto Smooth Angle")
# List The Classes #
classes = (
VIEW3D_MT_MirrorMenuEM,
VIEW3D_MT_AutoSmooth,
VIEW3D_MT_Edit_Mesh,
VIEW3D_MT_Edit_Multi,
VIEW3D_MT_EditM_Edge,
VIEW3D_MT_EditCursorMenu,
VIEW3D_MT_UV_Map,
VIEW3D_MT_TransformMenuEdit,
VIEW3D_MT_Select_Edit_Mesh,
VIEW3D_MT_Edit_Mesh_Select_Similar,
VIEW3D_MT_Edit_Mesh_Select_Trait,
VIEW3D_MT_Edit_Mesh_Select_More_Less,
VIEW3D_OT_selecteditVertex,
VIEW3D_OT_selecteditEdge,
VIEW3D_OT_selecteditFace,
@ -463,6 +231,7 @@ def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.VIEW3D_MT_edit_mesh_normals.append(menu_func)
# Unregister Classes & Hotkeys #
def unregister():
@ -470,6 +239,7 @@ def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
bpy.types.VIEW3D_MT_edit_mesh_normals.remove(menu_func)
if __name__ == "__main__":
register()

View File

@ -30,7 +30,8 @@ from bpy.props import (
from bl_ui.properties_paint_common import UnifiedPaintPanel
from . edit_mesh import *
from . view_menus import *
# Object Menus #
# ********** Object Menu **********
@ -41,119 +42,39 @@ 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.operator("object.delete", text="Delete...").use_global = False
layout.separator()
layout.menu("VIEW3D_MT_mirror")
layout.menu("VIEW3D_MT_object_parent")
layout.menu("VIEW3D_MT_Duplicate")
layout.operator("object.join")
layout.menu("VIEW3D_MT_make_links", text="Make Links")
layout.menu("VIEW3D_MT_object_relations")
layout.separator()
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'
ob = context.active_object
if ob and ob.type == 'GPENCIL' and context.gpencil_data:
layout.operator_menu_enum("gpencil.convert", "type", text="Convert to")
else:
layout.operator_menu_enum("object.convert", "target")
layout.menu("VIEW3D_MT_make_links", text="Make Links...")
layout.menu("VIEW3D_MT_Object_Data_Link")
layout.separator()
layout.menu("VIEW3D_MT_AutoSmooth", icon='ALIASED')
layout.separator()
layout.menu("VIEW3D_MT_object_constraints")
layout.menu("VIEW3D_MT_object_track")
layout.menu("VIEW3D_MT_object_animation")
layout.separator()
layout.menu("VIEW3D_MT_object_showhide")
layout.separator()
layout.operator_menu_enum("object.convert", "target")
# ********** Add Menu **********
class VIEW3D_MT_AddMenu(Menu):
bl_label = "Add Object"
def draw(self, context):
layout = self.layout
layout.operator_context = 'EXEC_REGION_WIN'
layout.menu("VIEW3D_MT_mesh_add", text="Add Mesh",
icon='OUTLINER_OB_MESH')
layout.menu("VIEW3D_MT_curve_add", text="Add Curve",
icon='OUTLINER_OB_CURVE')
layout.menu("VIEW3D_MT_surface_add", text="Add Surface",
icon='OUTLINER_OB_SURFACE')
layout.operator_menu_enum("object.metaball_add", "type",
icon='OUTLINER_OB_META')
layout.operator("object.text_add", text="Add Text",
icon='OUTLINER_OB_FONT')
layout.operator_menu_enum("object.gpencil_add", "type", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
layout.separator()
layout.menu("VIEW3D_MT_armature_add", text="Add Armature",
icon='OUTLINER_OB_ARMATURE')
layout.operator("object.add", text="Lattice",
icon='OUTLINER_OB_LATTICE').type = 'LATTICE'
layout.menu("VIEW3D_MT_object_constraints")
layout.menu("VIEW3D_MT_object_track")
layout.separator()
layout.operator_menu_enum("object.empty_add", "type", text="Empty", icon='OUTLINER_OB_EMPTY')
layout.menu("VIEW3D_MT_image_add", text="Image", icon='OUTLINER_OB_IMAGE')
layout.menu("VIEW3D_MT_object_rigid_body")
layout.menu("VIEW3D_MT_object_quick_effects")
layout.separator()
layout.operator_menu_enum("object.light_add", "type",
icon="OUTLINER_OB_LIGHT")
layout.menu("VIEW3D_MT_lightprobe_add", icon='OUTLINER_OB_LIGHTPROBE')
layout.separator()
layout.operator("object.camera_add", text="Camera",
icon='OUTLINER_OB_CAMERA')
layout.operator("view3d.copybuffer", text="Copy Objects", icon='COPYDOWN')
layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN')
layout.separator()
layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
layout.separator()
layout.operator_menu_enum("object.effector_add", "type",
text="Force Field",
icon='FORCE_FORCE')
layout.menu("VIEW3D_MT_object_quick_effects", text="Quick Effects", icon='PARTICLES')
layout.separator()
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:
col.operator_menu_enum(
"object.collection_instance_add",
"collection",
text="Collection Instance",
icon='OUTLINER_OB_GROUP_INSTANCE',
)
# ********** Object Mirror **********
class VIEW3D_MT_MirrorMenu(Menu):
bl_label = "Mirror"
def draw(self, context):
layout = self.layout
layout.operator("transform.mirror", text="Interactive Mirror")
layout.separator()
layout.operator_context = 'INVOKE_REGION_WIN'
props = layout.operator("transform.mirror", text="X Global")
props.constraint_axis = (True, False, False)
props.orient_type = 'GLOBAL'
props = layout.operator("transform.mirror", text="Y Global")
props.constraint_axis = (False, True, False)
props.orient_type = 'GLOBAL'
props = layout.operator("transform.mirror", text="Z Global")
props.constraint_axis = (False, False, True)
props.orient_type = 'GLOBAL'
layout.operator_context = 'EXEC_DEFAULT'
layout.operator("object.delete", text="Delete").use_global = False
layout.operator("object.delete", text="Delete Global").use_global = True
# ********** Object Interactive Mode **********
@ -223,41 +144,6 @@ class VIEW3D_MT_Interactive_Mode_GPencil(Menu):
layout.operator(VIEW3D_OT_SetObjectMode.bl_idname, text="Draw", icon="GREASEPENCIL").mode = "PAINT_GPENCIL"
layout.operator(VIEW3D_OT_SetObjectMode.bl_idname, text="Weight Paint", icon="WPAINT_HLT").mode = "WEIGHT_GPENCIL"
# currently unused
class VIEW3D_MT_Edit_Gpencil(Menu):
bl_label = "GPencil"
def draw(self, context):
toolsettings = context.tool_settings
layout = self.layout
layout.operator("gpencil.brush_paint", text="Sculpt Strokes").wait_for_input = True
layout.prop_menu_enum(toolsettings.gpencil_sculpt, "tool", text="Sculpt Brush")
layout.separator()
layout.menu("VIEW3D_MT_edit_gpencil_transform")
layout.operator("transform.mirror", text="Mirror")
layout.menu("GPENCIL_MT_snap")
layout.separator()
layout.menu("VIEW3D_MT_object_animation") # NOTE: provides keyingset access...
layout.separator()
layout.menu("VIEW3D_MT_edit_gpencil_delete")
layout.operator("gpencil.duplicate_move", text="Duplicate")
layout.separator()
layout.menu("VIEW3D_MT_select_gpencil")
layout.separator()
layout.operator("gpencil.copy", text="Copy")
layout.operator("gpencil.paste", text="Paste")
layout.separator()
layout.prop_menu_enum(toolsettings, "proportional_edit")
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
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
layout.separator()
layout.operator_menu_enum("gpencil.move_to_layer", "layer", text="Move to Layer")
layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...")
# ********** Text Interactive Mode **********
class VIEW3D_OT_Interactive_Mode_Text(Operator):
@ -275,31 +161,6 @@ class VIEW3D_OT_Interactive_Mode_Text(Operator):
return {'FINISHED'}
# ********** Object Parent **********
class VIEW3D_MT_ParentMenu(Menu):
bl_label = "Parent"
def draw(self, context):
layout = self.layout
layout.operator("object.parent_set", text="Set")
layout.operator("object.parent_clear", text="Clear")
# ********** Object Group **********
class VIEW3D_MT_GroupMenu(Menu):
bl_label = "Group"
def draw(self, context):
layout = self.layout
layout.operator("collection.create")
layout.operator("collection.objects_add_active")
layout.separator()
layout.operator("collection.objects_remove")
layout.operator("collection.objects_remove_all")
layout.operator("collection.objects_remove_active")
# ********** Object Camera Options **********
class VIEW3D_MT_Camera_Options(Menu):
bl_label = "Camera"
@ -307,22 +168,12 @@ class VIEW3D_MT_Camera_Options(Menu):
def draw(self, context):
layout = self.layout
layout.operator_context = 'EXEC_REGION_WIN'
layout.operator("object.camera_add", text="Add Camera", icon='OUTLINER_OB_CAMERA')
layout.operator("view3d.object_as_camera", text="Object As Camera", icon='OUTLINER_OB_CAMERA')
class VIEW3D_MT_Object_Data_Link(Menu):
bl_label = "Object Data"
def draw(self, context):
layout = self.layout
layout.operator_menu_enum("object.make_local", "type", text="Make Local...")
layout.menu("VIEW3D_MT_make_single_user")
layout.operator("object.proxy_make", text="Make Proxy...")
layout.operator("object.make_dupli_face")
layout.separator()
layout.operator("object.data_transfer")
layout.operator("object.datalayout_transfer")
layout.operator("object.select_camera", text="Select Camera")
layout.operator("object.camera_add", text="Add Camera")
layout.operator("view3d.view_camera", text="View Camera")
layout.operator("view3d.camera_to_view", text="Camera to View")
layout.operator("view3d.camera_to_view_selected", text="Camera to Selected")
layout.operator("view3d.object_as_camera", text="Object As Camera")
class VIEW3D_MT_Duplicate(Menu):
@ -371,21 +222,51 @@ class VIEW3D_OT_SetObjectMode(Operator):
return {'FINISHED'}
# currently unused
class VIEW3D_MT_Edit_Gpencil(Menu):
bl_label = "GPencil"
def draw(self, context):
toolsettings = context.tool_settings
layout = self.layout
layout.operator("gpencil.brush_paint", text="Sculpt Strokes").wait_for_input = True
layout.prop_menu_enum(toolsettings.gpencil_sculpt, "tool", text="Sculpt Brush")
layout.separator()
layout.menu("VIEW3D_MT_edit_gpencil_transform")
layout.operator("transform.mirror", text="Mirror")
layout.menu("GPENCIL_MT_snap")
layout.separator()
layout.menu("VIEW3D_MT_object_animation") # NOTE: provides keyingset access...
layout.separator()
layout.menu("VIEW3D_MT_edit_gpencil_delete")
layout.operator("gpencil.duplicate_move", text="Duplicate")
layout.separator()
layout.menu("VIEW3D_MT_select_gpencil")
layout.separator()
layout.operator("gpencil.copy", text="Copy")
layout.operator("gpencil.paste", text="Paste")
layout.separator()
layout.prop_menu_enum(toolsettings, "proportional_edit")
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
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
layout.separator()
layout.operator_menu_enum("gpencil.move_to_layer", "layer", text="Move to Layer")
layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...")
# List The Classes #
classes = (
VIEW3D_MT_AddMenu,
VIEW3D_MT_Object,
VIEW3D_MT_MirrorMenu,
VIEW3D_MT_ParentMenu,
VIEW3D_MT_GroupMenu,
VIEW3D_MT_UndoS,
VIEW3D_MT_Camera_Options,
VIEW3D_MT_InteractiveMode,
VIEW3D_MT_InteractiveModeOther,
VIEW3D_OT_SetObjectMode,
VIEW3D_MT_Object_Data_Link,
VIEW3D_MT_Duplicate,
VIEW3D_OT_Interactive_Mode_Text,
VIEW3D_OT_Interactive_Mode_Grease_Pencil,

View File

@ -1,339 +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 #####
# Contributed to by: meta-androcto, JayDez, sim88, sam, lijenstina, mkb, wisaac, CoDEmanX #
import bpy
from bpy.types import (
Operator,
Menu,
)
from bpy.props import (
BoolProperty,
StringProperty,
)
from bl_ui.properties_paint_common import UnifiedPaintPanel
from .object_menus import *
# Brushes Menu's #
# Thanks to CoDEmanX for the code
class VIEW3D_MT_Brush_Selection(Menu):
bl_label = "Brush Tool"
def draw(self, context):
layout = self.layout
settings = UnifiedPaintPanel.paint_settings(context)
# check if brush exists (for instance, in paint mode before adding a slot)
if hasattr(settings, 'brush'):
brush = settings.brush
else:
brush = None
if not brush:
layout.label(text="No Brushes currently available", icon="INFO")
return
if not context.particle_edit_object:
if UseBrushesLists():
flow = layout.column_flow(columns=3)
for brsh in bpy.data.brushes:
if (context.sculpt_object and brsh.use_paint_sculpt):
props = flow.operator("wm.context_set_id", text=brsh.name,
icon_value=layout.icon(brsh))
props.data_path = "tool_settings.sculpt.brush"
props.value = brsh.name
elif (context.image_paint_object and brsh.use_paint_image):
props = flow.operator("wm.context_set_id", text=brsh.name,
icon_value=layout.icon(brsh))
props.data_path = "tool_settings.image_paint.brush"
props.value = brsh.name
elif (context.vertex_paint_object and brsh.use_paint_vertex):
props = flow.operator("wm.context_set_id", text=brsh.name,
icon_value=layout.icon(brsh))
props.data_path = "tool_settings.vertex_paint.brush"
props.value = brsh.name
elif (context.weight_paint_object and brsh.use_paint_weight):
props = flow.operator("wm.context_set_id", text=brsh.name,
icon_value=layout.icon(brsh))
props.data_path = "tool_settings.weight_paint.brush"
props.value = brsh.name
else:
layout.template_ID_preview(settings, "brush", new="brush.add", rows=3, cols=8)
class VIEW3D_MT_Brush_Settings(Menu):
bl_label = "Brush Settings"
def draw(self, context):
layout = self.layout
settings = UnifiedPaintPanel.paint_settings(context)
brush = getattr(settings, "brush", None)
ups = context.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:
layout.prop(ups, "use_unified_color", text="Unified Color")
layout.separator()
if not brush:
layout.label(text="No Brushes currently available", icon="INFO")
return
layout.menu("VIEW3D_MT_brush_paint_modes")
if context.sculpt_object:
sculpt_tool = brush.sculpt_tool
layout.separator()
layout.operator_menu_enum("brush.curve_preset", "shape", text="Curve Preset")
layout.separator()
if sculpt_tool != 'GRAB':
layout.prop_menu_enum(brush, "stroke_method")
if sculpt_tool in {'DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'}:
layout.prop_menu_enum(brush, "direction")
if sculpt_tool == 'LAYER':
layout.prop(brush, "use_persistent")
layout.operator("sculpt.set_persistent_base")
# Sculpt Menu's #
class VIEW3D_MT_Sculpts(Menu):
bl_label = "Sculpt"
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
sculpt = toolsettings.sculpt
layout.prop(sculpt, "use_symmetry_x")
layout.prop(sculpt, "use_symmetry_y")
layout.prop(sculpt, "use_symmetry_z")
layout.separator()
layout.prop(sculpt, "lock_x")
layout.prop(sculpt, "lock_y")
layout.prop(sculpt, "lock_z")
layout.separator()
layout.prop(sculpt, "use_threaded", text="Threaded Sculpt")
layout.prop(sculpt, "show_low_resolution")
layout.prop(sculpt, "use_deform_only")
layout.separator()
layout.prop(sculpt, "show_brush")
class VIEW3D_MT_Hide_Masks(Menu):
bl_label = "Hide/Mask"
def draw(self, context):
layout = self.layout
props = layout.operator("paint.mask_lasso_gesture", text="Lasso Mask")
layout.separator()
props = layout.operator("view3d.select_box", text="Box Mask")
props = layout.operator("paint.hide_show", text="Box Hide")
props.action = 'HIDE'
props.area = 'INSIDE'
props = layout.operator("paint.hide_show", text="Box Show")
props.action = 'SHOW'
props.area = 'INSIDE'
layout.separator()
props = layout.operator("paint.mask_flood_fill", text="Fill Mask")
props.mode = 'VALUE'
props.value = 1
props = layout.operator("paint.mask_flood_fill", text="Clear Mask")
props.mode = 'VALUE'
props.value = 0
layout.operator("paint.mask_flood_fill", text="Invert Mask").mode = 'INVERT'
layout.separator()
props = layout.operator("paint.hide_show", text="Show All", icon="RESTRICT_VIEW_OFF")
props.action = 'SHOW'
props.area = 'ALL'
props = layout.operator("paint.hide_show", text="Hide Masked", icon="RESTRICT_VIEW_ON")
props.area = 'MASKED'
props.action = 'HIDE'
# Sculpt Specials Menu (Thanks to marvin.k.breuer) #
class VIEW3D_MT_Sculpt_Specials(Menu):
bl_label = "Sculpt Specials"
def draw(self, context):
layout = self.layout
settings = context.tool_settings
if context.sculpt_object.use_dynamic_topology_sculpting:
layout.operator("sculpt.dynamic_topology_toggle",
icon='X', text="Disable Dyntopo")
layout.separator()
if (settings.sculpt.detail_type_method == 'CONSTANT'):
layout.prop(settings.sculpt, "constant_detail", text="Const.")
layout.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
else:
layout.prop(settings.sculpt, "detail_size", text="Detail")
layout.separator()
layout.operator("sculpt.symmetrize", icon='ARROW_LEFTRIGHT')
layout.prop(settings.sculpt, "symmetrize_direction", "")
layout.separator()
layout.operator("sculpt.optimize")
if (settings.sculpt.detail_type_method == 'CONSTANT'):
layout.operator("sculpt.detail_flood_fill")
layout.separator()
layout.prop(settings.sculpt, "detail_refine_method", text="")
layout.prop(settings.sculpt, "detail_type_method", text="")
layout.separator()
layout.prop(settings.sculpt, "use_smooth_shading", "Smooth")
else:
layout.operator("sculpt.dynamic_topology_toggle", text="Enable Dyntopo")
# Vertex Color Menu #
class VIEW3D_MT_Vertex_Colors(Menu):
bl_label = "Vertex Colors"
def draw(self, context):
layout = self.layout
layout.operator("paint.vertex_color_set")
layout.separator()
layout.operator("paint.vertex_color_smooth")
layout.operator("paint.vertex_color_dirt")
# Weight Paint Menu #
class VIEW3D_MT_Paint_Weights(Menu):
bl_label = "Weights"
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.separator()
layout.operator("object.vertex_group_normalize_all", text="Normalize All")
layout.operator("object.vertex_group_normalize", text="Normalize")
layout.separator()
layout.operator("object.vertex_group_mirror", text="Mirror")
layout.operator("object.vertex_group_invert", text="Invert")
layout.separator()
layout.operator("object.vertex_group_clean", text="Clean")
layout.operator("object.vertex_group_quantize", text="Quantize")
layout.separator()
layout.operator("object.vertex_group_levels", text="Levels")
layout.operator("object.vertex_group_smooth", text="Smooth")
layout.separator()
props = layout.operator("object.data_transfer", text="Transfer Weights")
props.use_reverse_transfer = True
props.data_type = 'VGROUP_WEIGHTS'
layout.separator()
layout.operator("object.vertex_group_limit_total", text="Limit Total")
layout.operator("object.vertex_group_fix", text="Fix Deforms")
layout.separator()
layout.operator("paint.weight_set")
class VIEW3D_MT_Angle_Control(Menu):
bl_label = "Angle Control"
@classmethod
def poll(cls, context):
settings = UnifiedPaintPanel.paint_settings(context)
if not settings:
return False
brush = settings.brush
tex_slot = brush.texture_slot
return tex_slot.has_texture_angle and tex_slot.has_texture_angle_source
def draw(self, context):
layout = self.layout
settings = UnifiedPaintPanel.paint_settings(context)
brush = settings.brush
sculpt = (context.sculpt_object is not None)
tex_slot = brush.texture_slot
layout.prop(tex_slot, "use_rake", text="Rake")
if brush.brush_capabilities.has_random_texture_angle and tex_slot.has_random_texture_angle:
if sculpt:
if brush.sculpt_capabilities.has_random_texture_angle:
layout.prop(tex_slot, "use_random", text="Random")
else:
layout.prop(tex_slot, "use_random", text="Random")
# List The Classes #
classes = (
VIEW3D_MT_Angle_Control,
VIEW3D_MT_Sculpt_Specials,
VIEW3D_MT_Brush_Settings,
VIEW3D_MT_Brush_Selection,
VIEW3D_MT_Sculpts,
VIEW3D_MT_Hide_Masks,
VIEW3D_MT_Vertex_Colors,
VIEW3D_MT_Paint_Weights,
)
# Register Classes & Hotkeys #
def register():
for cls in classes:
bpy.utils.register_class(cls)
# Unregister Classes & Hotkeys #
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()

View File

@ -1,440 +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 #####
# Contributed to by: meta-androcto, JayDez, sim88, sam, lijenstina, mkb, wisaac, CoDEmanX #
import bpy
from bpy.types import (
Operator,
Menu,
)
from bpy.props import (
BoolProperty,
StringProperty,
)
from bl_ui.properties_paint_common import UnifiedPaintPanel
from .object_menus import *
# Select Menu's #
# Object Select #
class VIEW3D_MT_Select_Object(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.separator()
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_camera", text="Select Active Camera")
layout.operator("object.select_mirror", text="Mirror Selection")
layout.operator("object.select_random", text="Select Random")
layout.separator()
layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
layout.operator_menu_enum("object.select_grouped", "type", text="Select Grouped")
layout.operator_menu_enum("object.select_linked", "type", text="Select Linked")
layout.separator()
layout.menu("VIEW3D_MT_Select_Object_More_Less", text="More/Less")
layout.operator("object.select_pattern", text="Select Pattern...")
class VIEW3D_MT_Select_Object_More_Less(Menu):
bl_label = "Select More/Less"
def draw(self, context):
layout = self.layout
layout.operator("object.select_more", text="More")
layout.operator("object.select_less", text="Less")
layout.separator()
props = layout.operator("object.select_hierarchy", text="Parent")
props.extend = False
props.direction = 'PARENT'
props = layout.operator("object.select_hierarchy", text="Child")
props.extend = False
props.direction = 'CHILD'
layout.separator()
props = layout.operator("object.select_hierarchy", text="Extend Parent")
props.extend = True
props.direction = 'PARENT'
props = layout.operator("object.select_hierarchy", text="Extend Child")
props.extend = True
props.direction = 'CHILD'
# Edit Curve Select #
class VIEW3D_MT_Select_Edit_Curve(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.separator()
layout.operator("curve.select_all").action = 'TOGGLE'
layout.operator("curve.select_all", text="Inverse").action = 'INVERT'
layout.operator("curve.select_nth")
layout.separator()
layout.operator("curve.select_random")
layout.operator("curve.select_linked", text="Select Linked")
layout.operator("curve.select_similar", text="Select Similar")
layout.operator("curve.de_select_first")
layout.operator("curve.de_select_last")
layout.operator("curve.select_next")
layout.operator("curve.select_previous")
layout.separator()
layout.operator("curve.select_more")
layout.operator("curve.select_less")
# Armature Select #
class VIEW3D_MT_SelectArmatureMenu(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("armature.select_all")
layout.operator("armature.select_inverse", text="Inverse")
layout.operator("armature.select_hierarchy",
text="Parent").direction = 'PARENT'
layout.operator("armature.select_hierarchy",
text="Child").direction = 'CHILD'
props = layout.operator("armature.select_hierarchy",
text="Extend Parent")
props.extend = True
props.direction = 'PARENT'
props = layout.operator("armature.select_hierarchy",
text="Extend Child")
props.extend = True
props.direction = 'CHILD'
layout.operator("object.select_pattern", text="Select Pattern...")
class VIEW3D_MT_Select_Edit_Armature(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
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()
layout.operator("armature.select_more", text="More")
layout.operator("armature.select_less", text="Less")
layout.separator()
props = layout.operator("armature.select_hierarchy", text="Parent")
props.extend = False
props.direction = 'PARENT'
props = layout.operator("armature.select_hierarchy", text="Child")
props.extend = False
props.direction = 'CHILD'
layout.separator()
props = layout.operator("armature.select_hierarchy", text="Extend Parent")
props.extend = True
props.direction = 'PARENT'
props = layout.operator("armature.select_hierarchy", text="Extend Child")
props.extend = True
props.direction = 'CHILD'
layout.operator_menu_enum("armature.select_similar", "type", text="Similar")
layout.operator("object.select_pattern", text="Select Pattern...")
class VIEW3D_MT_Select_Pose(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
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.operator("pose.select_constraint_target",
text="Constraint Target")
layout.separator()
layout.operator("pose.select_linked", text="Linked")
layout.operator("pose.select_hierarchy",
text="Parent").direction = 'PARENT'
layout.operator("pose.select_hierarchy",
text="Child").direction = 'CHILD'
props = layout.operator("pose.select_hierarchy", text="Extend Parent")
props.extend = True
props.direction = 'PARENT'
props = layout.operator("pose.select_hierarchy", text="Extend Child")
props.extend = True
props.direction = 'CHILD'
layout.operator_menu_enum("pose.select_grouped", "type",
text="Grouped")
layout.separator()
layout.operator("object.select_pattern", text="Select Pattern...")
layout.menu("VIEW3D_MT_select_pose_more_less")
class VIEW3D_MT_Select_Pose_More_Less(Menu):
bl_label = "Select More/Less"
def draw(self, context):
layout = self.layout
props = layout.operator("pose.select_hierarchy", text="Parent")
props.extend = False
props.direction = 'PARENT'
props = layout.operator("pose.select_hierarchy", text="Child")
props.extend = False
props.direction = 'CHILD'
props = layout.operator("pose.select_hierarchy", text="Extend Parent")
props.extend = True
props.direction = 'PARENT'
props = layout.operator("pose.select_hierarchy", text="Extend Child")
props.extend = True
props.direction = 'CHILD'
# Surface Select #
class VIEW3D_MT_Select_Edit_Surface(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.separator()
layout.operator("curve.select_all").action = 'TOGGLE'
layout.operator("curve.select_all", text="Inverse").action = 'INVERT'
layout.operator("curve.select_random")
layout.operator("curve.select_nth")
layout.operator("curve.select_linked", text="Select Linked")
layout.operator("curve.select_similar", text="Select Similar")
layout.operator("curve.select_row")
layout.separator()
layout.operator("curve.select_more")
layout.operator("curve.select_less")
# Metaball Select #
class VIEW3D_MT_SelectMetaball(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.separator()
layout.operator("mball.select_all").action = 'TOGGLE'
layout.operator("mball.select_all").action = 'INVERT'
layout.operator("mball.select_random_metaelems")
class VIEW3D_MT_Select_Edit_Metaball(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.operator("mball.select_all").action = 'TOGGLE'
layout.operator("mball.select_all", text="Inverse").action = 'INVERT'
layout.operator("mball.select_random_metaelems")
layout.operator_menu_enum("mball.select_similar", "type", text="Similar")
# Particle Select #
class VIEW3D_MT_Selection_Mode_Particle(Menu):
bl_label = "Particle Select and Display Mode"
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
layout.prop(toolsettings.particle_edit, "select_mode", expand=True)
class VIEW3D_MT_Select_Particle(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
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()
layout.operator("particle.select_more")
layout.operator("particle.select_less")
layout.separator()
layout.operator("particle.select_random")
layout.separator()
layout.operator("particle.select_roots", text="Roots")
layout.operator("particle.select_tips", text="Tips")
# Lattice Edit Select #
class VIEW3D_MT_Select_Edit_Lattice(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.separator()
layout.operator("lattice.select_mirror")
layout.operator("lattice.select_random")
layout.operator("lattice.select_all").action = 'TOGGLE'
layout.operator("lattice.select_all", text="Inverse").action = 'INVERT'
layout.separator()
layout.operator("lattice.select_ungrouped", text="Ungrouped Verts")
# Grease Pencil Select #
class VIEW3D_MT_Select_Gpencil(Menu):
# To Do: used in 3dview header might work if mapped to mouse
# Not in Class List yet
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("gpencil.select_box")
layout.operator("gpencil.select_circle")
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_linked", text="Linked")
# layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
layout.operator("gpencil.select_grouped", text="Grouped")
layout.separator()
layout.operator("gpencil.select_more")
layout.operator("gpencil.select_less")
# Text Select #
class VIEW3D_MT_Select_Edit_Text(Menu):
# To Do: used in 3dview header might work if mapped to mouse
# Not in Class List yet
bl_label = "Edit"
def draw(self, context):
layout = self.layout
layout.operator("font.text_copy", text="Copy")
layout.operator("font.text_cut", text="Cut")
layout.operator("font.text_paste", text="Paste")
layout.operator("font.text_paste_from_file")
layout.operator("font.select_all")
# Paint Mode Menus #
class VIEW3D_MT_Select_Paint_Mask(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.operator("paint.face_select_all").action = 'TOGGLE'
layout.operator("paint.face_select_all", text="Inverse").action = 'INVERT'
layout.operator("paint.face_select_linked", text="Linked")
class VIEW3D_MT_Select_Paint_Mask_Vertex(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
layout.operator("view3d.select_box")
layout.operator("view3d.select_circle")
layout.operator("paint.vert_select_all").action = 'TOGGLE'
layout.operator("paint.vert_select_all", text="Inverse").action = 'INVERT'
layout.operator("paint.vert_select_ungrouped", text="Ungrouped Verts")
# List The Classes #
classes = (
VIEW3D_MT_Select_Object,
VIEW3D_MT_Select_Object_More_Less,
VIEW3D_MT_Select_Edit_Curve,
VIEW3D_MT_SelectArmatureMenu,
VIEW3D_MT_Select_Edit_Armature,
VIEW3D_MT_Select_Pose,
VIEW3D_MT_Select_Pose_More_Less,
VIEW3D_MT_Select_Edit_Surface,
VIEW3D_MT_SelectMetaball,
VIEW3D_MT_Select_Edit_Metaball,
VIEW3D_MT_Select_Particle,
VIEW3D_MT_Select_Edit_Lattice,
VIEW3D_MT_Select_Paint_Mask,
VIEW3D_MT_Select_Paint_Mask_Vertex,
VIEW3D_MT_Selection_Mode_Particle,
VIEW3D_MT_Select_Gpencil,
VIEW3D_MT_Select_Edit_Text,
)
# Register Classes & Hotkeys #
def register():
for cls in classes:
bpy.utils.register_class(cls)
# Unregister Classes & Hotkeys #
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()

View File

@ -20,114 +20,114 @@
import bpy
from bpy.types import (
Operator,
Menu,
)
Operator,
Menu,
)
from bpy.props import (
BoolProperty,
StringProperty,
)
BoolProperty,
StringProperty,
)
from .object_menus import *
# ********** Object Snap Cursor **********
class VIEW3D_MT_Snap_Context(Menu):
bl_label = "Snapping"
bl_label = "Snapping"
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
layout.prop(toolsettings, "use_snap")
layout.prop(toolsettings, "snap_elements", expand=True)
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
layout.prop(toolsettings, "use_snap")
layout.prop(toolsettings, "snap_elements", expand=True)
class VIEW3D_MT_Snap_Origin(Menu):
bl_label = "Snap Origin"
bl_label = "Snap Origin"
def draw(self, context):
layout = self.layout
layout.operator_context = 'EXEC_AREA'
layout.operator("object.origin_set",
text="Geometry to Origin").type = 'GEOMETRY_ORIGIN'
layout.separator()
layout.operator("object.origin_set",
text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
layout.operator("object.origin_set",
text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
layout.operator("object.origin_set",
text="Origin to Center of Mass").type = 'ORIGIN_CENTER_OF_MASS'
def draw(self, context):
layout = self.layout
layout.operator_context = 'EXEC_AREA'
layout.operator("object.origin_set",
text="Geometry to Origin").type = 'GEOMETRY_ORIGIN'
layout.separator()
layout.operator("object.origin_set",
text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
layout.operator("object.origin_set",
text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
layout.operator("object.origin_set",
text="Origin to Center of Mass").type = 'ORIGIN_CENTER_OF_MASS'
class VIEW3D_MT_CursorMenu(Menu):
bl_label = "Snap"
bl_label = "Snap To"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.menu("VIEW3D_MT_Snap_Origin")
layout.menu("VIEW3D_MT_Snap_Context")
layout.separator()
layout.operator("view3d.snap_cursor_to_selected",
text="Cursor to Selected")
layout.operator("view3d.snap_cursor_to_center",
text="Cursor to World Origin")
layout.operator("view3d.snap_cursor_to_grid",
text="Cursor to Grid")
layout.operator("view3d.snap_cursor_to_active",
text="Cursor to Active")
layout.separator()
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor").use_offset = False
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor (Keep Offset)").use_offset = True
layout.operator("view3d.snap_selected_to_grid",
text="Selection to Grid")
layout.operator("view3d.snap_cursor_selected_to_center",
text="Selection and Cursor to World Origin")
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.menu("VIEW3D_MT_Snap_Origin")
layout.menu("VIEW3D_MT_Snap_Context")
layout.separator()
layout.operator("view3d.snap_cursor_to_selected",
text="Cursor to Selected")
layout.operator("view3d.snap_cursor_to_center",
text="Cursor to World Origin")
layout.operator("view3d.snap_cursor_to_grid",
text="Cursor to Grid")
layout.operator("view3d.snap_cursor_to_active",
text="Cursor to Active")
layout.separator()
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor").use_offset = False
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor (Keep Offset)").use_offset = True
layout.operator("view3d.snap_selected_to_grid",
text="Selection to Grid")
layout.operator("view3d.snap_cursor_selected_to_center",
text="Selection and Cursor to World Origin")
class VIEW3D_MT_CursorMenuLite(Menu):
bl_label = "Snap Cursor"
bl_label = "Snap to"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.menu("VIEW3D_MT_Snap_Origin")
layout.separator()
layout.operator("view3d.snap_cursor_to_selected",
text="Cursor to Selected")
layout.operator("view3d.snap_cursor_to_center",
text="Cursor to World Origin")
layout.operator("view3d.snap_cursor_to_grid",
text="Cursor to Grid")
layout.operator("view3d.snap_cursor_to_active",
text="Cursor to Active")
layout.separator()
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor").use_offset = False
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor (Keep Offset)").use_offset = True
layout.operator("view3d.snap_selected_to_grid",
text="Selection to Grid")
layout.operator("view3d.snap_cursor_selected_to_center",
text="Selection and Cursor to World Origin")
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.menu("VIEW3D_MT_Snap_Origin")
layout.separator()
layout.operator("view3d.snap_cursor_to_selected",
text="Cursor to Selected")
layout.operator("view3d.snap_cursor_to_center",
text="Cursor to World Origin")
layout.operator("view3d.snap_cursor_to_grid",
text="Cursor to Grid")
layout.operator("view3d.snap_cursor_to_active",
text="Cursor to Active")
layout.separator()
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor").use_offset = False
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor (Keep Offset)").use_offset = True
layout.operator("view3d.snap_selected_to_grid",
text="Selection to Grid")
layout.operator("view3d.snap_cursor_selected_to_center",
text="Selection and Cursor to World Origin")
# Code thanks to Isaac Weaver (wisaac) D1963
class VIEW3D_OT_SnapCursSelToCenter(Operator):
bl_idname = "view3d.snap_cursor_selected_to_center"
bl_label = "Snap Cursor & Selection to World Origin"
bl_description = ("Snap 3D cursor and selected objects to the center \n"
"Works only in Object Mode")
bl_idname = "view3d.snap_cursor_selected_to_center"
bl_label = "Snap Cursor & Selection to World Origin"
bl_description = ("Snap 3D cursor and selected objects to the center \n"
"Works only in Object Mode")
@classmethod
def poll(cls, context):
return (context.area.type == "VIEW_3D" and context.mode == "OBJECT")
@classmethod
def poll(cls, context):
return (context.area.type == "VIEW_3D" and context.mode == "OBJECT")
def execute(self, context):
context.scene.cursor.location = (0, 0, 0)
for obj in context.selected_objects:
obj.location = (0, 0, 0)
return {'FINISHED'}
def execute(self, context):
context.scene.cursor.location = (0, 0, 0)
for obj in context.selected_objects:
obj.location = (0, 0, 0)
return {'FINISHED'}
# Cursor Edge Intersection Defs #
@ -239,32 +239,64 @@ class VIEW3D_OT_SetOriginToSelected(Operator):
return {'FINISHED'}
# ********** Edit Mesh Cursor **********
class VIEW3D_MT_EditCursorMenu(Menu):
bl_label = "Snap To"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("object.setorigintoselected",
text="Origin to Selected V/F/E")
layout.separator()
layout.menu("VIEW3D_MT_Snap_Origin")
layout.menu("VIEW3D_MT_Snap_Context")
layout.separator()
layout.operator("view3d.snap_cursor_to_selected",
text="Cursor to Selected")
layout.operator("view3d.snap_cursor_to_center",
text="Cursor to World Origin")
layout.operator("view3d.snap_cursor_to_grid",
text="Cursor to Grid")
layout.operator("view3d.snap_cursor_to_active",
text="Cursor to Active")
layout.operator("view3d.snap_cursor_to_edge_intersection",
text="Cursor to Edge Intersection")
layout.separator()
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor").use_offset = False
layout.operator("view3d.snap_selected_to_cursor",
text="Selection to Cursor (Keep Offset)").use_offset = True
layout.operator("view3d.snap_selected_to_grid",
text="Selection to Grid")
# List The Classes #
classes = (
VIEW3D_MT_CursorMenu,
VIEW3D_MT_CursorMenuLite,
VIEW3D_MT_Snap_Context,
VIEW3D_MT_Snap_Origin,
VIEW3D_OT_SnapCursSelToCenter,
VIEW3D_OT_CursorToEdgeIntersection,
VIEW3D_OT_SetOriginToSelected,
VIEW3D_MT_CursorMenu,
VIEW3D_MT_CursorMenuLite,
VIEW3D_MT_Snap_Context,
VIEW3D_MT_Snap_Origin,
VIEW3D_OT_SnapCursSelToCenter,
VIEW3D_OT_CursorToEdgeIntersection,
VIEW3D_OT_SetOriginToSelected,
VIEW3D_MT_EditCursorMenu,
)
# Register Classes & Hotkeys #
def register():
for cls in classes:
bpy.utils.register_class(cls)
for cls in classes:
bpy.utils.register_class(cls)
# Unregister Classes & Hotkeys #
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()
register()

View File

@ -74,7 +74,11 @@ class VIEW3D_MT_TransformMenuLite(Menu):
layout.separator()
layout.operator("transform.transform",
text="Align to Transform Orientation").mode = 'ALIGN'
layout.separator()
layout.operator("object.align")
layout.operator_context = 'EXEC_REGION_WIN'
layout.operator("transform.transform",
text="Align to Transform Orientation").mode = 'ALIGN'
# ********** Transform Camera **********
class VIEW3D_MT_TransformMenuCamera(Menu):
@ -118,61 +122,11 @@ class VIEW3D_MT_TransformMenuArmature(Menu):
text="Origin to Center of Mass").type = 'ORIGIN_CENTER_OF_MASS'
# ********** Transform Armature Edit **********
class VIEW3D_MT_TransformMenuArmatureEdit(Menu):
bl_label = "Transform"
def draw(self, context):
layout = self.layout
layout.operator("transform.translate", text="Move")
layout.operator("transform.rotate", text="Rotate")
layout.operator("transform.resize", text="Scale")
layout.separator()
layout.operator("transform.tosphere", text="To Sphere")
layout.operator("transform.shear", text="Shear")
layout.operator("transform.bend", text="Bend")
layout.operator("transform.push_pull", text="Push/Pull")
layout.operator("transform.vertex_warp", text="Warp")
layout.separator()
layout.operator("transform.vertex_random", text="Randomize")
layout.operator("armature.align")
layout.operator_context = 'EXEC_AREA'
# ********** Transform Armature Pose **********
class VIEW3D_MT_TransformMenuArmaturePose(Menu):
bl_label = "Transform"
def draw(self, context):
layout = self.layout
layout.operator("transform.translate", text="Move")
layout.operator("transform.rotate", text="Rotate")
layout.operator("transform.resize", text="Scale")
layout.separator()
layout.operator("pose.transforms_clear", text="Clear All")
layout.operator("pose.loc_clear", text="Location")
layout.operator("pose.rot_clear", text="Rotation")
layout.operator("pose.scale_clear", text="Scale")
layout.separator()
layout.operator("pose.user_transforms_clear", text="Reset unkeyed")
obj = context.object
if obj.type == 'ARMATURE' and obj.mode in {'EDIT', 'POSE'}:
if obj.data.display_type == 'BBONE':
layout.operator("transform.transform", text="Scale BBone").mode = 'BONE_SIZE'
elif obj.data.display_type == 'ENVELOPE':
layout.operator("transform.transform", text="Scale Envelope Distance").mode = 'BONE_SIZE'
layout.operator("transform.transform", text="Scale Radius").mode = 'BONE_ENVELOPE'
# List The Classes #
classes = (
VIEW3D_MT_TransformMenu,
VIEW3D_MT_TransformMenuArmature,
VIEW3D_MT_TransformMenuArmatureEdit,
VIEW3D_MT_TransformMenuArmaturePose,
VIEW3D_MT_TransformMenuLite,
VIEW3D_MT_TransformMenuCamera,
)

View File

@ -28,8 +28,46 @@ from bpy.props import (
StringProperty,
)
from . edit_mesh import *
# View Menu's #
class VIEW3D_MT_View_Menu(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
view = context.space_data
layout.menu("VIEW3D_MT_view_viewpoint")
layout.menu("VIEW3D_MT_view_align")
layout.menu("VIEW3D_MT_view_navigation")
layout.menu("INFO_MT_area")
layout.operator_context = 'INVOKE_REGION_WIN'
layout.menu("VIEW3D_MT_view_regions", text="View Regions")
layout.menu("VIEW3D_MT_Shade")
layout.separator()
layout.operator("view3d.view_selected", text="Frame Selected").use_all_regions = False
if view.region_quadviews:
layout.operator("view3d.view_selected", text="Frame Selected (Quad View)").use_all_regions = True
layout.operator("view3d.view_all", text="Frame All").center = False
layout.separator()
layout.operator("view3d.view_persportho", text="Perspective/Orthographic")
layout.menu("VIEW3D_MT_view_local")
layout.separator()
layout.operator("render.opengl", text="Viewport Render Image", icon='RENDER_STILL')
layout.operator("render.opengl", text="Viewport Render Animation", icon='RENDER_ANIMATION').animation = True
layout.separator()
layout.prop(view, "show_region_toolbar")
layout.prop(view, "show_region_ui")
layout.prop(view, "show_region_tool_header")
layout.prop(view, "show_region_hud")
# Display Wire (Thanks to marvin.k.breuer) #
class VIEW3D_OT_Display_Wire_All(Operator):
bl_label = "Wire on All Objects"
@ -81,9 +119,6 @@ class VIEW3D_MT_Shade(Menu):
layout.separator()
layout.operator("view3d.display_wire_all", text="Wire all", icon='SHADING_WIRE')
layout.separator()
layout.prop(context.space_data.fx_settings, "use_ssao",
text="Ambient Occlusion", icon="GROUP")
# layout.prop(context.space_data, "use_matcap", icon="MATCAP_01")
# if context.space_data.use_matcap:
@ -100,6 +135,7 @@ def menu_func(self, context):
classes = (
VIEW3D_MT_Shade,
VIEW3D_OT_Display_Wire_All,
VIEW3D_MT_View_Menu
)
@ -108,14 +144,12 @@ def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.VIEW3D_MT_view.append(menu_func)
# Unregister Classes & Hotkeys #
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
bpy.types.VIEW3D_MT_view.remove(menu_func)
if __name__ == "__main__":
register()