Skip to content

Commit

Permalink
Checker Map fixes
Browse files Browse the repository at this point in the history
Fix #44
Original Materials are now restored when cycling Checker Maps from a dictionary stored in utilities_texel; this means, to not lose the original material assignations: MATERIALS SHOULD BE RESTORED BEFORE EXITING BLENDER / CHANGING THE BLEND FILE BEING EDITED.
The original materials won't be lost in any case, they will be marked as Fake Users while renamed with the prefix "backup_". Before, using this tool straigh deleted them and the materials slots, making imposible to reasign new materials easily in a multi-material object.
Checker Maps operates in both EDIT and OBJECT modes for multiple objects without issues.
The UV Editor back image won't be replaced by the "checker_map_gravity" map anymore.
Some cleanup in utilities_bake
  • Loading branch information
franMarz authored Dec 15, 2020
1 parent b187264 commit 767de25
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 38 deletions.
58 changes: 24 additions & 34 deletions op_texel_checker_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
texture_modes = ['UV_GRID','COLOR_GRID','GRAVITY','NONE']



class op(bpy.types.Operator):
bl_idname = "uv.textools_texel_checker_map"
bl_label = "Checker Map"
Expand All @@ -34,8 +33,6 @@ def execute(self, context):
return {'FINISHED'}




def assign_checker_map(size_x, size_y):
# Force Object mode
previous_mode = bpy.context.active_object.mode
Expand All @@ -55,7 +52,6 @@ def assign_checker_map(size_x, size_y):
if space.type == 'VIEW_3D':
space.shading.type = 'MATERIAL'


if len(objects) > 0:

# Detect current Checker modes
Expand Down Expand Up @@ -84,6 +80,8 @@ def assign_checker_map(size_x, size_y):
image_sizes_x.append(image.size[0])
if image.size[1] not in image_sizes_y:
image_sizes_y.append(image.size[1])
else:
utilities_texel.store_materials(obj)

mode_count[mode]+=1

Expand All @@ -95,7 +93,6 @@ def assign_checker_map(size_x, size_y):
for key,val in mode_max_count:
print("{} = {}".format(key, val))


# Determine next mode
mode = 'NONE'
if mode_max_count[0][1] == 0:
Expand All @@ -120,16 +117,23 @@ def assign_checker_map(size_x, size_y):
else:
# Next mode
mode = texture_modes[ (index+1)%len(texture_modes) ]


print("Mode: "+mode)

if mode == 'NONE':

if mode == 'UV_GRID':
name = utilities_texel.get_checker_name(mode, size_x, size_y)
image = get_image(name, mode, size_x, size_y)
for obj in objects:
remove_material(obj)
apply_image(obj, image)

elif mode == 'NONE':
utilities_texel.restore_materials(objects)

elif mode == 'GRAVITY':
image = load_image("checker_map_gravity")
for area in bpy.context.screen.areas:
if area.type == 'IMAGE_EDITOR':
editorImage = area.spaces[0].image
image = load_image("checker_map_gravity")
area.spaces[0].image = editorImage
break
for obj in objects:
apply_image(obj, image)

Expand Down Expand Up @@ -159,8 +163,8 @@ def load_image(name):
pathTexture = icons_dir = os.path.join(os.path.dirname(__file__), "resources/{}.png".format(name))
image = bpy.ops.image.open(filepath=pathTexture, relative_path=False)
if "{}.png".format(name) in bpy.data.images:
bpy.data.images["{}.png".format(name)].name = name #remove extension in name
return bpy.data.images[name];
bpy.data.images["{}.png".format(name)].name = name #remove extension in name
return bpy.data.images[name]



Expand All @@ -169,27 +173,11 @@ def get_valid_objects():
objects = []
for obj in bpy.context.selected_objects:
if obj.type == 'MESH' and obj.data.uv_layers:
objects.append(obj)

objects.append(obj)
return objects







def remove_material(obj):
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
obj.select_set( state = True, view_layer = None)
bpy.context.view_layer.objects.active = obj
count = len(obj.material_slots)
for i in range(count):
bpy.ops.object.material_slot_remove()



def apply_image(obj, image):

bpy.ops.object.mode_set(mode='OBJECT')
Expand All @@ -209,7 +197,8 @@ def apply_image(obj, image):

