archipack: thumb generator to replace static thumbs, revert _preset to preset according to talk with ideasman42

This commit is contained in:
stephen leger 2017-08-03 15:59:40 +02:00
parent 83e5b12b75
commit 00b84551cf
65 changed files with 615 additions and 241 deletions

View File

@ -261,7 +261,7 @@ class Archipack_Pref(AddonPreferences):
col.label(text="Manipulators:")
col.prop(self, "arrow_size")
col.prop(self, "handle_size")
# layout.operator("archipack.render_thumbs")
# ----------------------------------------------------
# Archipack panels
@ -283,18 +283,16 @@ class TOOLS_PT_Archipack_Tools(Panel):
def draw(self, context):
wm = context.window_manager
layout = self.layout
row = layout.row(align=True)
box = row.box()
box = layout.box()
box.label("Auto boolean")
row = box.row(align=True)
row.operator("archipack.auto_boolean", text="AutoBoolean", icon='AUTO').mode = 'HYBRID'
row = layout.row(align=True)
box = row.box()
box.operator("archipack.auto_boolean", text="AutoBoolean", icon='AUTO').mode = 'HYBRID'
box = layout.box()
box.label("Rendering")
row = box.row(align=True)
row.prop(wm.archipack, 'render_type', text="")
row = box.row(align=True)
row.operator("archipack.render", icon='RENDER_STILL')
box.prop(wm.archipack, 'render_type', text="")
box.operator("archipack.render", icon='RENDER_STILL')
box = layout.box()
box.label("Render presets Thumbnails")
box.operator("archipack.render_thumbs", icon='ERROR')
class TOOLS_PT_Archipack_Create(Panel):

View File

@ -1,11 +0,0 @@
DEFAULT##|##Floor_grout
DEFAULT##|##Floor_alt1
DEFAULT##|##Floor_alt2
DEFAULT##|##Floor_alt3
DEFAULT##|##Floor_alt4
DEFAULT##|##Floor_alt5
DEFAULT##|##Floor_alt6
DEFAULT##|##Floor_alt7
DEFAULT##|##Floor_alt8
DEFAULT##|##Floor_alt9
DEFAULT##|##Floor_alt10

View File

@ -1,12 +0,0 @@
DEFAULT##|##Roof_sheeting
DEFAULT##|##Roof_rakes
DEFAULT##|##Roof_eaves
DEFAULT##|##Roof_ridge
DEFAULT##|##Roof_rafter
DEFAULT##|##Roof_valley
DEFAULT##|##Roof_hip_tiles
DEFAULT##|##Roof_tiles
DEFAULT##|##Roof_tiles2
DEFAULT##|##Roof_tiles3
DEFAULT##|##Roof_tiles4
DEFAULT##|##Roof_tiles5

View File

@ -1,8 +0,0 @@
DEFAULT##|##Wall_inside
DEFAULT##|##Wall_outside
DEFAULT##|##Wall_cuts
DEFAULT##|##Wall_alt1
DEFAULT##|##Wall_alt2
DEFAULT##|##Wall_alt3
DEFAULT##|##Wall_alt4
DEFAULT##|##Wall_alt5

View File

@ -40,6 +40,7 @@ class CutterSegment(Line):
def __init__(self, p, v, type='DEFAULT'):
Line.__init__(self, p, v)
self.type = type
self.is_hole = True
@property
def copy(self):
@ -404,23 +405,29 @@ class CutAblePolygon():
# no points found at all
if start < 0:
# print("no pt inside")
return
return not keep_inside
if not slice_res:
# print("slice fails")
# found more segments than input
# cutter made more than one loop
return
return True
if len(store) < 1:
if is_inside:
# print("not touching, add as hole")
self.holes.append(cutter)
return
if keep_inside:
self.segs = cutter.segs
else:
self.holes.append(cutter)
return True
self.segs = store
self.is_convex()
return True
class CutAbleGenerator():
@ -641,8 +648,7 @@ class ArchipackCutter():
row.prop(self, 'parts_expand', icon="TRIA_DOWN", icon_only=True, text="Parts", emboss=False)
box.prop(self, 'n_parts')
for i, part in enumerate(self.parts):
if i < self.n_parts:
part.draw(layout, context, i)
part.draw(layout, context, i)
else:
row.prop(self, 'parts_expand', icon="TRIA_RIGHT", icon_only=True, text="Parts", emboss=False)

View File

