bl-symmetrize-texture/addon/app.py

160 lines
5.0 KiB
Python

'''
Copyright (C) 2021 - 2024 Akaneyu
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 3 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, see <http://www.gnu.org/licenses/>.
'''
import os
import ctypes
import bpy
import bpy.utils.previews
import blf
import numpy as np
from . ui_renderer import UIRenderer as UIRenderer
class Session:
def __init__(self):
self.icons = None
self.ui_renderer = None
self.draw_handler = None
self.previous_object = None
self.brush_position = None
self.brush_size = 50.0
self.selecting_direction = False
self.brush_active = False
self.resizing_brush = False
def get_session():
global session
return session
def draw_handler():
global session
context = bpy.context
wm = context.window_manager
props = wm.symmetrizetexture_properties
mirror_axis = props.image_mirror_axis
info_text = None
if not session.ui_renderer:
session.ui_renderer = UIRenderer()
# direction setup
if session.selecting_direction:
if mirror_axis == 'x_axis':
border_pos1 = context.region.view2d.view_to_region(0.5, 0, clip=False)
border_pos2 = context.region.view2d.view_to_region(0.5, 1.0, clip=False)
else:
border_pos1 = context.region.view2d.view_to_region(0, 0.5, clip=False)
border_pos2 = context.region.view2d.view_to_region(1.0, 0.5, clip=False)
session.ui_renderer.render_border(border_pos1, border_pos2)
center = context.region.view2d.view_to_region(0.5, 0.5, clip=False)
if mirror_axis == 'x_axis':
arrow_angle = 0 if session.direction > 0 else np.pi
else:
arrow_angle = np.pi / 2.0 if session.direction > 0 else np.pi * 1.5
session.ui_renderer.render_arrow(center, arrow_angle)
info_text = "[LMB] Perform " \
+ "[RMB] Cancel"
# brush
if session.brush_active and session.brush_position:
session.ui_renderer.render_brush_frame(session.brush_position, session.brush_size)
info_text = "[LMB] Perform " \
+ "[RMB] Finish " \
+ "[F] Change brush size"
area_width, area_height = context.area.width, context.area.height
# info text
if info_text:
ui_scale = context.preferences.system.ui_scale
session.ui_renderer.render_info_box((0, 0), (area_width, 20 * ui_scale))
blf.position(0, 8 * ui_scale, 6 * ui_scale, 0)
blf.size(0, 11 * ui_scale) if bpy.app.version >= (3, 6) \
else blf.size(0, 11 * ui_scale, 72)
blf.color(0, 0.7, 0.7, 0.7, 1.0)
blf.draw(0, info_text)
def load_icons():
global session
script_dir = os.path.dirname(os.path.realpath(__file__))
icons = bpy.utils.previews.new()
icons_dir = os.path.join(script_dir, "icons")
for file_name in os.listdir(icons_dir):
icon_name = os.path.splitext(file_name)[0]
icons.load(icon_name, os.path.join(icons_dir, file_name), 'IMAGE')
session.icons = icons
def dispose_icons():
global session
bpy.utils.previews.remove(session.icons)
def load_native_library():
script_dir = os.path.dirname(os.path.realpath(__file__))
if os.name == 'nt':
lib_file_name = 'symmetrize_texture.dll'
else:
lib_file_name = 'libsymmetrize_texture.so'
lib = ctypes.CDLL(os.path.join(script_dir, lib_file_name))
return lib
def unload_native_library(lib):
if os.name == 'nt':
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
kernel32.FreeLibrary.argtypes = [ctypes.c_void_p]
kernel32.FreeLibrary(lib._handle)
else:
stdlib = ctypes.CDLL("")
stdlib.dlclose.argtypes = [ctypes.c_void_p]
stdlib.dlclose(lib._handle)
def get_image_previews(self, context):
image_previews = []
for i, img in enumerate(bpy.data.images):
image_previews.append((img.name, img.name, img.name, bpy.types.UILayout.icon(img), i))
return image_previews
class SYMMETRIZE_TEXTURE_PropertyGroup(bpy.types.PropertyGroup):
image_preview: bpy.props.EnumProperty(items=get_image_previews, options={'LIBRARY_EDITABLE'})
# created in the register(): image_mirror_axis
brush_strength: bpy.props.FloatProperty(name='Strength', default=1.0, min=0, max=1.0, precision=3)
brush_falloff: bpy.props.EnumProperty(items=(
('smooth', 'Smooth', 'Smooth', 'SMOOTHCURVE', 0),
('constant', 'Constant', 'Constant', 'NOCURVE', 1)))
session = Session()