''' 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 . ''' 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()