@ -806,9 +806,6 @@ class FloorGenerator(CutAblePolygon, CutAbleGenerator):
m.set_pts([pt1, pt2, pt3])
def generate_pattern(self, d, verts, faces, matids, uvs):
# clear data before refreshing it
self.uv_factor = 1 / max(self.xmax, self.ymax) # automatically scale to keep within reasonable bounds
if d.pattern == "boards":
self.boards(d, verts, faces, matids, uvs)
@ -1225,14 +1222,14 @@ class archipack_floor(ArchipackObject, Manipulable, PropertyGroup):
vary_materials = BoolProperty(
name="Vary Material?",
default=False,
default=True,
description="Vary Material indexes",
update=update)
matid = IntProperty(
name="#variations",
min=1,
max=10,
default=1,
default=7,
description="Material index maxi",
update=update)
auto_update = BoolProperty(
@ -1815,7 +1812,7 @@ class ARCHIPACK_OT_floor(ArchipackCreateTool, Operator):
# activate manipulators at creation time
o.select = True
context.scene.objects.active = o
bpy.ops.archipack.floor_manipulate()
self.manipulate()
return {'FINISHED'}
else:
self.report({'WARNING'}, "Option only valid in Object mode")

View File

@ -2094,7 +2094,7 @@ class ARCHIPACK_OT_manipulate(Operator):
return res
def invoke(self, context, event):
if context.space_data.type == 'VIEW_3D':
if context.space_data is not None and context.space_data.type == 'VIEW_3D':
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
@ -2213,7 +2213,7 @@ class Manipulable():
# take care of context switching
# when call from outside of 3d view
if context.space_data.type != 'VIEW_3D':
if context.space_data is not None and context.space_data.type != 'VIEW_3D':
for window in bpy.context.window_manager.windows:
screen = window.screen
for area in screen.areas:

View File

@ -37,6 +37,7 @@ from bpy.props import (
StringProperty
)
setman = None
libman = None
@ -49,7 +50,10 @@ class MatLib():
"""
def __init__(self, matlib_path, name):
self.name = name
self.path = os.path.join(matlib_path, name)
try:
self.path = os.path.join(matlib_path, name)
except:
pass
self.materials = []
def cleanup(self):
@ -60,14 +64,15 @@ class MatLib():
list material names
"""
# print("MatLib.load_list(%s)" % (self.name))
self.materials.clear()
with bpy.data.libraries.load(self.path) as (data_from, data_to):
for mat in data_from.materials:
self.materials.append(mat)
if sort:
self.materials = list(sorted(self.materials))
try:
with bpy.data.libraries.load(self.path) as (data_from, data_to):
for mat in data_from.materials:
self.materials.append(mat)
if sort:
self.materials = list(sorted(self.materials))
except:
pass
def has(self, name):
return name in self.materials
@ -76,15 +81,19 @@ class MatLib():
"""
Load a material from library
"""
# print("MatLib.load_mat(%s) linked:%s" % (name, link))
with bpy.data.libraries.load(self.path, link, False) as (data_from, data_to):
data_to.materials = [name]
try:
# print("MatLib.load_mat(%s) linked:%s" % (name, link))
with bpy.data.libraries.load(self.path, link, False) as (data_from, data_to):
data_to.materials = [name]
except:
pass
def get_mat(self, name, link):
"""
apply a material by name to active_object
into slot index
lazy load material list on demand
return material or None
"""
# Lazy load material names
@ -116,14 +125,14 @@ class MatlibsManager():
self.matlibs.clear()
def get_prefs(self, context):
"""
let raise error if any
"""
global __name__
prefs = None
try:
# retrieve addon name from imports
addon_name = __name__.split('.')[0]
prefs = context.user_preferences.addons[addon_name].preferences
except:
pass
# retrieve addon name from imports
addon_name = __name__.split('.')[0]
prefs = context.user_preferences.addons[addon_name].preferences
return prefs
@property
@ -166,7 +175,7 @@ class MatlibsManager():
prefs = self.get_prefs(context)
self.add_to_list(prefs.matlib_path)
except:
print("unable to load %s" % mat_path)
print("Archipack: Unable to load default material library, please check path in addon prefs")
pass
def apply(self, context, slot_index, name, link=False):
@ -248,20 +257,23 @@ class MaterialSetManager():
# print("load filename %s" % filename)
material_sets = {}
# create file object, and set open mode
if os.path.exists(filename):
f = open(filename, 'r')
lines = f.readlines()
try:
f = open(filename, 'r')
lines = f.readlines()
for line in lines:
s_key, mat_name = line.split("##|##")
if str(s_key) not in material_sets.keys():
material_sets[s_key] = []
material_sets[s_key].append(mat_name.strip())
f.close()
for line in lines:
s_key, mat_name = line.split("##|##")
if str(s_key) not in material_sets.keys():
material_sets[s_key] = []
material_sets[s_key].append(mat_name.strip())
except:
print("Archipack: An error occured while loading {}".format(filename))
pass
finally:
f.close()
for s_key in material_sets.keys():
self.register_set(object_type, s_key, material_sets[s_key])
@ -275,9 +287,14 @@ class MaterialSetManager():
for s_key in o_dict.keys():
for mat in o_dict[s_key]:
lines.append("{}##|##{}\n".format(s_key, mat))
f = open(filename, 'w')
f.writelines(lines)
f.close()
try:
f = open(filename, 'w')
f.writelines(lines)
except:
print("Archipack: An error occured while saving {}".format(filename))
pass
finally:
f.close()
def add(self, context, set_name):
o = context.active_object
@ -302,9 +319,10 @@ class MaterialSetManager():
if object_type not in self.objects.keys():
self.load(object_type)
if object_type not in self.objects.keys():
print("Archipack: Unknown object type {}".format(object_type))
return None
if set_name not in self.objects[object_type].keys():
print("set {} not found".format(set_name))
print("Archipack: set {} not found".format(set_name))
return None
return self.objects[object_type][set_name]
@ -315,9 +333,9 @@ class MaterialSetManager():
if object_type not in self.objects.keys():
self.objects[object_type] = {}
s_keys = self.objects[object_type].keys()
if len(s_keys) < 1:
return [('DEFAULT', 'Default', '', 0)]
@ -344,7 +362,7 @@ class archipack_material(PropertyGroup):
)
material = EnumProperty(
name="Material",
description="Material type",
description="Material Set name",
items=material_enum,
update=update
)
@ -429,7 +447,7 @@ class ARCHIPACK_OT_material(Operator):
)
material = StringProperty(
name="Material",
description="Material type",
description="Material Set name",
default=""
)
@ -455,8 +473,10 @@ class ARCHIPACK_OT_material(Operator):
pass
if res:
# print("ARCHIPACK_OT_material.apply {} {}".format(self.category, self.material))
return {'FINISHED'}
else:
print("Archipack: unable to add material {} for {}".format(self.material, self.category))
self.report({'WARNING'}, 'Material {} for {} not found'.format(self.material, self.category))
return {'CANCELLED'}
@ -469,7 +489,7 @@ class ARCHIPACK_OT_material_add(Operator):
material = StringProperty(
name="Material",
description="Material type",
description="Material Set name",
default=""
)

