# -*- coding:utf-8 -*- # ##### BEGIN GPL LICENSE BLOCK ##### # # 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 2 # 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, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110- 1301, USA. # # ##### END GPL LICENSE BLOCK ##### # # ---------------------------------------------------------- # support routines for render measures in final image # Author: Antonio Vazquez (antonioya) # Archipack adaptation by : Stephen Leger (s-leger) # # ---------------------------------------------------------- # noinspection PyUnresolvedReferences import bpy # noinspection PyUnresolvedReferences import bgl from shutil import copyfile from os import path, listdir import subprocess # noinspection PyUnresolvedReferences import bpy_extras.image_utils as img_utils # noinspection PyUnresolvedReferences from math import ceil from bpy.types import Operator # from bl_ui import properties_render class ARCHIPACK_OT_render_thumbs(Operator): bl_idname = "archipack.render_thumbs" bl_label = "Render presets thumbs" bl_description = "Setup default presets and update thumbs" bl_options = {'REGISTER', 'INTERNAL'} @classmethod def poll(cls, context): # Ensure CYCLES engine is available # hasattr(context.scene, 'cycles') return context.scene def background_render(self, context, cls, preset): generator = path.dirname(path.realpath(__file__)) + path.sep + "archipack_thumbs.py" addon_name = __name__.split('.')[0] matlib_path = context.preferences.addons[addon_name].preferences.matlib_path # Run external instance of blender like the original thumbnail generator. cmd = [ bpy.app.binary_path, "--background", "--factory-startup", "-noaudio", # "--addons", addon_name, "--python", generator, "--", "addon:" + addon_name, "matlib:" + matlib_path, "cls:" + cls, "preset:" + preset ] # print(" ".join(cmd)) popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) for stdout_line in iter(popen.stdout.readline, ""): yield stdout_line popen.stdout.close() popen.wait() def copy_to_user_path(self, category): """ Copy factory presets to writeable presets folder Two cases here: 1 there is not presets thumbs found (official version) 2 thumbs already are there (unofficial) """ file_list = [] # load default presets dir_path = path.dirname(path.realpath(__file__)) sub_path = "presets" + path.sep + category source_path = path.join(dir_path, sub_path) if path.exists(source_path): file_list.extend([f for f in listdir(source_path) if (f.endswith('.py') or f.endswith('.txt')) and not f.startswith('.')]) target_path = path.join("presets", category) presets_path = bpy.utils.user_resource('SCRIPTS', target_path, create=True) # files from factory not found in user doesn't require a recompute skipfiles = [] for f in file_list: # copy python/txt preset if not path.exists(presets_path + path.sep + f): copyfile(source_path + path.sep + f, presets_path + path.sep + f) # skip txt files (material presets) if f.endswith(".txt"): skipfiles.append(f) # when thumbs already are in factory folder but not found in user one # simply copy them, and add preset to skip list thumb_filename = f[:-3] + ".png" if path.exists(source_path + path.sep + thumb_filename): if not path.exists(presets_path + path.sep + thumb_filename): copyfile(source_path + path.sep + thumb_filename, presets_path + path.sep + thumb_filename) skipfiles.append(f) return skipfiles def scan_files(self, category): file_list = [] # copy from factory to user writeable folder skipfiles = self.copy_to_user_path(category) # load user def presets preset_paths = bpy.utils.script_paths("presets") for preset in preset_paths: presets_path = path.join(preset, category) if path.exists(presets_path): file_list += [presets_path + path.sep + f[:-3] for f in listdir(presets_path) if f.endswith('.py') and not f.startswith('.') and f not in skipfiles] file_list.sort() return file_list def rebuild_thumbs(self, context): file_list = [] dir_path = path.dirname(path.realpath(__file__)) sub_path = "presets" presets_path = path.join(dir_path, sub_path) # print(presets_path) if path.exists(presets_path): dirs = listdir(presets_path) for dir in dirs: abs_dir = path.join(presets_path, dir) if path.isdir(abs_dir): files = self.scan_files(dir) file_list.extend([(dir, file) for file in files]) ttl = len(file_list) for i, preset in enumerate(file_list): dir, file = preset cls = dir[10:] # context.scene.archipack_progress = (100 * i / ttl) log_all = False for l in self.background_render(context, cls, file + ".py"): if "[log]" in l: print(l[5:].strip()) elif "blender.crash" in l: print("Unexpected error") log_all = True if log_all: print(l.strip()) def invoke(self, context, event): addon_name = __name__.split('.')[0] matlib_path = context.preferences.addons[addon_name].preferences.matlib_path if matlib_path == '': self.report({'WARNING'}, "You should setup a default material library path in addon preferences") return context.window_manager.invoke_confirm(self, event) def execute(self, context): # context.scene.archipack_progress_text = 'Generating thumbs' # context.scene.archipack_progress = 0 self.rebuild_thumbs(context) # context.scene.archipack_progress = -1 return {'FINISHED'} def register(): bpy.utils.register_class(ARCHIPACK_OT_render_thumbs) def unregister(): bpy.utils.unregister_class(ARCHIPACK_OT_render_thumbs)