mirror of
https://github.com/drewcassidy/TexTools-Blender
synced 2024-09-01 14:54:44 +00:00
265 lines
8.2 KiB
Python
265 lines
8.2 KiB
Python
import bpy
|
|
import bmesh
|
|
import operator
|
|
from mathutils import Vector
|
|
from collections import defaultdict
|
|
from math import pi
|
|
|
|
from . import utilities_uv
|
|
from . import utilities_ui
|
|
from . import utilities_texel
|
|
|
|
name_texture = "TT_resize_area"
|
|
|
|
|
|
utilities_ui.icon_register("op_extend_canvas_TL_active.png")
|
|
utilities_ui.icon_register("op_extend_canvas_TR_active.png")
|
|
utilities_ui.icon_register("op_extend_canvas_BL_active.png")
|
|
utilities_ui.icon_register("op_extend_canvas_BR_active.png")
|
|
|
|
|
|
def on_dropdown_size_x(self, context):
|
|
self.size_x = int(self.dropdown_size_x)
|
|
# context.area.tag_redraw()
|
|
|
|
|
|
def on_dropdown_size_y(self, context):
|
|
self.size_y = int(self.dropdown_size_y)
|
|
# context.area.tag_redraw()
|
|
|
|
|
|
class op(bpy.types.Operator):
|
|
bl_idname = "uv.textools_uv_resize"
|
|
bl_label = "Resize Area"
|
|
bl_description = "Resize or extend the UV area"
|
|
bl_options = {'REGISTER', 'UNDO'}
|
|
|
|
size_x: bpy.props.IntProperty(
|
|
name="Width",
|
|
description="padding size in pixels",
|
|
default=1024,
|
|
min=1,
|
|
max=8192
|
|
)
|
|
size_y: bpy.props.IntProperty(
|
|
name="Height",
|
|
description="padding size in pixels",
|
|
default=1024,
|
|
min=1,
|
|
max=8192
|
|
)
|
|
dropdown_size_x: bpy.props.EnumProperty(
|
|
items=utilities_ui.size_textures,
|
|
name="",
|
|
update=on_dropdown_size_x,
|
|
default='1024'
|
|
)
|
|
dropdown_size_y: bpy.props.EnumProperty(
|
|
items=utilities_ui.size_textures,
|
|
name="",
|
|
update=on_dropdown_size_y,
|
|
default='1024'
|
|
)
|
|
|
|
direction: bpy.props.EnumProperty(name='direction', items=(
|
|
('TL', ' ', 'Top Left', utilities_ui.icon_get(
|
|
"op_extend_canvas_TL_active"), 0),
|
|
('BL', ' ', 'Bottom Left', utilities_ui.icon_get(
|
|
"op_extend_canvas_BL_active"), 2),
|
|
('TR', ' ', 'Top Right', utilities_ui.icon_get(
|
|
"op_extend_canvas_TR_active"), 1),
|
|
('BR', ' ', 'Bottom Right', utilities_ui.icon_get(
|
|
"op_extend_canvas_BR_active"), 3)
|
|
))
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not bpy.context.active_object:
|
|
return False
|
|
|
|
if bpy.context.active_object.type != 'MESH':
|
|
return False
|
|
|
|
# Only in Edit mode
|
|
if bpy.context.active_object.mode != 'EDIT':
|
|
return False
|
|
|
|
# Only in UV editor mode
|
|
if bpy.context.area.type != 'IMAGE_EDITOR':
|
|
return False
|
|
|
|
# Requires UV map
|
|
if not bpy.context.object.data.uv_layers:
|
|
return False
|
|
|
|
return True
|
|
|
|
def invoke(self, context, event):
|
|
print("Invoke resize area")
|
|
self.size_x = bpy.context.scene.texToolsSettings.size[0]
|
|
self.size_y = bpy.context.scene.texToolsSettings.size[1]
|
|
|
|
for item in utilities_ui.size_textures:
|
|
if int(item[0]) == self.size_x:
|
|
self.dropdown_size_x = item[0]
|
|
break
|
|
for item in utilities_ui.size_textures:
|
|
if int(item[0]) == self.size_y:
|
|
self.dropdown_size_y = item[0]
|
|
break
|
|
|
|
return context.window_manager.invoke_props_dialog(self, width=140)
|
|
|
|
def check(self, context):
|
|
return True
|
|
|
|
def draw(self, context):
|
|
# https://b3d.interplanety.org/en/creating-pop-up-panels-with-user-ui-in-blender-add-on/
|
|
layout = self.layout
|
|
|
|
layout.separator()
|
|
|
|
# New Size
|
|
row = layout.row()
|
|
split = row.split(factor=0.6)
|
|
c = split.column(align=True)
|
|
c.prop(self, "size_x", text="X", expand=True)
|
|
c.prop(self, "size_y", text="Y", expand=True)
|
|
|
|
c = split.column(align=True)
|
|
c.prop(self, "dropdown_size_x", text="")
|
|
c.prop(self, "dropdown_size_y", text="")
|
|
|
|
# Direction
|
|
col = layout.column(align=True)
|
|
col.label(text="Direction")
|
|
row = col.row(align=True)
|
|
row.prop(self, 'direction', expand=True)
|
|
|
|
# Summary
|
|
size_A = "{} x {}".format(
|
|
bpy.context.scene.texToolsSettings.size[0], bpy.context.scene.texToolsSettings.size[1])
|
|
if bpy.context.scene.texToolsSettings.size[0] == bpy.context.scene.texToolsSettings.size[1]:
|
|
size_A = "{}²".format(bpy.context.scene.texToolsSettings.size[0])
|
|
size_B = "{} x {}".format(self.size_x, self.size_y)
|
|
if self.size_x == self.size_y:
|
|
size_B = "{}²".format(self.size_x)
|
|
|
|
layout.label(text="{} to {}".format(
|
|
size_A, size_B
|
|
))
|
|
|
|
layout.separator()
|
|
|
|
def execute(self, context):
|
|
|
|
# Store selection
|
|
utilities_uv.selection_store()
|
|
|
|
# Get start and end size
|
|
size_A = Vector([
|
|
bpy.context.scene.texToolsSettings.size[0],
|
|
bpy.context.scene.texToolsSettings.size[1]
|
|
])
|
|
size_B = Vector([
|
|
self.size_x,
|
|
self.size_y
|
|
])
|
|
|
|
resize_uv(
|
|
self,
|
|
context,
|
|
self.direction,
|
|
size_A,
|
|
size_B
|
|
)
|
|
resize_image(
|
|
context,
|
|
self.direction,
|
|
size_A,
|
|
size_B
|
|
)
|
|
|
|
bpy.context.scene.texToolsSettings.size[0] = self.size_x
|
|
bpy.context.scene.texToolsSettings.size[1] = self.size_y
|
|
|
|
# Restore selection
|
|
utilities_uv.selection_restore()
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
def resize_uv(self, context, mode, size_A, size_B):
|
|
|
|
# Set pivot
|
|
bpy.context.tool_settings.transform_pivot_point = 'CURSOR'
|
|
if mode == 'TL':
|
|
bpy.ops.uv.cursor_set(location=Vector([0, 1]))
|
|
elif mode == 'TR':
|
|
bpy.ops.uv.cursor_set(location=Vector([1, 1]))
|
|
elif mode == 'BL':
|
|
bpy.ops.uv.cursor_set(location=Vector([0, 0]))
|
|
elif mode == 'BR':
|
|
bpy.ops.uv.cursor_set(location=Vector([1, 0]))
|
|
|
|
# Select all UV faces
|
|
bpy.ops.uv.select_all(action='SELECT')
|
|
|
|
# Resize
|
|
scale_x = size_A.x / size_B.x
|
|
scale_y = size_A.y / size_B.y
|
|
bpy.ops.transform.resize(
|
|
value=(scale_x, scale_y, 1.0), use_proportional_edit=False)
|
|
|
|
|
|
def resize_image(context, mode, size_A, size_B):
|
|
print("resize image {}".format(context.area.spaces))
|
|
|
|
# Notes: https://blender.stackexchange.com/questions/31514/active-image-of-uv-image-editor
|
|
# https://docs.blender.org/api/blender_python_api_2_70_4/bpy.types.SpaceImageEditor.html
|
|
|
|
if context.area.spaces.active != None:
|
|
if context.area.spaces.active.image != None:
|
|
image = context.area.spaces.active.image
|
|
image_obj = utilities_texel.get_object_texture_image(
|
|
bpy.context.active_object)
|
|
if name_texture in image.name or image == image_obj:
|
|
# Resize Image UV editor background image
|
|
utilities_texel.image_resize(
|
|
image, int(size_B.x), int(size_B.y))
|
|
|
|
else:
|
|
# No Image assigned
|
|
|
|
# Get background color from theme + 1.25x brighter
|
|
theme = bpy.context.preferences.themes[0]
|
|
color = theme.image_editor.space.back.copy()
|
|
color.r *= 1.15
|
|
color.g *= 1.15
|
|
color.b *= 1.15
|
|
|
|
image = None
|
|
if name_texture in bpy.data.images:
|
|
# TexTools Image already exists
|
|
image = bpy.data.images[name_texture]
|
|
image.scale(int(size_B.x), int(size_B.y))
|
|
image.generated_width = int(size_B.x)
|
|
image.generated_height = int(size_B.y)
|
|
else:
|
|
# Create new image
|
|
image = bpy.data.images.new(
|
|
name_texture, width=int(size_B.x), height=int(size_B.y))
|
|
image.generated_color = (color.r, color.g, color.b, 1.0)
|
|
image.generated_type = 'BLANK'
|
|
image.generated_width = int(size_B.x)
|
|
image.generated_height = int(size_B.y)
|
|
|
|
# Assign in UV view
|
|
context.area.spaces.active.image = image
|
|
|
|
# Clean up images and materials
|
|
utilities_texel.checker_images_cleanup()
|
|
|
|
|
|
bpy.utils.register_class(op)
|