View File

@ -36,7 +36,6 @@ from bpy_extras.view3d_utils import (
region_2d_to_origin_3d,
region_2d_to_vector_3d
)
# from .materialutils import MaterialUtils
class ArchipackObject():
@ -151,18 +150,30 @@ class ArchipackCreateTool():
def load_preset(self, d):
"""
Load python preset
d: archipack object datablock
preset: full filename.py with path
"""
d.auto_update = False
fallback = True
if self.filepath != "":
try:
bpy.ops.script.python_file_run(filepath=self.filepath)
fallback = False
except:
print("Archipack unable to load preset file : %s" % (self.filepath))
pass
if fallback:
# fallback to load preset on background process
try:
exec(compile(open(self.filepath).read(), self.filepath, 'exec'))
except:
print("Archipack unable to load preset file : %s" % (self.filepath))
pass
d.auto_update = True
def add_material(self, o, material='DEFAULT', category=None):
# skip if preset allready add material
if "archipack_material" in o:
return
try:
if category is None:
category = self.archipack_category

View File

@ -26,6 +26,7 @@
# ----------------------------------------------------------
import bpy
import os
import subprocess
from bl_operators.presets import AddPresetBase
from mathutils import Vector
from bpy.props import StringProperty
@ -235,19 +236,19 @@ class PresetMenu():
self.imageList.append(self.default_image.filepath_raw)
return
dir_path = os.path.dirname(os.path.realpath(__file__))
sub_path = "_presets" + os.path.sep + "missing.png"
sub_path = "presets" + os.path.sep + "missing.png"
filepath = os.path.join(dir_path, sub_path)
if os.path.exists(filepath) and os.path.isfile(filepath):
self.default_image = bpy.data.images.load(filepath=filepath)
self.imageList.append(self.default_image.filepath_raw)
if self.default_image is None:
raise EnvironmentError("archipack/_presets/missing.png not found")
raise EnvironmentError("archipack/presets/missing.png not found")
def scan_files(self, category):
file_list = []
# load default presets
dir_path = os.path.dirname(os.path.realpath(__file__))
sub_path = "_presets" + os.path.sep + category
sub_path = "presets" + os.path.sep + category
presets_path = os.path.join(dir_path, sub_path)
if os.path.exists(presets_path):
file_list += [presets_path + os.path.sep + f[:-3]
@ -280,7 +281,7 @@ class PresetMenu():
"""
image = None
img_idx = bpy.data.images.find(os.path.basename(filepath) + '.png')
if img_idx > -1:
if img_idx > -1 and bpy.data.images[img_idx].filepath_raw == filepath:
image = bpy.data.images[img_idx]
self.imageList.append(image.filepath_raw)
elif os.path.exists(filepath + '.png') and os.path.isfile(filepath + '.png'):
@ -522,6 +523,23 @@ class ArchipackPreset(AddPresetBase):
# remove thumb
os.remove(filepath[:-3] + ".png")
def background_render(self, context, cls, preset):
print("bg render")
generator = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + "archipack_thumbs.py"
# Run external instance of blender like the original thumbnail generator.
cmd = [
bpy.app.binary_path,
"--background",
"-noaudio",
"--python", generator,
"--",
"cls:" + cls,
"preset:" + preset
]
print(repr(cmd))
subprocess.Popen(cmd)
def post_cb(self, context):
if not self.remove_active:
@ -536,49 +554,9 @@ class ArchipackPreset(AddPresetBase):
target_path,
create=True)
filepath = os.path.join(target_path, filename) + ".png"
# render thumb
scene = context.scene
render = scene.render
# save render parame
resolution_x = render.resolution_x
resolution_y = render.resolution_y
resolution_percentage = render.resolution_percentage
old_filepath = render.filepath
use_file_extension = render.use_file_extension
use_overwrite = render.use_overwrite
use_compositing = render.use_compositing
use_sequencer = render.use_sequencer
file_format = render.image_settings.file_format
color_mode = render.image_settings.color_mode
color_depth = render.image_settings.color_depth
render.resolution_x = 150
render.resolution_y = 100
render.resolution_percentage = 100
render.filepath = filepath
render.use_file_extension = True
render.use_overwrite = True
render.use_compositing = False
render.use_sequencer = False
render.image_settings.file_format = 'PNG'
render.image_settings.color_mode = 'RGBA'
render.image_settings.color_depth = '8'
bpy.ops.render.render(animation=False, write_still=True, use_viewport=False)
# restore render params
render.resolution_x = resolution_x
render.resolution_y = resolution_y
render.resolution_percentage = resolution_percentage
render.filepath = old_filepath
render.use_file_extension = use_file_extension
render.use_overwrite = use_overwrite
render.use_compositing = use_compositing
render.use_sequencer = use_sequencer
render.image_settings.file_format = file_format
render.image_settings.color_mode = color_mode
render.image_settings.color_depth = color_depth
preset = os.path.join(target_path, filename) + ".py"
cls = self.preset_subdir[10:]
print("post cb cls:%s preset:%s" % (cls, preset))
self.background_render(context, cls, preset)
return

View File

@ -36,13 +36,16 @@ info_header_draw = None
def update(self, context):
global last_update
areas = context.window.screen.areas
for area in areas:
if area.type == 'INFO':
area.tag_redraw()
if time() - last_update > 0.1:
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
last_update = time()
if (context.window is not None and
context.window.screen is not None and
context.window.screen.areas is not None):
areas = context.window.screen.areas
for area in areas:
if area.type == 'INFO':
area.tag_redraw()
if time() - last_update > 0.1:
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
last_update = time()
def register():

View File

@ -30,8 +30,9 @@
import bpy
# noinspection PyUnresolvedReferences
import bgl
from os import path, remove
from os import path, remove, listdir
from sys import exc_info
import subprocess
# noinspection PyUnresolvedReferences
import bpy_extras.image_utils as img_utils
# noinspection PyUnresolvedReferences
@ -39,6 +40,95 @@ from math import ceil
from bpy.types import Operator
class ARCHIPACK_OT_render_thumbs(Operator):
bl_idname = "archipack.render_thumbs"
bl_label = "Render preset thumbs"
bl_description = "Render all presets thumbs"
bl_options = {'REGISTER', 'INTERNAL'}
def background_render(self, context, cls, preset):
generator = path.dirname(path.realpath(__file__)) + path.sep + "archipack_thumbs.py"
# Run external instance of blender like the original thumbnail generator.
cmd = [
bpy.app.binary_path,
"--background",
"-noaudio",
"--python", generator,
"--",
"cls:" + cls,
"preset:" + preset
]
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 scan_files(self, category):
file_list = []
# load default presets
dir_path = path.dirname(path.realpath(__file__))
sub_path = "presets" + path.sep + category
presets_path = path.join(dir_path, sub_path)
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('.')]
# 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('.')]
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)
for l in self.background_render(context, cls, file + ".py"):
if "[log]" in l:
print(l[5:].strip())
# elif not "Fra:1" in l:
# print(l.strip())
@classmethod
def poll(cls, context):
return context.scene.archipack_progress < 0
def invoke(self, context, event):
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'}
# -------------------------------------------------------------
# Defines button for render
#
@ -523,7 +613,9 @@ class ARCHIPACK_OT_render(Operator):
def register():
bpy.utils.register_class(ARCHIPACK_OT_render)
bpy.utils.register_class(ARCHIPACK_OT_render_thumbs)
def unregister():
bpy.utils.unregister_class(ARCHIPACK_OT_render)
bpy.utils.unregister_class(ARCHIPACK_OT_render_thumbs)

View File

@ -1578,6 +1578,9 @@ class RoofGenerator(CutAbleGenerator):
idmat = 7
rand = 3
ttl = len(self.pans)
if ttl < 1:
return
sx, sy, sz = d.tile_size_x, d.tile_size_y, d.tile_size_z
@ -1687,10 +1690,10 @@ class RoofGenerator(CutAbleGenerator):
dx, dy = d.tile_space_x, d.tile_space_y
ttl = len(self.pans)
step = 100 / ttl
context.scene.archipack_progress_text = "Build tiles:"
if d.quick_edit:
context.scene.archipack_progress_text = "Build tiles:"
for i, pan in enumerate(self.pans):
@ -1737,7 +1740,8 @@ class RoofGenerator(CutAbleGenerator):
progress = step * i + substep * k
# print("progress %s" % (progress))
context.scene.archipack_progress = progress
if d.quick_edit:
context.scene.archipack_progress = progress
y = k * dy
@ -1875,7 +1879,8 @@ class RoofGenerator(CutAbleGenerator):
bmed.bmesh_join(context, o, [bm], normal_update=True)
bpy.ops.object.mode_set(mode='OBJECT')
context.scene.archipack_progress = -1
if d.quick_edit:
context.scene.archipack_progress = -1
def _rake(self, s, i, boundary, pan,
width, height, altitude, offset, idmat,
@ -2654,9 +2659,9 @@ class RoofGenerator(CutAbleGenerator):
x1, y1 = s.lerp(t0)
x2, y2 = p1
x3, y3 = s.lerp(t1)
z0 = self.z + d.beam_alt
z0 = self.z + d.beam_alt + pan.altitude(p0)
z1 = z0 - d.beam_height
z2 = self.z + d.beam_alt
z2 = self.z + d.beam_alt + pan.altitude(p1)
z3 = z2 - d.beam_height
verts.extend([
(x0, y0, z0),
@ -2910,9 +2915,18 @@ class RoofGenerator(CutAbleGenerator):
s2 = pan.last_seg(i)
s3 = pan.next_seg(i)
res, p0, t0 = s0.intersect(s2)
res, p1, t1 = s0.intersect(s3)
p0 = s0.p0
p1 = s0.p1
t0 = 0
t1 = 1
res, p, t = s0.intersect(s2)
if res:
t0 = t
p0 = p
res, p, t = s0.intersect(s3)
if res:
t1 = t
p1 = p
p0 = s.lerp(t0)
p1 = s.lerp(t1)
@ -3043,8 +3057,14 @@ class RoofGenerator(CutAbleGenerator):
s0 = s.offset(-2 * d.tile_couloir)
s1 = pan.last_seg(i)
s2 = pan.next_seg(i)
res, p0, t = s0.intersect(s1)
res, p1, t = s0.intersect(s2)
p0 = s0.p0
p1 = s0.p1
res, p, t = s0.intersect(s1)
if res:
p0 = p
res, p, t = s0.intersect(s2)
if res:
p1 = p
alt = self.z + d.valley_altitude
x0, y0 = s1.p1
x1, y1 = p0
@ -3397,14 +3417,21 @@ class RoofGenerator(CutAbleGenerator):
"""
either external or holes cuts
"""
to_remove = []
for b in o.children:
d = archipack_roof_cutter.datablock(b)
if d is not None:
g = d.ensure_direction()
g.change_coordsys(b.matrix_world, o.matrix_world)
for pan in self.pans:
pan.slice(g)
for i, pan in enumerate(self.pans):
keep = pan.slice(g)
if not keep:
if i not in to_remove:
to_remove.append(i)
pan.limits()
to_remove.sort()
for i in reversed(to_remove):
self.pans.pop(i)
def draft(self, context, verts, edges):
for pan in self.pans:
@ -3469,7 +3496,7 @@ class ArchipackSegment():
name="length",
min=0.01,
max=1000.0,
default=2.0,
default=4.0,
update=update
)
a0 = FloatProperty(
@ -3552,10 +3579,10 @@ class ArchipackLines():
class archipack_roof_segment(ArchipackSegment, PropertyGroup):
bound_idx = IntProperty(
default=0,
min=0,
update=update_manipulators
)
default=0,
min=0,
update=update_manipulators
)
width_left = FloatProperty(
name="L Width",
min=0.01,
@ -3610,31 +3637,31 @@ class archipack_roof_segment(ArchipackSegment, PropertyGroup):
update=update
)
take_precedence = BoolProperty(
name="Take precedence",
description="On T segment take width precedence",
default=False,
update=update
)
name="Take precedence",
description="On T segment take width precedence",
default=False,
update=update
)
constraint_type = EnumProperty(
items=(
('HORIZONTAL', 'Horizontal', '', 0),
('SLOPE', 'Slope', '', 1)
),
default='HORIZONTAL',
update=update_manipulators
)
items=(
('HORIZONTAL', 'Horizontal', '', 0),
('SLOPE', 'Slope', '', 1)
),
default='HORIZONTAL',
update=update_manipulators
)
enforce_part = EnumProperty(
name="Enforce part",
items=(
('AUTO', 'Auto', '', 0),
('VALLEY', 'Valley', '', 1),
('HIP', 'Hip', '', 2)
),
default='AUTO',
update=update
)
name="Enforce part",
items=(
('AUTO', 'Auto', '', 0),
('VALLEY', 'Valley', '', 1),
('HIP', 'Hip', '', 2)
),
default='AUTO',
update=update
)
def find_in_selection(self, context):
"""
@ -3737,11 +3764,6 @@ class archipack_roof(ArchipackLines, ArchipackObject, Manipulable, PropertyGroup
name="Quick Edit",
default=True
)
force_update = BoolProperty(
options={'SKIP_SAVE'},
name="Throttle",
default=True
)
tile_enable = BoolProperty(
name="Enable",
@ -4223,51 +4245,51 @@ class archipack_roof(ArchipackLines, ArchipackObject, Manipulable, PropertyGroup
)
t_parent = StringProperty(
name="Parent",
default="",
update=update_parent
)
name="Parent",
default="",
update=update_parent
)
t_part = IntProperty(
name="Part",
description="Parent part index",
default=0,
min=0,
update=update_cutter
)
name="Part",
description="Parent part index",
default=0,
min=0,
update=update_cutter
)
t_dist_x = FloatProperty(
name="Dist x",
description="Location on axis ",
default=0,
update=update_cutter
)
name="Dist x",
description="Location on axis ",
default=0,
update=update_cutter
)
t_dist_y = FloatProperty(
name="Dist y",
description="Lateral distance from axis",
min=0.0001,
default=0.0001,
update=update_cutter
)
name="Dist y",
description="Lateral distance from axis",
min=0.0001,
default=0.0001,
update=update_cutter
)
hole_offset_left = FloatProperty(
name="Left",
description="Left distance from border",
min=0,
default=0,
update=update_cutter
)
name="Left",
description="Left distance from border",
min=0,
default=0,
update=update_cutter
)
hole_offset_right = FloatProperty(
name="Right",
description="Right distance from border",
min=0,
default=0,
update=update_cutter
)
name="Right",
description="Right distance from border",
min=0,
default=0,
update=update_cutter
)
hole_offset_front = FloatProperty(
name="Front",
description="Front distance from border",
default=0,
update=update_cutter
)
name="Front",
description="Front distance from border",
default=0,
update=update_cutter
)
def make_wall_fit(self, context, o, wall, inside=False):
origin = Vector((0, 0, self.z))
@ -5007,6 +5029,12 @@ class ARCHIPACK_OT_roof(ArchipackCreateTool, Operator):
o.select = True
context.scene.objects.active = o
self.add_material(o)
# disable progress bar when
# background render thumbs
if not self.auto_manipulate:
d.quick_edit = False
self.load_preset(d)
return o
@ -5335,7 +5363,7 @@ class ARCHIPACK_OT_roof_preset(ArchipackPreset, Operator):
@property
def blacklist(self):
return ['n_parts', 'parts', 'manipulators', 'user_defined_path']
return ['n_parts', 'parts', 'manipulators', 'user_defined_path', 'quick_edit', 'draft']
def register():