# Assign material
if len(obj.data.materials) > 0:
obj.data.materials[0] = material
for m in range(len(obj.data.materials)):
obj.data.materials[m] = material
else:
obj.data.materials.append(material)

Expand All @@ -233,19 +222,20 @@ def apply_image(obj, image):
links.new(nodo1.outputs['Color'], nodo2.inputs['Base Color'])



def get_image(name, mode, size_x, size_y):
# Image already exists?
if name in bpy.data.images:
# Update texture UV checker mode
bpy.data.images[name].generated_type = mode
return bpy.data.images[name];
return bpy.data.images[name]

# Create new image instead
image = bpy.data.images.new(name, width=size_x, height=size_y)
image.generated_type = mode #UV_GRID or COLOR_GRID
image.generated_width = int(size_x)
image.generated_height = int(size_y)

return image


bpy.utils.register_class(op)
7 changes: 3 additions & 4 deletions utilities_bake.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from . import settings
from . import utilities_color
# from . import op_bake


keywords_low = ['lowpoly','low','lowp','lp','lo','l']
Expand Down Expand Up @@ -132,7 +131,7 @@ def store_materials(obj):
bpy.context.view_layer.objects.active = obj

bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(obj.data);
bm = bmesh.from_edit_mesh(obj.data)

# for each slot backup the material
for s in range(len(obj.material_slots)):
Expand All @@ -157,7 +156,7 @@ def restore_materials():
# Enter edit mode
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(obj.data);
bm = bmesh.from_edit_mesh(obj.data)

# Restore slots
for index in range(len(stored_materials[obj])):
Expand All @@ -177,7 +176,7 @@ def restore_materials():
bpy.ops.object.mode_set(mode='OBJECT')

# Remove material slots if none before
if len(stored_materials[obj]) == 0:
if len(stored_materials[obj]) == 0 :
for i in range(len(obj.material_slots)):
bpy.ops.object.material_slot_remove()

Expand Down
85 changes: 85 additions & 0 deletions utilities_texel.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,88 @@ def get_area_triangle(A,B,C):

# Use abs(s-a) for values that otherwise generate negative values e.g. pinched UV verts, otherwise math domain error
return math.sqrt(s * abs(s-a) * abs(s-b) * abs(s-c))



stored_materials = {}
stored_material_faces = {}
def store_materials_clear():
stored_materials.clear()
stored_material_faces.clear()



def store_materials(obj):
stored_materials[obj] = []
stored_material_faces[obj] = []

# Enter edit mode
bpy.ops.object.select_all(action='DESELECT')
obj.select_set( state = True, view_layer = None)
bpy.context.view_layer.objects.active = obj

bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(obj.data)

# for each slot backup the material
for s in range(len(obj.material_slots)):
slot = obj.material_slots[s]

stored_materials[obj].append(slot.material)
stored_material_faces[obj].append( [face.index for face in bm.faces if face.material_index == s] )

# print("Faces: {}x".format( len(stored_material_faces[obj][-1]) ))

if slot and slot.material:
slot.material.name = "backup_"+slot.material.name
slot.material.use_fake_user = True
print("- Store {} = {}".format(obj.name,slot.material.name))

# Back to object mode
bpy.ops.object.mode_set(mode='OBJECT')



def restore_materials(objs):
if len(objs) == 0 :
return
else:
for obj in objs :
if stored_materials.get(obj) == None :
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
obj.select_set( state = True, view_layer = None)
bpy.context.view_layer.objects.active = obj
count = len(obj.material_slots)
for i in range(count):
bpy.ops.object.material_slot_remove()
objs = [obj for obj in objs if obj in stored_materials]

for obj in objs :
# Enter edit mode
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(obj.data)

# Restore slots
for index in range(len(stored_materials[obj])):
material = stored_materials[obj][index]
faces = stored_material_faces[obj][index]

if material:
material.name = material.name.replace("backup_","")
obj.material_slots[index].material = material
material.use_fake_user = False

# Face material indexies
for face in bm.faces:
if face.index in faces:
face.material_index = index

# Back to object mode
bpy.ops.object.mode_set(mode='OBJECT')

# Remove material slots if none before
if len(stored_materials[obj]) == 0 :
for i in range(len(obj.material_slots)):
bpy.ops.object.material_slot_remove()

0 comments on commit 767de25

Please sign in to comment.