bl-symmetrize-texture/addon/app.py

167 lines
5.0 KiB
Python
Raw Normal View History

2024-03-05 21:33:30 +09:00
'''
Copyright (C) 2021 - 2023 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 sys
import os
import ctypes
import math
import bpy
import bpy.utils.previews
import blf
import numpy as np
from . ui_renderer import UIRenderer as UIRenderer
from . import utils
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\n" \
+ "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\n" \
+ "RMB: Finish\n" \
+ "F: Change brush size"
area_height = context.area.height
# info text
if info_text:
blf.enable(0, blf.WORD_WRAP)
blf.word_wrap(0, 200)
blf.color(0, 1.0, 1.0, 1.0, 1.0)
if bpy.context.area.type == 'VIEW_3D':
blf.position(0, 85, area_height - 150, 0)
else:
blf.position(0, 85, area_height - 70, 0)
blf.size(0, 14, 72)
blf.draw(0, info_text)
blf.disable(0, blf.WORD_WRAP)
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()