View File

@ -0,0 +1,183 @@
# -*- 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 #####
# <pep8 compliant>
# ----------------------------------------------------------
# Author: Stephen Leger (s-leger)
# Inspired by Asset-Flinguer
# ----------------------------------------------------------
import sys
from mathutils import Vector
import bpy
def log(s):
print("[log]" + s)
def generateThumb(context, cls, preset):
log("### RENDER THUMB ############################")
log("Start generating: " + cls)
# engine settings
context.scene.render.engine = 'CYCLES'
render = context.scene.cycles
render.progressive = 'PATH'
render.samples = 24
render.use_square_samples = True
render.preview_samples = 24
render.aa_samples = 24
render.transparent_max_bounces = 8
render.transparent_min_bounces = 8
render.transmission_bounces = 8
render.max_bounces = 8
render.min_bounces = 6
render.caustics_refractive = False
render.caustics_reflective = False
render.use_transparent_shadows = True
render.diffuse_bounces = 1
render.glossy_bounces = 4
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete()
# create object, loading preset
getattr(bpy.ops.archipack, cls)('INVOKE_DEFAULT', filepath=preset, auto_manipulate=False)
o = context.active_object
size = o.dimensions
x, y, z = o.bound_box[0]
min_x = x
min_y = y
min_z = z
x, y, z = o.bound_box[6]
max_x = x
max_y = y
max_z = z
center = Vector((
min_x + 0.5 * (max_x - min_x),
min_y + 0.5 * (max_y - min_y),
min_z + 0.5 * (max_z - min_z)))
# oposite / tan (0.5 * fov) where fov is 49.134 deg
dist = max(size) / 0.32
loc = center + dist * Vector((0.5, -1, 0.5)).normalized()
log("Prepare camera")
bpy.ops.object.camera_add(view_align=True,
enter_editmode=False,
location=loc,
rotation=(1.150952, 0.0, 0.462509))
cam = context.active_object
cam.data.lens = 50
cam.select = True
context.scene.camera = cam
bpy.ops.object.select_all(action="DESELECT")
o.select = True
bpy.ops.view3d.camera_to_view_selected()
log("Prepare scene")
# add plane
bpy.ops.mesh.primitive_plane_add(
radius=1000,
view_align=False,
enter_editmode=False,
location=(0, 0, 0)
)
p = context.active_object
m = bpy.data.materials.new("Plane")
m.use_nodes = True
m.node_tree.nodes[1].inputs[0].default_value = (1, 1, 1, 1)
p.data.materials.append(m)
# add 3 lights
bpy.ops.object.lamp_add(
type='POINT',
radius=1,
view_align=False,
location=(3.69736, -7, 6.0))
l = context.active_object
l.data.use_nodes = True
tree = l.data.node_tree
nodes = l.data.node_tree.nodes
emit = nodes["Emission"]
emit.inputs[1].default_value = 2000.0
bpy.ops.object.lamp_add(
type='POINT',
radius=1,
view_align=False,
location=(9.414563179016113, 5.446230888366699, 5.903861999511719))
l = context.active_object
l.data.use_nodes = True
tree = l.data.node_tree
nodes = l.data.node_tree.nodes
emit = nodes["Emission"]
falloff = nodes.new(type="ShaderNodeLightFalloff")
falloff.inputs[0].default_value = 5
tree.links.new(falloff.outputs[2], emit.inputs[1])
bpy.ops.object.lamp_add(
type='POINT',
radius=1,
view_align=False,
location=(-7.847615718841553, 1.03135085105896, 5.903861999511719))
l = context.active_object
l.data.use_nodes = True
tree = l.data.node_tree
nodes = l.data.node_tree.nodes
emit = nodes["Emission"]
falloff = nodes.new(type="ShaderNodeLightFalloff")
falloff.inputs[0].default_value = 5
tree.links.new(falloff.outputs[2], emit.inputs[1])
# Set output filename.
render = context.scene.render
render.filepath = preset[:-3] + ".png"
render.use_file_extension = True
render.use_overwrite = True
render.use_compositing = False
render.use_sequencer = False
render.resolution_x = 150
render.resolution_y = 100
render.resolution_percentage = 100
# render.image_settings.file_format = 'PNG'
# render.image_settings.color_mode = 'RGBA'
# render.image_settings.color_depth = '8'
# Configure output size.
log("Render")
# Render thumbnail
bpy.ops.render.render(write_still=True)
log("### COMPLETED ############################")
preset = ""
for arg in sys.argv:
if arg.startswith("cls:"):
cls = arg[4:]
if arg.startswith("preset:"):
preset = arg[7:]
generateThumb(bpy.context, cls, preset)

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='DEFAULT')
d.add_grout = False
d.bevel = False
d.bevel_amount = 0.001

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='DEFAULT')
d.add_grout = False
d.bevel = False
d.bevel_amount = 0.001

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='DEFAULT')
d.add_grout = False
d.bevel = False
d.bevel_amount = 0.001

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='TILES')
d.add_grout = True
d.bevel = True
d.bevel_amount = 0.0015
@ -23,7 +24,7 @@ d.thickness_variance = 25.0
d.tile_length = 0.3
d.tile_width = 0.1
d.vary_length = False
d.vary_materials = False
d.vary_materials = True
d.vary_thickness = False
d.vary_width = False
d.width_spacing = 0.002

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='TILES')
d.add_grout = True
d.bevel = True
d.bevel_amount = 0.0015
@ -23,7 +24,7 @@ d.thickness_variance = 25.0
d.tile_length = 0.3
d.tile_width = 0.3
d.vary_length = False
d.vary_materials = False
d.vary_materials = True
d.vary_thickness = False
d.vary_width = False
d.width_spacing = 0.002

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='DEFAULT')
d.add_grout = False
d.bevel = False
d.bevel_amount = 0.001

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='TILES')
d.add_grout = True
d.bevel = True
d.bevel_amount = 0.0015
@ -23,7 +24,7 @@ d.thickness_variance = 25.0
d.tile_length = 0.3
d.tile_width = 0.3
d.vary_length = False
d.vary_materials = False
d.vary_materials = True
d.vary_thickness = False
d.vary_width = False
d.width_spacing = 0.002

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='TILES')
d.add_grout = True
d.bevel = True
d.bevel_amount = 0.0015
@ -23,7 +24,7 @@ d.thickness_variance = 25.0
d.tile_length = 0.3
d.tile_width = 0.6
d.vary_length = False
d.vary_materials = False
d.vary_materials = True
d.vary_thickness = False
d.vary_width = False
d.width_spacing = 0.002

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_floor[0]
bpy.ops.archipack.material(category='floor', material='TILES')
d.add_grout = True
d.bevel = True
d.bevel_amount = 0.0015
@ -23,7 +24,7 @@ d.thickness_variance = 25.0
d.tile_length = 0.3
d.tile_width = 0.3
d.vary_length = False
d.vary_materials = False
d.vary_materials = True
d.vary_thickness = False
d.vary_width = False
d.width_spacing = 0.002

