Skip to content

Commit

Permalink
Implement uniform scale for layer and mask UVs (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
passivestar authored Oct 11, 2024
1 parent e1ae95b commit 8ade49a
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 13 deletions.
24 changes: 23 additions & 1 deletion Layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def add_new_layer(group_tree, layer_name, layer_type, channel_idx,
):

yp = group_tree.yp
#ypup = get_user_preferences()
ypup = get_user_preferences()
obj = bpy.context.object
mat = obj.active_material

Expand Down Expand Up @@ -149,6 +149,10 @@ def add_new_layer(group_tree, layer_name, layer_type, channel_idx,
# Tree start and end
create_essential_nodes(tree, True, False, True)

# Uniform Scale
if is_bl_newer_than(2, 81) and is_layer_using_vector(layer):
layer.enable_uniform_scale = ypup.enable_uniform_uv_scale_by_default

# Add source
if layer_type == 'VCOL':
source = new_node(tree, layer, 'source', get_vcol_bl_idname(), 'Source')
Expand Down Expand Up @@ -5971,6 +5975,15 @@ def update_layer_blur_vector_factor(self, context):
if blur_vector:
blur_vector.inputs[0].default_value = layer.blur_vector_factor

def update_layer_uniform_scale_enabled(self, context):
if not hasattr(context, 'layer'): return

update_entity_uniform_scale_enabled(self)

check_layer_tree_ios(context.layer)
reconnect_layer_nodes(context.layer)
rearrange_layer_nodes(context.layer)

class YLayer(bpy.types.PropertyGroup):
name : StringProperty(
name = 'Layer Name',
Expand Down Expand Up @@ -6185,6 +6198,15 @@ class YLayer(bpy.types.PropertyGroup):
texcoord : StringProperty(default='')
blur_vector : StringProperty(default='')

enable_uniform_scale : BoolProperty(
name = 'Enable Uniform Scale',
description = 'Use the same value for all scale components',
default = False,
update = update_layer_uniform_scale_enabled
)

uniform_scale_value : FloatProperty(default=1)

decal_process : StringProperty(default='')

#need_temp_uv_refresh : BoolProperty(default=False)
Expand Down
25 changes: 24 additions & 1 deletion Mask.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
def add_new_mask(layer, name, mask_type, texcoord_type, uv_name, image = None, vcol = None, segment=None, object_index=0, blend_type='MULTIPLY', hemi_space='WORLD', hemi_use_prev_normal=False, color_id=(1,0,1), source_input='RGB', edge_detect_radius=0.05, modifier_type='INVERT', interpolation='Linear'):
yp = layer.id_data.yp
yp.halt_update = True
ypup = get_user_preferences()

tree = get_tree(layer)
nodes = tree.nodes
Expand All @@ -24,6 +25,10 @@ def add_new_mask(layer, name, mask_type, texcoord_type, uv_name, image = None, v
mask.texcoord_type = texcoord_type
mask.source_input = source_input

# Uniform Scale
if is_bl_newer_than(2, 81) and is_mask_using_vector(mask):
mask.enable_uniform_scale = ypup.enable_uniform_uv_scale_by_default

if segment:
mask.segment_name = segment.name

Expand Down Expand Up @@ -403,7 +408,7 @@ def invoke(self, context, event):
elif layer.type == 'IMAGE':
source = get_layer_source(layer)
if source and source.image: self.interpolation = source.interpolation

if get_user_preferences().skip_property_popups and not event.shift:
return self.execute(context)

Expand Down Expand Up @@ -1735,6 +1740,15 @@ class YLayerMaskChannel(bpy.types.PropertyGroup):
# UI related
expand_content : BoolProperty(default=False)

def update_mask_uniform_scale_enabled(self, context):
if not hasattr(context, 'layer'): return

update_entity_uniform_scale_enabled(self)

check_layer_tree_ios(context.layer)
reconnect_layer_nodes(context.layer)
rearrange_layer_nodes(context.layer)

class YLayerMask(bpy.types.PropertyGroup):

name : StringProperty(default='', update=update_mask_name)
Expand Down Expand Up @@ -1944,6 +1958,15 @@ class YLayerMask(bpy.types.PropertyGroup):
baked_mapping : StringProperty(default='')
blur_vector : StringProperty(default='')

enable_uniform_scale : BoolProperty(
name = 'Enable Uniform Scale',
description = 'Use the same value for all scale components',
default = False,
update = update_mask_uniform_scale_enabled
)

uniform_scale_value : FloatProperty(default=1)

decal_process : StringProperty(default='')
texcoord : StringProperty(default='')
decal_alpha : StringProperty(default='')
Expand Down
11 changes: 11 additions & 0 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2167,6 +2167,17 @@ def get_entity_mapping(entity, get_baked=False):

return None

def update_entity_uniform_scale_enabled(entity):
scale_input = get_entity_mapping(entity).inputs[3]

if entity.enable_uniform_scale:
# Set the uniform scale to min axis of regular scale when uniform scale is enabled
set_entity_prop_value(entity, 'uniform_scale_value', min(map(abs, scale_input.default_value)))
else:
# Set the regular scale axes to the uniform scale when uniform scale is disabled
scale = get_entity_prop_value(entity, 'uniform_scale_value')
scale_input.default_value = (scale, scale, scale)

def get_neighbor_uv_space_input(texcoord_type):
if texcoord_type == 'UV':
return 0.0 # Tangent Space
Expand Down
8 changes: 8 additions & 0 deletions input_outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,10 @@ def check_layer_tree_ios(layer, tree=None, remove_props=False, hard_reset=False)
dirty = create_prop_input(layer, 'decal_distance_value', valid_inputs, input_index, dirty)
input_index += 1

if is_bl_newer_than(2, 81) and layer.enable_uniform_scale and is_layer_using_vector(layer):
dirty = create_prop_input(layer, 'uniform_scale_value', valid_inputs, input_index, dirty)
input_index += 1

# Channel prop inputs
for i, ch in enumerate(layer.channels):
if not get_channel_enabled(ch): continue
Expand Down Expand Up @@ -960,6 +964,10 @@ def check_layer_tree_ios(layer, tree=None, remove_props=False, hard_reset=False)
dirty = create_prop_input(mask, 'intensity_value', valid_inputs, input_index, dirty)
input_index += 1

if is_bl_newer_than(2, 81) and mask.enable_uniform_scale and is_mask_using_vector(mask):
dirty = create_prop_input(mask, 'uniform_scale_value', valid_inputs, input_index, dirty)
input_index += 1

# Mask blur vector
if mask.enable_blur_vector:
dirty = create_prop_input(mask, 'blur_vector_factor', valid_inputs, input_index, dirty)
Expand Down
18 changes: 18 additions & 0 deletions node_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,15 @@ def reconnect_layer_nodes(layer, ch_idx=-1, merge_mask=False):

if vector and mapping and layer.texcoord_type != 'Decal':
vector = create_link(tree, vector, mapping.inputs[0])[0]

# Layer UV uniform scale value
if is_bl_newer_than(2, 81):
uniform_scale_value = get_essential_node(tree, TREE_START).get(get_entity_input_name(layer, 'uniform_scale_value'))
if uniform_scale_value:
if layer.enable_uniform_scale:
create_link(tree, uniform_scale_value, mapping.inputs[3])
else:
break_link(tree, uniform_scale_value, mapping.inputs[3])

if vector and layer.type not in {'VCOL', 'BACKGROUND', 'COLOR', 'GROUP', 'HEMI', 'OBJECT_INDEX'}:
create_link(tree, vector, source.inputs[0])
Expand Down Expand Up @@ -2082,6 +2091,15 @@ def reconnect_layer_nodes(layer, ch_idx=-1, merge_mask=False):

create_link(tree, mask_vector, mask_source.inputs[0])

# Mask UV uniform scale value
if is_bl_newer_than(2, 81):
uniform_scale_value = get_essential_node(tree, TREE_START).get(get_entity_input_name(mask, 'uniform_scale_value'))
if uniform_scale_value:
if mask.enable_uniform_scale:
create_link(tree, uniform_scale_value, mask_mapping.inputs[3])
else:
break_link(tree, uniform_scale_value, mask_mapping.inputs[3])

# Mask uv neighbor
mask_uv_neighbor = nodes.get(mask.uv_neighbor) if mask.texcoord_type != 'Layer' else uv_neighbor
if mask_uv_neighbor:
Expand Down
8 changes: 8 additions & 0 deletions preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ class YPaintPreferences(AddonPreferences):
description = "Enable baked outside by default when creating new "+get_addon_title()+" node.\n(Useful for creating game assets)",
default = False
)

enable_uniform_uv_scale_by_default : BoolProperty(
name = 'Enable Uniform UV Scale by default',
description = "Enable uniform UV scale by default in Layer and Mask UVs. This will make all scale axes have the same value",
default = False
)

# Addon updater preferences.
auto_check_update : BoolProperty(
Expand Down Expand Up @@ -139,6 +145,8 @@ def draw(self, context):
self.layout.prop(self, 'use_image_preview')
self.layout.prop(self, 'skip_property_popups')
self.layout.prop(self, 'enable_baked_outside_by_default')
if is_bl_newer_than(2, 81):
self.layout.prop(self, 'enable_uniform_uv_scale_by_default')
self.layout.prop(self, 'show_experimental')
self.layout.prop(self, 'developer_mode')
#self.layout.prop(self, 'parallax_without_baked')
Expand Down
50 changes: 39 additions & 11 deletions ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,14 +571,14 @@ def draw_inbetween_modifier_mask_props(layer, source, layout):
elif layer.modifier_type == 'RAMP':
col.template_color_ramp(source, "color_ramp", expand=True)

def draw_input_prop(layout, entity, prop_name, emboss=None):
def draw_input_prop(layout, entity, prop_name, emboss=None, text=''):
inp = get_entity_prop_input(entity, prop_name)
if emboss != None:
if inp: layout.prop(inp, 'default_value', text='', emboss=emboss)
else: layout.prop(entity, prop_name, text='', emboss=emboss)
if inp: layout.prop(inp, 'default_value', text=text, emboss=emboss)
else: layout.prop(entity, prop_name, text=text, emboss=emboss)
else:
if inp: layout.prop(inp, 'default_value', text='')
else: layout.prop(entity, prop_name, text='')
if inp: layout.prop(inp, 'default_value', text=text)
else: layout.prop(entity, prop_name, text=text)

def draw_mask_modifier_stack(layer, mask, layout, ui):
ypui = bpy.context.window_manager.ypui
Expand Down Expand Up @@ -1476,15 +1476,29 @@ def draw_layer_source(context, layout, layer, layer_tree, source, image, vcol, i
mcol.prop(mapping.inputs[1], 'default_value', text='Offset')
mcol = rrow.column()
mcol.prop(mapping.inputs[2], 'default_value', text='Rotation')
mcol = rrow.column()
mcol.prop(mapping.inputs[3], 'default_value', text='Scale')
if layer.enable_uniform_scale:
mcol = rrow.column(align=True)
mcol.label(text='Scale:')
draw_input_prop(mcol, layer, 'uniform_scale_value', None, 'X')
draw_input_prop(mcol, layer, 'uniform_scale_value', None, 'Y')
draw_input_prop(mcol, layer, 'uniform_scale_value', None, 'Z')
else:
mcol = rrow.column()
mcol.prop(mapping.inputs[3], 'default_value', text='Scale')
else:
mcol = rrow.column()
mcol.prop(mapping, 'translation')
mcol = rrow.column()
mcol.prop(mapping, 'rotation')
mcol = rrow.column()
mcol.prop(mapping, 'scale')

# Uniform scale
if is_bl_newer_than(2, 81):
rrow = boxcol.row(align=True)
splits = split_layout(rrow, 0.5)
splits.label(text='Uniform Scale:')
rrow.prop(layer, 'enable_uniform_scale', text='')

if yp.need_temp_uv_refresh:
rrow = boxcol.row(align=True)
Expand All @@ -1493,7 +1507,7 @@ def draw_layer_source(context, layout, layer, layer_tree, source, image, vcol, i

# Blur row
rrow = boxcol.row(align=True)
splits = split_layout(rrow, 0.3)
splits = split_layout(rrow, 0.5)
splits.label(text='Blur:')
if layer.enable_blur_vector:
draw_input_prop(splits, layer, 'blur_vector_factor')
Expand Down Expand Up @@ -2446,15 +2460,29 @@ def draw_layer_masks(context, layout, layer):
mcol.prop(mapping.inputs[1], 'default_value', text='Offset')
mcol = rrow.column()
mcol.prop(mapping.inputs[2], 'default_value', text='Rotation')
mcol = rrow.column()
mcol.prop(mapping.inputs[3], 'default_value', text='Scale')
if mask.enable_uniform_scale:
mcol = rrow.column(align=True)
mcol.label(text='Scale:')
draw_input_prop(mcol, mask, 'uniform_scale_value', None, 'X')
draw_input_prop(mcol, mask, 'uniform_scale_value', None, 'Y')
draw_input_prop(mcol, mask, 'uniform_scale_value', None, 'Z')
else:
mcol = rrow.column()
mcol.prop(mapping.inputs[3], 'default_value', text='Scale')
else:
mcol = rrow.column()
mcol.prop(mapping, 'translation')
mcol = rrow.column()
mcol.prop(mapping, 'rotation')
mcol = rrow.column()
mcol.prop(mapping, 'scale')

# Uniform scale
if is_bl_newer_than(2, 81):
rrow = boxcol.row(align=True)
splits = split_layout(rrow, 0.5)
splits.label(text='Uniform Scale:')
rrow.prop(mask, 'enable_uniform_scale', text='')

if mask.type == 'IMAGE' and mask.active_edit and (
yp.need_temp_uv_refresh
Expand All @@ -2466,7 +2494,7 @@ def draw_layer_masks(context, layout, layer):
# Blur row
if mask.texcoord_type != 'Layer':
rrow = boxcol.row(align=True)
splits = split_layout(rrow, 0.3)
splits = split_layout(rrow, 0.5)
splits.label(text='Blur:')
if mask.enable_blur_vector:
draw_input_prop(splits, mask, 'blur_vector_factor')
Expand Down

0 comments on commit 8ade49a

Please sign in to comment.