Brushstroke Tools: Initial Version #328
Binary file not shown.
@ -128,6 +128,9 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
|
|||||||
brushstrokes_object.modifiers[mod.name][f'{v.identifier}_use_attribute'] = False
|
brushstrokes_object.modifiers[mod.name][f'{v.identifier}_use_attribute'] = False
|
||||||
brushstrokes_object.modifiers[mod.name][f'{v.identifier}'] = type(brushstrokes_object.modifiers[mod.name][f'{v.identifier}'])(val)
|
brushstrokes_object.modifiers[mod.name][f'{v.identifier}'] = type(brushstrokes_object.modifiers[mod.name][f'{v.identifier}'])(val)
|
||||||
|
|
||||||
|
# transfer modifier info data from preset to brush strokes
|
||||||
|
utils.deep_copy_mod_info(settings.preset_object, brushstrokes_object)
|
||||||
|
|
||||||
# refresh UI
|
# refresh UI
|
||||||
for mod in brushstrokes_object.modifiers:
|
for mod in brushstrokes_object.modifiers:
|
||||||
mod.node_group.interface_update(context)
|
mod.node_group.interface_update(context)
|
||||||
@ -209,8 +212,12 @@ class BSBST_OT_init_preset(bpy.types.Operator):
|
|||||||
mod_info = settings.preset_object.modifier_info.add()
|
mod_info = settings.preset_object.modifier_info.add()
|
||||||
mod_info.name = mod.name
|
mod_info.name = mod.name
|
||||||
|
|
||||||
|
# context link settings
|
||||||
utils.mark_socket_context_type(mod_info, 'Socket_2', 'SURFACE_OBJECT')
|
utils.mark_socket_context_type(mod_info, 'Socket_2', 'SURFACE_OBJECT')
|
||||||
|
|
||||||
|
# ui visibility settings
|
||||||
|
mod_info.hide_ui = True
|
||||||
|
|
||||||
## brushstrokes
|
## brushstrokes
|
||||||
mod = preset_object.modifiers.new('Brushstrokes', 'NODES')
|
mod = preset_object.modifiers.new('Brushstrokes', 'NODES')
|
||||||
mod.node_group = bpy.data.node_groups['.brushstroke_tools.surface_fill']
|
mod.node_group = bpy.data.node_groups['.brushstroke_tools.surface_fill']
|
||||||
@ -220,9 +227,36 @@ class BSBST_OT_init_preset(bpy.types.Operator):
|
|||||||
mod_info = settings.preset_object.modifier_info.add()
|
mod_info = settings.preset_object.modifier_info.add()
|
||||||
mod_info.name = mod.name
|
mod_info.name = mod.name
|
||||||
|
|
||||||
|
# context link settings
|
||||||
utils.mark_socket_context_type(mod_info, 'Socket_2', 'FLOW_OBJECT')
|
utils.mark_socket_context_type(mod_info, 'Socket_2', 'FLOW_OBJECT')
|
||||||
utils.mark_socket_context_type(mod_info, 'Socket_3', 'UVMAP')
|
utils.mark_socket_context_type(mod_info, 'Socket_3', 'UVMAP')
|
||||||
utils.mark_socket_context_type(mod_info, 'Socket_9', 'RANDOM')
|
utils.mark_socket_context_type(mod_info, 'Socket_9', 'RANDOM')
|
||||||
|
utils.mark_socket_context_type(mod_info, 'Socket_60', 'FLOW_OBJECT')
|
||||||
|
|
||||||
|
# ui visibility settings
|
||||||
|
hide_sockets =[
|
||||||
|
'Socket_3',
|
||||||
|
'Socket_8',
|
||||||
|
'Socket_9',
|
||||||
|
'Socket_12',
|
||||||
|
'Socket_15',
|
||||||
|
'Socket_27',
|
||||||
|
'Socket_35',
|
||||||
|
]
|
||||||
|
for s in hide_sockets:
|
||||||
|
utils.mark_socket_hidden(mod_info, s)
|
||||||
|
|
||||||
|
hide_panels = [
|
||||||
|
'Surface',
|
||||||
|
'Flow',
|
||||||
|
'Stroke Culling',
|
||||||
|
'Lighting Influence',
|
||||||
|
'Offset Override',
|
||||||
|
'Debug',
|
||||||
|
]
|
||||||
|
for p in hide_panels:
|
||||||
|
utils.mark_panel_hidden(mod_info, p)
|
||||||
|
|
||||||
|
|
||||||
def init_draw(self, context):
|
def init_draw(self, context):
|
||||||
settings = context.scene.BSBST_settings
|
settings = context.scene.BSBST_settings
|
||||||
|
@ -122,9 +122,11 @@ class BSBST_socket_info(bpy.types.PropertyGroup):
|
|||||||
link_context: bpy.props.BoolProperty(default=False, name='Link to Context')
|
link_context: bpy.props.BoolProperty(default=False, name='Link to Context')
|
||||||
link_context_type: bpy.props.EnumProperty(default=1, name='Link to Context', update=update_link_context_type,
|
link_context_type: bpy.props.EnumProperty(default=1, name='Link to Context', update=update_link_context_type,
|
||||||
items=link_context_type_items)
|
items=link_context_type_items)
|
||||||
|
hide_ui: bpy.props.BoolProperty(default=False)
|
||||||
|
|
||||||
class BSBST_modifier_info(bpy.types.PropertyGroup):
|
class BSBST_modifier_info(bpy.types.PropertyGroup):
|
||||||
name: bpy.props.StringProperty(default='')
|
name: bpy.props.StringProperty(default='')
|
||||||
|
hide_ui: bpy.props.BoolProperty(default=False)
|
||||||
socket_info: bpy.props.CollectionProperty(type=BSBST_socket_info)
|
socket_info: bpy.props.CollectionProperty(type=BSBST_socket_info)
|
||||||
|
|
||||||
class BSBST_context_brushstrokes(bpy.types.PropertyGroup):
|
class BSBST_context_brushstrokes(bpy.types.PropertyGroup):
|
||||||
@ -164,6 +166,7 @@ class BSBST_Settings(bpy.types.PropertyGroup):
|
|||||||
update=update_active_brushstrokes,
|
update=update_active_brushstrokes,
|
||||||
get=get_active_context_brushstrokes_index,
|
get=get_active_context_brushstrokes_index,
|
||||||
set=set_active_context_brushstrokes_index)
|
set=set_active_context_brushstrokes_index)
|
||||||
|
ui_options: bpy.props.BoolProperty(default=False, name='UI Options')
|
||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
BSBST_socket_info,
|
BSBST_socket_info,
|
||||||
|
@ -2,7 +2,7 @@ import bpy
|
|||||||
from . import utils
|
from . import utils
|
||||||
from . import settings as settings_py
|
from . import settings as settings_py
|
||||||
|
|
||||||
def draw_panel_ui_recursive(panel, panel_name, mod, items):
|
def draw_panel_ui_recursive(panel, panel_name, mod, items, display_mode):
|
||||||
|
|
||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
settings = scene.BSBST_settings
|
settings = scene.BSBST_settings
|
||||||
@ -19,15 +19,40 @@ def draw_panel_ui_recursive(panel, panel_name, mod, items):
|
|||||||
|
|
||||||
for k, v in items:
|
for k, v in items:
|
||||||
if type(v) == bpy.types.NodeTreeInterfacePanel:
|
if type(v) == bpy.types.NodeTreeInterfacePanel:
|
||||||
|
|
||||||
|
v_id = f'Panel_{v.index}' # TODO: replace with panel identifier once that is exposed in Blender 4.3
|
||||||
|
|
||||||
|
if not mod_info:
|
||||||
|
continue
|
||||||
|
s = mod_info.socket_info.get(v_id)
|
||||||
|
if not s:
|
||||||
|
continue
|
||||||
|
if display_mode == 0:
|
||||||
|
if s.hide_ui:
|
||||||
|
continue
|
||||||
|
|
||||||
subpanel_header, subpanel = panel.panel(k, default_closed = v.default_closed)
|
subpanel_header, subpanel = panel.panel(k, default_closed = v.default_closed)
|
||||||
subpanel_header.label(text=k)
|
subpanel_header.label(text=k)
|
||||||
draw_panel_ui_recursive(subpanel, k, mod, v.interface_items.items())
|
if display_mode != 0:
|
||||||
|
subpanel_header.prop(s, 'hide_ui', icon_only=True, icon='REMOVE')
|
||||||
|
draw_panel_ui_recursive(subpanel, k, mod, v.interface_items.items(), display_mode)
|
||||||
else:
|
else:
|
||||||
if v.parent.name != panel_name:
|
if v.parent.name != panel_name:
|
||||||
continue
|
continue
|
||||||
if f'{v.identifier}' not in mod.keys():
|
if f'{v.identifier}' not in mod.keys():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if not mod_info:
|
||||||
|
continue
|
||||||
|
|
||||||
|
s = mod_info.socket_info.get(v.identifier)
|
||||||
|
if not s:
|
||||||
|
continue
|
||||||
|
if display_mode == 0:
|
||||||
|
if s.hide_ui:
|
||||||
|
continue
|
||||||
row = panel.row(align=True)
|
row = panel.row(align=True)
|
||||||
|
|
||||||
col = row.column()
|
col = row.column()
|
||||||
input_row = col.row(align=True)
|
input_row = col.row(align=True)
|
||||||
attribute_toggle = False
|
attribute_toggle = False
|
||||||
@ -51,21 +76,17 @@ def draw_panel_ui_recursive(panel, panel_name, mod, items):
|
|||||||
toggle.input_name = v.identifier
|
toggle.input_name = v.identifier
|
||||||
else:
|
else:
|
||||||
input_row.prop(mod, f'["{v.identifier}"]', text=k)
|
input_row.prop(mod, f'["{v.identifier}"]', text=k)
|
||||||
if not mod_info:
|
|
||||||
continue
|
|
||||||
if type(v) in utils.linkable_sockets:
|
if type(v) in utils.linkable_sockets:
|
||||||
s = mod_info.socket_info.get(v.identifier)
|
|
||||||
if not s:
|
|
||||||
continue
|
|
||||||
col.enabled = not s.link_context
|
col.enabled = not s.link_context
|
||||||
if not s:
|
|
||||||
continue
|
|
||||||
icon = settings_py.icon_from_link_type(s.link_context_type)
|
icon = settings_py.icon_from_link_type(s.link_context_type)
|
||||||
row.alignment = 'EXPAND'
|
row.alignment = 'EXPAND'
|
||||||
if s.link_context:
|
if s.link_context:
|
||||||
row.prop(s, 'link_context', text='', icon_value=icon)
|
row.prop(s, 'link_context', text='', icon_value=icon)
|
||||||
else:
|
else:
|
||||||
|
if display_mode == -1:
|
||||||
row.prop(s, 'link_context_type', text='', emboss=True, icon='LINKED', icon_only=True)
|
row.prop(s, 'link_context_type', text='', emboss=True, icon='LINKED', icon_only=True)
|
||||||
|
if display_mode != 0:
|
||||||
|
row.prop(s, 'hide_ui', icon_only=True, icon='REMOVE')
|
||||||
|
|
||||||
class BSBST_UL_brushstroke_objects(bpy.types.UIList):
|
class BSBST_UL_brushstroke_objects(bpy.types.UIList):
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
@ -121,7 +142,7 @@ class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
|
|||||||
new_advanced_panel.label(text='Curve mode does not support drawing on deformed geometry', icon='ERROR')
|
new_advanced_panel.label(text='Curve mode does not support drawing on deformed geometry', icon='ERROR')
|
||||||
|
|
||||||
new_advanced_panel.prop(settings, 'assign_materials')
|
new_advanced_panel.prop(settings, 'assign_materials')
|
||||||
row = new_advanced_panel.row()
|
new_advanced_panel.prop(settings, 'ui_options', icon='OPTIONS')
|
||||||
|
|
||||||
# identify style context
|
# identify style context
|
||||||
style_object = context.object if settings.style_context=='BRUSHSTROKES' else settings.preset_object
|
style_object = context.object if settings.style_context=='BRUSHSTROKES' else settings.preset_object
|
||||||
@ -139,6 +160,10 @@ class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
|
|||||||
|
|
||||||
is_preset = style_object == settings.preset_object
|
is_preset = style_object == settings.preset_object
|
||||||
|
|
||||||
|
display_mode = settings.ui_options
|
||||||
|
if is_preset:
|
||||||
|
display_mode = -1
|
||||||
|
|
||||||
style_header, style_panel = layout.panel("brushstrokes_style", default_closed=False)
|
style_header, style_panel = layout.panel("brushstrokes_style", default_closed=False)
|
||||||
|
|
||||||
if is_preset:
|
if is_preset:
|
||||||
@ -161,15 +186,25 @@ class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
|
|||||||
|
|
||||||
if style_object:
|
if style_object:
|
||||||
for mod in style_object.modifiers:
|
for mod in style_object.modifiers:
|
||||||
|
mod_info = mod.id_data.modifier_info.get(mod.name)
|
||||||
|
if not mod_info:
|
||||||
|
continue
|
||||||
|
if display_mode == 0:
|
||||||
|
if mod_info.hide_ui:
|
||||||
|
continue
|
||||||
|
|
||||||
mod_header, mod_panel = style_panel.panel(mod.name, default_closed = False)
|
mod_header, mod_panel = style_panel.panel(mod.name, default_closed = False)
|
||||||
mod_header.label(text='', icon='GEOMETRY_NODES')
|
row = mod_header.row(align=True)
|
||||||
mod_header.prop(mod, 'name', text='')
|
row.label(text='', icon='GEOMETRY_NODES')
|
||||||
|
row.prop(mod, 'name', text='')
|
||||||
|
|
||||||
if is_preset:
|
if is_preset:
|
||||||
op = mod_header.operator('brushstroke_tools.preset_remove_mod', text='', icon='X')
|
op = row.operator('brushstroke_tools.preset_remove_mod', text='', icon='X')
|
||||||
else:
|
else:
|
||||||
op = mod_header.operator('object.modifier_remove', text='', icon='X')
|
op = row.operator('object.modifier_remove', text='', icon='X')
|
||||||
op.modifier = mod.name
|
op.modifier = mod.name
|
||||||
|
if display_mode != 0:
|
||||||
|
mod_header.prop(mod_info, 'hide_ui', icon_only=True, icon='REMOVE')
|
||||||
|
|
||||||
if not mod_panel:
|
if not mod_panel:
|
||||||
continue
|
continue
|
||||||
@ -184,7 +219,11 @@ class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
|
|||||||
if not mod.node_group:
|
if not mod.node_group:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
draw_panel_ui_recursive(mod_panel, '', mod, mod.node_group.interface.items_tree.items())
|
draw_panel_ui_recursive(mod_panel,
|
||||||
|
'',
|
||||||
|
mod,
|
||||||
|
mod.node_group.interface.items_tree.items(),
|
||||||
|
display_mode)
|
||||||
|
|
||||||
# expose add modifier operator for preset context
|
# expose add modifier operator for preset context
|
||||||
if is_preset:
|
if is_preset:
|
||||||
|
@ -26,21 +26,19 @@ def refresh_preset(dummy):
|
|||||||
if not settings.preset_object:
|
if not settings.preset_object:
|
||||||
return
|
return
|
||||||
for mod in settings.preset_object.modifiers:
|
for mod in settings.preset_object.modifiers:
|
||||||
if not mod.type == 'NODES':
|
|
||||||
continue
|
|
||||||
if not mod.node_group:
|
|
||||||
continue
|
|
||||||
mod_info = settings.preset_object.modifier_info.get(mod.name)
|
mod_info = settings.preset_object.modifier_info.get(mod.name)
|
||||||
if not mod_info:
|
if not mod_info:
|
||||||
mod_info = settings.preset_object.modifier_info.add()
|
mod_info = settings.preset_object.modifier_info.add()
|
||||||
mod_info.name = mod.name
|
mod_info.name = mod.name
|
||||||
for v in mod.node_group.interface.items_tree.values():
|
for v in mod.node_group.interface.items_tree.values():
|
||||||
if not type(v) in linkable_sockets:
|
if type(v) is bpy.types.NodeTreeInterfacePanel:
|
||||||
continue
|
v_id = f'Panel_{v.index}' # TODO: replace with panel identifier once that is exposed in Blender 4.3
|
||||||
if v.identifier in [s.name for s in mod_info.socket_info]:
|
else:
|
||||||
|
v_id = v.identifier
|
||||||
|
if v_id in [s.name for s in mod_info.socket_info]:
|
||||||
continue
|
continue
|
||||||
n = mod_info.socket_info.add()
|
n = mod_info.socket_info.add()
|
||||||
n.name = v.identifier
|
n.name = v_id
|
||||||
# TODO: clean up old settings
|
# TODO: clean up old settings
|
||||||
|
|
||||||
def mark_socket_context_type(mod_info, socket_name, link_type):
|
def mark_socket_context_type(mod_info, socket_name, link_type):
|
||||||
@ -50,6 +48,37 @@ def mark_socket_context_type(mod_info, socket_name, link_type):
|
|||||||
socket_info.name = socket_name
|
socket_info.name = socket_name
|
||||||
socket_info.link_context_type = link_type
|
socket_info.link_context_type = link_type
|
||||||
|
|
||||||
|
def mark_socket_hidden(mod_info, socket_name, hide=True):
|
||||||
|
socket_info = mod_info.socket_info.get(socket_name)
|
||||||
|
if not socket_info:
|
||||||
|
socket_info = mod_info.socket_info.add()
|
||||||
|
socket_info.name = socket_name
|
||||||
|
socket_info.hide_ui = hide
|
||||||
|
|
||||||
|
def mark_panel_hidden(mod_info, panel_name, hide=True):
|
||||||
|
mod = mod_info.id_data.modifiers.get(mod_info.name)
|
||||||
|
if not mod:
|
||||||
|
return
|
||||||
|
if not mod.type == 'NODES':
|
||||||
|
return
|
||||||
|
ng = mod.node_group
|
||||||
|
if not ng:
|
||||||
|
return
|
||||||
|
v_id = ''
|
||||||
|
for k, v in ng.interface.items_tree.items():
|
||||||
|
if type(v) != bpy.types.NodeTreeInterfacePanel:
|
||||||
|
continue
|
||||||
|
if v.name == panel_name:
|
||||||
|
v_id = f'Panel_{v.index}'
|
||||||
|
break
|
||||||
|
if not v_id:
|
||||||
|
return
|
||||||
|
socket_info = mod_info.socket_info.get(v_id)
|
||||||
|
if not socket_info:
|
||||||
|
socket_info = mod_info.socket_info.add()
|
||||||
|
socket_info.name = v_id
|
||||||
|
socket_info.hide_ui = hide
|
||||||
|
|
||||||
def deep_copy_mod_info(source_object, target_object):
|
def deep_copy_mod_info(source_object, target_object):
|
||||||
for mod_info in source_object.modifier_info:
|
for mod_info in source_object.modifier_info:
|
||||||
mod_info_tgt = target_object.modifier_info.add()
|
mod_info_tgt = target_object.modifier_info.add()
|
||||||
|
Loading…
Reference in New Issue
Block a user