View File

@ -0,0 +1,22 @@
DEFAULT##|##Floor_grout
DEFAULT##|##Floor_alt1
DEFAULT##|##Floor_alt2
DEFAULT##|##Floor_alt3
DEFAULT##|##Floor_alt4
DEFAULT##|##Floor_alt5
DEFAULT##|##Floor_alt6
DEFAULT##|##Floor_alt7
DEFAULT##|##Floor_alt8
DEFAULT##|##Floor_alt9
DEFAULT##|##Floor_alt10
TILES##|##Floor_grout
TILES##|##Floor_tiles_alt1
TILES##|##Floor_tiles_alt2
TILES##|##Floor_tiles_alt3
TILES##|##Floor_tiles_alt4
TILES##|##Floor_tiles_alt5
TILES##|##Floor_tiles_alt6
TILES##|##Floor_alt7
TILES##|##Floor_alt8
TILES##|##Floor_alt9
TILES##|##Floor_alt10

View File

@ -0,0 +1,49 @@
DEFAULT##|##Roof_sheeting
DEFAULT##|##Roof_rakes
DEFAULT##|##Roof_eaves
DEFAULT##|##Roof_ridge
DEFAULT##|##Roof_rafter
DEFAULT##|##Roof_valley
DEFAULT##|##Roof_hip_tiles
DEFAULT##|##Roof_tiles
DEFAULT##|##Roof_tiles2
DEFAULT##|##Roof_tiles3
DEFAULT##|##Roof_tiles4
DEFAULT##|##Roof_tiles5
STONE##|##Roof_sheeting
STONE##|##Roof_rakes
STONE##|##Roof_eaves
STONE##|##Roof_ridge
STONE##|##Roof_rafter
STONE##|##Roof_valley
STONE##|##Roof_hip_stone
STONE##|##Roof_tiles_stone
STONE##|##Roof_tiles_stone2
STONE##|##Roof_tiles_stone3
STONE##|##Roof_tiles_stone4
STONE##|##Roof_tiles_stone5
BLACK##|##Roof_sheeting
BLACK##|##Roof_rakes
BLACK##|##Roof_eaves
BLACK##|##Roof_ridge
BLACK##|##Roof_rafter
BLACK##|##Roof_valley
BLACK##|##Roof_hip_black
BLACK##|##Roof_tiles_black
BLACK##|##Roof_tiles_black2
BLACK##|##Roof_tiles_black3
BLACK##|##Roof_tiles_black4
BLACK##|##Roof_tiles_black5
METAL##|##Roof_sheeting
METAL##|##Roof_rakes
METAL##|##Roof_eaves
METAL##|##Roof_ridge
METAL##|##Roof_rafter
METAL##|##Roof_valley
METAL##|##Roof_hip_metal
METAL##|##Roof_metal
METAL##|##Roof_metal2
METAL##|##Roof_metal3
METAL##|##Roof_metal4
METAL##|##Roof_metal5

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='DEFAULT')
d.tile_model = 'BRAAS1'
d.tile_size_z = 0.05
d.tile_border = 0.0

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='DEFAULT')
d.tile_model = 'BRAAS2'
d.tile_size_z = 0.05
d.tile_border = 0.0

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='BLACK')
d.tile_model = 'ETERNIT'
d.tile_size_z = 0.01
d.tile_border = 0.0

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='STONE')
d.tile_model = 'LAUZE'
d.tile_size_z = 0.04
d.tile_border = 0.0

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='METAL')
d.tile_side = 0.0
d.hip_alt = 0.07
d.tile_fit_y = False

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='METAL')
d.tile_side = 0.0
d.hip_alt = 0.07
d.tile_fit_y = False

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='DEFAULT')
d.tile_model = 'ROMAN'
d.tile_size_z = 0.16
d.tile_border = 0.0

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='DEFAULT')
d.tile_model = 'ROUND'
d.tile_size_z = 0.02
d.tile_border = 0.0

View File

@ -1,5 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_roof[0]
bpy.ops.archipack.material(category='roof', material='BLACK')
d.tile_model = 'PLACEHOLDER'
d.tile_size_z = 0.01
d.tile_border = 0.0

View File

@ -1,6 +1,6 @@
import bpy
d = bpy.context.active_object.data.archipack_stair[0]
d.auto_update = False
d.steps_type = 'CLOSED'
d.handrail_slice_right = True
d.total_angle = 6.2831854820251465

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB