Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Dinges <blender@dingto.org>2021-11-23 11:24:55 +0300
committerThomas Dinges <blender@dingto.org>2021-11-23 11:24:55 +0300
commitd7517a6f2a69071eab53c02a645f7651ccfffd45 (patch)
tree7a496b8ada3e764b7e6c438e30d8c2be49fb95cf /archipack/archipack_stair.py
parent162cba016c8c11bcebea4d8d3cf80da9faf4ce76 (diff)
Remove Archipack to reflect new key requirements.
https://wiki.blender.org/wiki/Process/Addons
Diffstat (limited to 'archipack/archipack_stair.py')
-rw-r--r--archipack/archipack_stair.py2845
1 files changed, 0 insertions, 2845 deletions
diff --git a/archipack/archipack_stair.py b/archipack/archipack_stair.py
deleted file mode 100644
index 9fbcdfe2..00000000
--- a/archipack/archipack_stair.py
+++ /dev/null
@@ -1,2845 +0,0 @@
-# -*- 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)
-#
-# ----------------------------------------------------------
-# noinspection PyUnresolvedReferences
-import bpy
-# noinspection PyUnresolvedReferences
-from bpy.types import Operator, PropertyGroup, Mesh, Panel
-from bpy.props import (
- FloatProperty, BoolProperty, IntProperty, CollectionProperty,
- StringProperty, EnumProperty, FloatVectorProperty
- )
-from .bmesh_utils import BmeshEdit as bmed
-from .panel import Panel as Lofter
-from mathutils import Vector, Matrix
-from math import sin, cos, pi, floor, acos
-from .archipack_manipulator import Manipulable, archipack_manipulator
-from .archipack_2d import Line, Arc
-from .archipack_preset import ArchipackPreset, PresetMenuOperator
-from .archipack_object import ArchipackCreateTool, ArchipackObject
-
-
-class Stair():
- def __init__(self, left_offset, right_offset, steps_type, nose_type, z_mode, nose_z, bottom_z):
- self.steps_type = steps_type
- self.nose_type = nose_type
- self.l_shape = None
- self.r_shape = None
- self.next_type = 'NONE'
- self.last_type = 'NONE'
- self.z_mode = z_mode
- # depth of open step
- self.nose_z = nose_z
- # size under the step on bottom
- self.bottom_z = bottom_z
- self.left_offset = left_offset
- self.right_offset = right_offset
- self.last_height = 0
-
- def set_matids(self, matids):
- self.idmat_top, self.idmat_step_front, self.idmat_raise, \
- self.idmat_side, self.idmat_bottom, self.idmat_step_side = matids
-
- def set_height(self, step_height, z0):
- self.step_height = step_height
- self.z0 = z0
-
- @property
- def height(self):
- return self.n_step * self.step_height
-
- @property
- def top_offset(self):
- return self.t_step / self.step_depth
-
- @property
- def top(self):
- return self.z0 + self.height
-
- @property
- def left_length(self):
- return self.get_length("LEFT")
-
- @property
- def right_length(self):
- return self.get_length("RIGHT")
-
- def step_size(self, step_depth):
- t_step, n_step = self.steps(step_depth)
- self.n_step = n_step
- self.t_step = t_step
- self.step_depth = step_depth
- return n_step
-
- def p3d_left(self, verts, p2d, i, t, landing=False):
- x, y = p2d
- nose_z = min(self.step_height, self.nose_z)
- zl = self.z0 + t * self.height
- zs = self.z0 + i * self.step_height
- if self.z_mode == 'LINEAR':
- z0 = max(0, zl)
- z1 = z0 - self.bottom_z
- verts.extend([(x, y, z0), (x, y, z1)])
- else:
- if "FULL" in self.steps_type:
- z0 = 0
- else:
- z0 = max(0, zl - nose_z - self.bottom_z)
- z3 = zs + max(0, self.step_height - nose_z)
- z4 = zs + self.step_height
- if landing:
- if "FULL" in self.steps_type:
- z2 = 0
- z1 = 0
- else:
- z2 = max(0, min(z3, z3 - self.bottom_z))
- z1 = z2
- else:
- z1 = min(z3, max(z0, zl - nose_z))
- z2 = min(z3, max(z1, zl))
- verts.extend([(x, y, z0),
- (x, y, z1),
- (x, y, z2),
- (x, y, z3),
- (x, y, z4)])
-
- def p3d_right(self, verts, p2d, i, t, landing=False):
- x, y = p2d
- nose_z = min(self.step_height, self.nose_z)
- zl = self.z0 + t * self.height
- zs = self.z0 + i * self.step_height
- if self.z_mode == 'LINEAR':
- z0 = max(0, zl)
- z1 = z0 - self.bottom_z
- verts.extend([(x, y, z1), (x, y, z0)])
- else:
- if "FULL" in self.steps_type:
- z0 = 0
- else:
- z0 = max(0, zl - nose_z - self.bottom_z)
- z3 = zs + max(0, self.step_height - nose_z)
- z4 = zs + self.step_height
- if landing:
- if "FULL" in self.steps_type:
- z2 = 0
- z1 = 0
- else:
- z2 = max(0, min(z3, z3 - self.bottom_z))
- z1 = z2
- else:
- z1 = min(z3, max(z0, zl - nose_z))
- z2 = min(z3, max(z1, zl))
- verts.extend([(x, y, z4),
- (x, y, z3),
- (x, y, z2),
- (x, y, z1),
- (x, y, z0)])
-
- def p3d_cstep_left(self, verts, p2d, i, t):
- x, y = p2d
- nose_z = min(self.step_height, self.nose_z)
- zs = self.z0 + i * self.step_height
- z3 = zs + max(0, self.step_height - nose_z)
- z1 = min(z3, zs - nose_z)
- verts.append((x, y, z1))
- verts.append((x, y, z3))
-
- def p3d_cstep_right(self, verts, p2d, i, t):
- x, y = p2d
- nose_z = min(self.step_height, self.nose_z)
- zs = self.z0 + i * self.step_height
- z3 = zs + max(0, self.step_height - nose_z)
- z1 = min(z3, zs - nose_z)
- verts.append((x, y, z3))
- verts.append((x, y, z1))
-
- def straight_stair(self, length):
- self.next_type = 'STAIR'
- s = self.straight(length)
- return StraightStair(s.p, s.v, self.left_offset, self.right_offset, self.steps_type,
- self.nose_type, self.z_mode, self.nose_z, self.bottom_z)
-
- def straight_landing(self, length, last_type='STAIR'):
- self.next_type = 'LANDING'
- s = self.straight(length)
- return StraightLanding(s.p, s.v, self.left_offset, self.right_offset, self.steps_type,
- self.nose_type, self.z_mode, self.nose_z, self.bottom_z, last_type=last_type)
-
- def curved_stair(self, da, radius, left_shape, right_shape, double_limit=pi):
- self.next_type = 'STAIR'
- n = self.normal(1)
- n.v = radius * n.v.normalized()
- if da < 0:
- n.v = -n.v
- a0 = n.angle
- c = n.p - n.v
- return CurvedStair(c, radius, a0, da, self.left_offset, self.right_offset,
- self.steps_type, self.nose_type, self.z_mode, self.nose_z, self.bottom_z,
- left_shape, right_shape, double_limit=double_limit)
-
- def curved_landing(self, da, radius, left_shape, right_shape, double_limit=pi, last_type='STAIR'):
- self.next_type = 'LANDING'
- n = self.normal(1)
- n.v = radius * n.v.normalized()
- if da < 0:
- n.v = -n.v
- a0 = n.angle
- c = n.p - n.v
- return CurvedLanding(c, radius, a0, da, self.left_offset, self.right_offset,
- self.steps_type, self.nose_type, self.z_mode, self.nose_z, self.bottom_z,
- left_shape, right_shape, double_limit=double_limit, last_type=last_type)
-
- def get_z(self, t, mode):
- if mode == 'LINEAR':
- return self.z0 + t * self.height
- else:
- step = 1 + floor(t / self.t_step)
- return self.z0 + step * self.step_height
-
- def make_profile(self, t, side, profile, verts, faces, matids, next=None, tnext=0):
- z0 = self.get_z(t, 'LINEAR')
- dz1 = 0
- t, part, dz0, shape = self.get_part(t, side)
- if next is not None:
- tnext, next, dz1, shape1 = next.get_part(tnext, side)
- xy, s = part.proj_xy(t, next)
- v_xy = s * xy.to_3d()
- z, s = part.proj_z(t, dz0, next, dz1)
- v_z = s * Vector((-xy.y * z.x, xy.x * z.x, z.y))
- x, y = part.lerp(t)
- verts += [Vector((x, y, z0)) + v.x * v_xy + v.y * v_z for v in profile]
-
- def project_uv(self, rM, uvs, verts, indexes, up_axis='Z'):
- if up_axis == 'Z':
- uvs.append([(rM @ Vector(verts[i])).to_2d() for i in indexes])
- elif up_axis == 'Y':
- uvs.append([(x, z) for x, y, z in [(rM @ Vector(verts[i])) for i in indexes]])
- else:
- uvs.append([(y, z) for x, y, z in [(rM @ Vector(verts[i])) for i in indexes]])
-
- def get_proj_matrix(self, part, t, nose_y):
- # a matrix to project verts
- # into uv space for horizontal parts of this step
- # so uv = (rM @ vertex).to_2d()
- tl = t - nose_y / self.get_length("LEFT")
- tr = t - nose_y / self.get_length("RIGHT")
- t2, part, dz, shape = self.get_part(tl, "LEFT")
- p0 = part.lerp(t2)
- t2, part, dz, shape = self.get_part(tr, "RIGHT")
- p1 = part.lerp(t2)
- v = (p1 - p0).normalized()
- return Matrix([
- [-v.y, v.x, 0, p0.x],
- [v.x, v.y, 0, p0.y],
- [0, 0, 1, 0],
- [0, 0, 0, 1]
- ]).inverted()
-
- def _make_nose(self, i, s, verts, faces, matids, uvs, nose_y):
-
- t = self.t_step * i
-
- # a matrix to project verts
- # into uv space for horizontal parts of this step
- # so uv = (rM @ vertex).to_2d()
- rM = self.get_proj_matrix(self, t, nose_y)
-
- if self.z_mode == 'LINEAR':
- return rM
-
- f = len(verts)
-
- tl = t - nose_y / self.get_length("LEFT")
- tr = t - nose_y / self.get_length("RIGHT")
-
- t2, part, dz, shape = self.get_part(tl, "LEFT")
- p0 = part.lerp(t2)
- self.p3d_left(verts, p0, s, t2)
-
- t2, part, dz, shape = self.get_part(tr, "RIGHT")
- p1 = part.lerp(t2)
- self.p3d_right(verts, p1, s, t2)
-
- start = 3
- end = 6
- offset = 10
-
- # left, top, right
- matids.extend([self.idmat_step_side,
- self.idmat_top,
- self.idmat_step_side])
-
- faces += [(f + j, f + j + 1, f + j + offset + 1, f + j + offset) for j in range(start, end)]
-
- u = nose_y
- v = (p1 - p0).length
- w = verts[f + 2][2] - verts[f + 3][2]
- s = int((end - start) / 2)
-
- uvs += [[(u, verts[f + j][2]), (u, verts[f + j + 1][2]),
- (0, verts[f + j + 1][2]), (0, verts[f + j][2])] for j in range(start, start + s)]
-
- uvs.append([(0, 0), (0, v), (u, v), (u, 0)])
-
- uvs += [[(u, verts[f + j][2]), (u, verts[f + j + 1][2]),
- (0, verts[f + j + 1][2]), (0, verts[f + j][2])] for j in range(start + s + 1, end)]
-
- if 'STRAIGHT' in self.nose_type or 'OPEN' in self.steps_type:
- # face bottom
- matids.append(self.idmat_bottom)
- faces.append((f + end, f + start, f + offset + start, f + offset + end))
- uvs.append([(u, v), (u, 0), (0, 0), (0, v)])
-
- if self.steps_type != 'OPEN':
- if 'STRAIGHT' in self.nose_type:
- # front face bottom straight
- matids.append(self.idmat_raise)
- faces.append((f + 12, f + 17, f + 16, f + 13))
- uvs.append([(0, w), (v, w), (v, 0), (0, 0)])
-
- elif 'OBLIQUE' in self.nose_type:
- # front face bottom oblique
- matids.append(self.idmat_raise)
- faces.append((f + 12, f + 17, f + 6, f + 3))
-
- uvs.append([(0, w), (v, w), (v, 0), (0, 0)])
-
- matids.append(self.idmat_side)
- faces.append((f + 3, f + 13, f + 12))
- uvs.append([(0, 0), (u, 0), (u, w)])
-
- matids.append(self.idmat_side)
- faces.append((f + 6, f + 17, f + 16))
- uvs.append([(0, 0), (u, w), (u, 0)])
-
- # front face top
- w = verts[f + 3][2] - verts[f + 4][2]
- matids.append(self.idmat_step_front)
- faces.append((f + 4, f + 3, f + 6, f + 5))
- uvs.append([(0, 0), (0, w), (v, w), (v, 0)])
- return rM
-
- def make_faces(self, f, rM, verts, faces, matids, uvs):
-
- if self.z_mode == 'LINEAR':
- start = 0
- end = 3
- offset = 4
- matids.extend([self.idmat_side,
- self.idmat_top,
- self.idmat_side,
- self.idmat_bottom])
- elif "OPEN" in self.steps_type:
- # faces dessus-dessous-lateral marches fermees
- start = 3
- end = 6
- offset = 10
- matids.extend([self.idmat_step_side,
- self.idmat_top,
- self.idmat_step_side,
- self.idmat_bottom])
- else:
- # faces dessus-dessous-lateral marches fermees
- start = 0
- end = 9
- offset = 10
- matids.extend([self.idmat_side,
- self.idmat_side,
- self.idmat_side,
- self.idmat_step_side,
- self.idmat_top,
- self.idmat_step_side,
- self.idmat_side,
- self.idmat_side,
- self.idmat_side,
- self.idmat_bottom])
-
- u_l0 = 0
- u_l1 = self.t_step * self.left_length
- u_r0 = 0
- u_r1 = self.t_step * self.right_length
-
- s = int((end - start) / 2)
- uvs += [[(u_l0, verts[f + j][2]), (u_l0, verts[f + j + 1][2]),
- (u_l1, verts[f + j + offset + 1][2]), (u_l1, verts[f + j + offset][2])] for j in range(start, start + s)]
-
- self.project_uv(rM, uvs, verts, [f + start + s, f + start + s + 1,
- f + start + s + offset + 1, f + start + s + offset])
-
- uvs += [[(u_r0, verts[f + j][2]), (u_r0, verts[f + j + 1][2]),
- (u_r1, verts[f + j + offset + 1][2]), (u_r1, verts[f + j + offset][2])] for j in range(start + s + 1, end)]
-
- self.project_uv(rM, uvs, verts, [f + end, f + start, f + offset + start, f + offset + end])
-
- faces += [(f + j, f + j + 1, f + j + offset + 1, f + j + offset) for j in range(start, end)]
- faces.append((f + end, f + start, f + offset + start, f + offset + end))
-
-
-class StraightStair(Stair, Line):
- def __init__(self, p, v, left_offset, right_offset, steps_type, nose_type, z_mode, nose_z, bottom_z):
- Stair.__init__(self, left_offset, right_offset, steps_type, nose_type, z_mode, nose_z, bottom_z)
- Line.__init__(self, p, v)
- self.l_line = self.offset(-left_offset)
- self.r_line = self.offset(right_offset)
-
- def make_step(self, i, verts, faces, matids, uvs, nose_y=0):
-
- rM = self._make_nose(i, i, verts, faces, matids, uvs, nose_y)
-
- t0 = self.t_step * i
-
- f = len(verts)
-
- p = self.l_line.lerp(t0)
- self.p3d_left(verts, p, i, t0)
- p = self.r_line.lerp(t0)
- self.p3d_right(verts, p, i, t0)
-
- t1 = t0 + self.t_step
-
- p = self.l_line.lerp(t1)
- self.p3d_left(verts, p, i, t1)
- p = self.r_line.lerp(t1)
- self.p3d_right(verts, p, i, t1)
-
- self.make_faces(f, rM, verts, faces, matids, uvs)
-
- if "OPEN" in self.steps_type:
- faces.append((f + 13, f + 14, f + 15, f + 16))
- matids.append(self.idmat_step_front)
- uvs.append([(0, 0), (0, 1), (1, 1), (1, 0)])
-
- def get_length(self, side):
- return self.length
-
- def get_lerp_vect(self, posts, side, i, t_step, respect_edges, z_offset=0, t0_abs=None):
- if t0_abs is not None:
- t0 = t0_abs
- else:
- t0 = i * t_step
- t, part, dz, shape = self.get_part(t0, side)
- dz /= part.length
- n = part.normal(t)
- z0 = self.get_z(t0, 'STEP')
- z1 = self.get_z(t0, 'LINEAR')
- posts.append((n, dz, z0, z1 + t0 * z_offset))
- return [t0]
-
- def n_posts(self, post_spacing, side, respect_edges):
- return self.steps(post_spacing)
-
- def get_part(self, t, side):
- if side == 'LEFT':
- part = self.l_line
- else:
- part = self.r_line
- return t, part, self.height, 'LINE'
-
-
-class CurvedStair(Stair, Arc):
- def __init__(self, c, radius, a0, da, left_offset, right_offset, steps_type, nose_type,
- z_mode, nose_z, bottom_z, left_shape, right_shape, double_limit=pi):
-
- Stair.__init__(self, left_offset, right_offset, steps_type, nose_type, z_mode, nose_z, bottom_z)
- Arc.__init__(self, c, radius, a0, da)
- self.l_shape = left_shape
- self.r_shape = right_shape
- self.edges_multiples = round(abs(da), 6) > double_limit
- # left arc, tangent at start and end
- self.l_arc, self.l_t0, self.l_t1, self.l_tc = self.set_offset(-left_offset, left_shape)
- self.r_arc, self.r_t0, self.r_t1, self.r_tc = self.set_offset(right_offset, right_shape)
-
- def set_offset(self, offset, shape):
- arc = self.offset(offset)
- t0 = arc.tangeant(0, 1)
- t1 = arc.tangeant(1, 1)
- tc = arc.tangeant(0.5, 1)
- if self.edges_multiples:
- i, p, t = t0.intersect(tc)
- tc.v *= 2 * t
- tc.p = p
- i, p, t2 = tc.intersect(t1)
- else:
- i, p, t = t0.intersect(t1)
- t0.v *= t
- t1.p = p
- t1.v *= t
- return arc, t0, t1, tc
-
- def get_length(self, side):
- if side == 'RIGHT':
- arc = self.r_arc
- shape = self.r_shape
- t0 = self.r_t0
- else:
- arc = self.l_arc
- shape = self.l_shape
- t0 = self.l_t0
- if shape == 'CIRCLE':
- return arc.length
- else:
- if self.edges_multiples:
- # two edges
- return t0.length * 4
- else:
- return t0.length * 2
-
- def _make_step(self, t_step, i, s, verts, landing=False):
-
- tb = t_step * i
-
- f = len(verts)
-
- t, part, dz, shape = self.get_part(tb, "LEFT")
- p = part.lerp(t)
- self.p3d_left(verts, p, s, tb, landing)
-
- t, part, dz, shape = self.get_part(tb, "RIGHT")
- p = part.lerp(t)
- self.p3d_right(verts, p, s, tb, landing)
- return f
-
- def _make_edge(self, t_step, i, j, f, rM, verts, faces, matids, uvs):
- tb = t_step * i
- # make edges verts after regular ones
- if self.l_shape != 'CIRCLE' or self.r_shape != 'CIRCLE':
- if self.edges_multiples:
- # edge 1
- if tb < 0.25 and tb + t_step > 0.25:
- f0 = f
- f = len(verts)
- if self.l_shape == 'CIRCLE':
- self.p3d_left(verts, self.l_arc.lerp(0.25), j, 0.25)
- else:
- self.p3d_left(verts, self.l_tc.p, j, 0.25)
- if self.r_shape == 'CIRCLE':
- self.p3d_right(verts, self.r_arc.lerp(0.25), j, 0.25)
- else:
- self.p3d_right(verts, self.r_tc.p, j, 0.25)
- self.make_faces(f0, rM, verts, faces, matids, uvs)
- # edge 2
- if tb < 0.75 and tb + t_step > 0.75:
- f0 = f
- f = len(verts)
- if self.l_shape == 'CIRCLE':
- self.p3d_left(verts, self.l_arc.lerp(0.75), j, 0.75)
- else:
- self.p3d_left(verts, self.l_t1.p, j, 0.75)
- if self.r_shape == 'CIRCLE':
- self.p3d_right(verts, self.r_arc.lerp(0.75), j, 0.75)
- else:
- self.p3d_right(verts, self.r_t1.p, j, 0.75)
- self.make_faces(f0, rM, verts, faces, matids, uvs)
- else:
- if tb < 0.5 and tb + t_step > 0.5:
- f0 = f
- f = len(verts)
- # the step goes through the edge
- if self.l_shape == 'CIRCLE':
- self.p3d_left(verts, self.l_arc.lerp(0.5), j, 0.5)
- else:
- self.p3d_left(verts, self.l_t1.p, j, 0.5)
- if self.r_shape == 'CIRCLE':
- self.p3d_right(verts, self.r_arc.lerp(0.5), j, 0.5)
- else:
- self.p3d_right(verts, self.r_t1.p, j, 0.5)
- self.make_faces(f0, rM, verts, faces, matids, uvs)
- return f
-
- def make_step(self, i, verts, faces, matids, uvs, nose_y=0):
-
- # open stair with closed face
-
- # step nose
- rM = self._make_nose(i, i, verts, faces, matids, uvs, nose_y)
- f = 0
- if self.l_shape == 'CIRCLE' or self.r_shape == 'CIRCLE':
- # every 6 degree
- n_subs = max(1, int(abs(self.da) / pi * 30 / self.n_step))
- t_step = self.t_step / n_subs
- for j in range(n_subs):
- f0 = f
- f = self._make_step(t_step, n_subs * i + j, i, verts)
- if j > 0:
- self.make_faces(f0, rM, verts, faces, matids, uvs)
- f = self._make_edge(t_step, n_subs * i + j, i, f, rM, verts, faces, matids, uvs)
- else:
- f = self._make_step(self.t_step, i, i, verts)
- f = self._make_edge(self.t_step, i, i, f, rM, verts, faces, matids, uvs)
-
- self._make_step(self.t_step, i + 1, i, verts)
- self.make_faces(f, rM, verts, faces, matids, uvs)
-
- if "OPEN" in self.steps_type and self.z_mode != 'LINEAR':
- # back face top
- faces.append((f + 13, f + 14, f + 15, f + 16))
- matids.append(self.idmat_step_front)
- uvs.append([(0, 0), (0, 1), (1, 1), (1, 0)])
-
- def get_part(self, t, side):
- if side == 'RIGHT':
- arc = self.r_arc
- shape = self.r_shape
- t0, t1, tc = self.r_t0, self.r_t1, self.r_tc
- else:
- arc = self.l_arc
- shape = self.l_shape
- t0, t1, tc = self.l_t0, self.l_t1, self.l_tc
- if shape == 'CIRCLE':
- return t, arc, self.height, shape
- else:
- if self.edges_multiples:
- # two edges
- if t <= 0.25:
- return 4 * t, t0, 0.25 * self.height, shape
- elif t <= 0.75:
- return 2 * (t - 0.25), tc, 0.5 * self.height, shape
- else:
- return 4 * (t - 0.75), t1, 0.25 * self.height, shape
- else:
- if t <= 0.5:
- return 2 * t, t0, 0.5 * self.height, shape
- else:
- return 2 * (t - 0.5), t1, 0.5 * self.height, shape
-
- def get_lerp_vect(self, posts, side, i, t_step, respect_edges, z_offset=0, t0_abs=None):
- if t0_abs is not None:
- t0 = t0_abs
- else:
- t0 = i * t_step
- res = [t0]
- t1 = t0 + t_step
- zs = self.get_z(t0, 'STEP')
- zl = self.get_z(t0, 'LINEAR')
-
- # vect normal
- t, part, dz, shape = self.get_part(t0, side)
- n = part.normal(t)
- dz /= part.length
- posts.append((n, dz, zs, zl + t0 * z_offset))
-
- if shape != 'CIRCLE' and respect_edges:
- if self.edges_multiples:
- if t0 < 0.25 and t1 > 0.25:
- zs = self.get_z(0.25, 'STEP')
- zl = self.get_z(0.25, 'LINEAR')
- t, part, dz, shape = self.get_part(0.25, side)
- n = part.normal(1)
- posts.append((n, dz, zs, zl + 0.25 * z_offset))
- res.append(0.25)
- if t0 < 0.75 and t1 > 0.75:
- zs = self.get_z(0.75, 'STEP')
- zl = self.get_z(0.75, 'LINEAR')
- t, part, dz, shape = self.get_part(0.75, side)
- n = part.normal(1)
- posts.append((n, dz, zs, zl + 0.75 * z_offset))
- res.append(0.75)
- elif t0 < 0.5 and t1 > 0.5:
- zs = self.get_z(0.5, 'STEP')
- zl = self.get_z(0.5, 'LINEAR')
- t, part, dz, shape = self.get_part(0.5, side)
- n = part.normal(1)
- posts.append((n, dz, zs, zl + 0.5 * z_offset))
- res.append(0.5)
- return res
-
- def n_posts(self, post_spacing, side, respect_edges):
- if side == 'LEFT':
- arc, t0, shape = self.l_arc, self.l_t0, self.l_shape
- else:
- arc, t0, shape = self.r_arc, self.r_t0, self.r_shape
- step_factor = 1
- if shape == 'CIRCLE':
- length = arc.length
- else:
- if self.edges_multiples:
- if respect_edges:
- step_factor = 2
- length = 4 * t0.length
- else:
- length = 2 * t0.length
- steps = step_factor * max(1, round(length / post_spacing, 0))
- # print("respect_edges:%s t_step:%s n_step:%s" % (respect_edges, 1.0 / steps, int(steps)))
- return 1.0 / steps, int(steps)
-
-
-class StraightLanding(StraightStair):
- def __init__(self, p, v, left_offset, right_offset, steps_type,
- nose_type, z_mode, nose_z, bottom_z, last_type='STAIR'):
-
- StraightStair.__init__(self, p, v, left_offset, right_offset, steps_type,
- nose_type, z_mode, nose_z, bottom_z)
-
- self.last_type = last_type
-
- @property
- def height(self):
- return 0
-
- @property
- def top_offset(self):
- return self.t_step / self.v.length
-
- @property
- def top(self):
- if self.next_type == 'LANDING':
- return self.z0
- else:
- return self.z0 + self.step_height
-
- def step_size(self, step_depth):
- self.n_step = 1
- self.t_step = 1
- self.step_depth = step_depth
- if self.last_type == 'LANDING':
- return 0
- else:
- return 1
-
- def make_step(self, i, verts, faces, matids, uvs, nose_y=0):
-
- if i == 0 and self.last_type != 'LANDING':
- rM = self._make_nose(i, 0, verts, faces, matids, uvs, nose_y)
- else:
- rM = self.get_proj_matrix(self.l_line, self.t_step * i, nose_y)
-
- f = len(verts)
- j = 0
- t0 = self.t_step * i
-
- p = self.l_line.lerp(t0)
- self.p3d_left(verts, p, j, t0)
-
- p = self.r_line.lerp(t0)
- self.p3d_right(verts, p, j, t0)
-
- t1 = t0 + self.t_step
- p = self.l_line.lerp(t1)
- self.p3d_left(verts, p, j, t1, self.next_type != 'LANDING')
-
- p = self.r_line.lerp(t1)
- self.p3d_right(verts, p, j, t1, self.next_type != 'LANDING')
-
- self.make_faces(f, rM, verts, faces, matids, uvs)
-
- if "OPEN" in self.steps_type and self.next_type != 'LANDING':
- faces.append((f + 13, f + 14, f + 15, f + 16))
- matids.append(self.idmat_step_front)
- uvs.append([(0, 0), (0, 1), (1, 1), (1, 0)])
-
- def straight_landing(self, length):
- return Stair.straight_landing(self, length, last_type='LANDING')
-
- def curved_landing(self, da, radius, left_shape, right_shape, double_limit=pi):
- return Stair.curved_landing(self, da, radius, left_shape,
- right_shape, double_limit=double_limit, last_type='LANDING')
-
- def get_z(self, t, mode):
- if mode == 'STEP':
- return self.z0 + self.step_height
- else:
- return self.z0
-
-
-class CurvedLanding(CurvedStair):
- def __init__(self, c, radius, a0, da, left_offset, right_offset, steps_type,
- nose_type, z_mode, nose_z, bottom_z, left_shape, right_shape, double_limit=pi, last_type='STAIR'):
-
- CurvedStair.__init__(self, c, radius, a0, da, left_offset, right_offset, steps_type,
- nose_type, z_mode, nose_z, bottom_z, left_shape, right_shape, double_limit=double_limit)
-
- self.last_type = last_type
-
- @property
- def top_offset(self):
- if self.l_shape == 'CIRCLE' or self.r_shape == 'CIRCLE':
- return self.t_step / self.step_depth
- else:
- if self.edges_multiples:
- return 0.5 / self.length
- else:
- return 1 / self.length
-
- @property
- def height(self):
- return 0
-
- @property
- def top(self):
- if self.next_type == 'LANDING':
- return self.z0
- else:
- return self.z0 + self.step_height
-
- def step_size(self, step_depth):
- if self.l_shape == 'CIRCLE' or self.r_shape == 'CIRCLE':
- t_step, n_step = self.steps(step_depth)
- else:
- if self.edges_multiples:
- t_step, n_step = 0.5, 2
- else:
- t_step, n_step = 1, 1
- self.n_step = n_step
- self.t_step = t_step
- self.step_depth = step_depth
- if self.last_type == 'LANDING':
- return 0
- else:
- return 1
-
- def make_step(self, i, verts, faces, matids, uvs, nose_y=0):
-
- if i == 0 and 'LANDING' not in self.last_type:
- rM = self._make_nose(i, 0, verts, faces, matids, uvs, nose_y)
- else:
- rM = self.get_proj_matrix(self.l_arc, self.t_step * i, nose_y)
-
- f = len(verts)
-
- if self.l_shape == 'CIRCLE' or self.r_shape == 'CIRCLE':
- n_subs = max(1, int(abs(self.da / pi * 30 / self.n_step)))
- t_step = self.t_step / n_subs
- for j in range(n_subs):
- f0 = f
- f = self._make_step(t_step, n_subs * i + j, 0, verts)
- if j > 0:
- self.make_faces(f0, rM, verts, faces, matids, uvs)
- f = self._make_edge(t_step, n_subs * i + j, 0, f, rM, verts, faces, matids, uvs)
- else:
- f = self._make_step(self.t_step, i, 0, verts)
- f = self._make_edge(self.t_step, i, 0, f, rM, verts, faces, matids, uvs)
-
- self._make_step(self.t_step, i + 1, 0, verts, i == self.n_step - 1 and 'LANDING' not in self.next_type)
- self.make_faces(f, rM, verts, faces, matids, uvs)
-
- if "OPEN" in self.steps_type and 'LANDING' not in self.next_type:
- faces.append((f + 13, f + 14, f + 15, f + 16))
- matids.append(self.idmat_step_front)
- uvs.append([(0, 0), (0, 1), (1, 1), (1, 0)])
-
- def straight_landing(self, length):
- return Stair.straight_landing(self, length, last_type='LANDING')
-
- def curved_landing(self, da, radius, left_shape, right_shape, double_limit=pi):
- return Stair.curved_landing(self, da, radius, left_shape,
- right_shape, double_limit=double_limit, last_type='LANDING')
-
- def get_z(self, t, mode):
- if mode == 'STEP':
- return self.z0 + self.step_height
- else:
- return self.z0
-
-
-class StairGenerator():
- def __init__(self, parts):
- self.parts = parts
- self.last_type = 'NONE'
- self.stairs = []
- self.steps_type = 'NONE'
- self.sum_da = 0
- self.user_defined_post = None
- self.user_defined_uvs = None
- self.user_defined_mat = None
-
- def add_part(self, type, steps_type, nose_type, z_mode, nose_z, bottom_z, center,
- radius, da, width_left, width_right, length, left_shape, right_shape):
-
- self.steps_type = steps_type
- if len(self.stairs) < 1:
- s = None
- else:
- s = self.stairs[-1]
-
- if "S_" not in type:
- self.sum_da += da
-
- # start a new stair
- if s is None:
- if type == 'S_STAIR':
- p = Vector((0, 0))
- v = Vector((0, length))
- s = StraightStair(p, v, width_left, width_right, steps_type, nose_type, z_mode, nose_z, bottom_z)
- elif type == 'C_STAIR':
- if da < 0:
- c = Vector((radius, 0))
- else:
- c = Vector((-radius, 0))
- s = CurvedStair(c, radius, 0, da, width_left, width_right, steps_type,
- nose_type, z_mode, nose_z, bottom_z, left_shape, right_shape)
- elif type == 'D_STAIR':
- if da < 0:
- c = Vector((radius, 0))
- else:
- c = Vector((-radius, 0))
- s = CurvedStair(c, radius, 0, da, width_left, width_right, steps_type,
- nose_type, z_mode, nose_z, bottom_z, left_shape, right_shape, double_limit=0)
- elif type == 'S_LANDING':
- p = Vector((0, 0))
- v = Vector((0, length))
- s = StraightLanding(p, v, width_left, width_right, steps_type, nose_type, z_mode, nose_z, bottom_z)
- elif type == 'C_LANDING':
- if da < 0:
- c = Vector((radius, 0))
- else:
- c = Vector((-radius, 0))
- s = CurvedLanding(c, radius, 0, da, width_left, width_right, steps_type,
- nose_type, z_mode, nose_z, bottom_z, left_shape, right_shape)
- elif type == 'D_LANDING':
- if da < 0:
- c = Vector((radius, 0))
- else:
- c = Vector((-radius, 0))
- s = CurvedLanding(c, radius, 0, da, width_left, width_right, steps_type,
- nose_type, z_mode, nose_z, bottom_z, left_shape, right_shape, double_limit=0)
- else:
- if type == 'S_STAIR':
- s = s.straight_stair(length)
- elif type == 'C_STAIR':
- s = s.curved_stair(da, radius, left_shape, right_shape)
- elif type == 'D_STAIR':
- s = s.curved_stair(da, radius, left_shape, right_shape, double_limit=0)
- elif type == 'S_LANDING':
- s = s.straight_landing(length)
- elif type == 'C_LANDING':
- s = s.curved_landing(da, radius, left_shape, right_shape)
- elif type == 'D_LANDING':
- s = s.curved_landing(da, radius, left_shape, right_shape, double_limit=0)
- self.stairs.append(s)
- self.last_type = type
-
- def n_steps(self, step_depth):
- n_steps = 0
- for stair in self.stairs:
- n_steps += stair.step_size(step_depth)
- return n_steps
-
- def set_height(self, step_height):
- z = 0
- for stair in self.stairs:
- stair.set_height(step_height, z)
- z = stair.top
-
- def make_stair(self, height, step_depth, verts, faces, matids, uvs, nose_y=0):
- n_steps = self.n_steps(step_depth)
- self.set_height(height / n_steps)
-
- for s, stair in enumerate(self.stairs):
- if s < len(self.parts):
- manipulator = self.parts[s].manipulators[0]
- # Store Gl Points for manipulators
- if 'Curved' in type(stair).__name__:
- c = stair.c
- p0 = (stair.p0 - c).to_3d()
- p1 = (stair.p1 - c).to_3d()
- manipulator.set_pts([(c.x, c.y, stair.top), p0, p1])
- manipulator.type_key = 'ARC_ANGLE_RADIUS'
- manipulator.prop1_name = 'da'
- manipulator.prop2_name = 'radius'
- else:
- if self.sum_da > 0:
- side = 1
- else:
- side = -1
- v0 = stair.p0
- v1 = stair.p1
- manipulator.set_pts([(v0.x, v0.y, stair.top), (v1.x, v1.y, stair.top), (side, 0, 0)])
- manipulator.type_key = 'SIZE'
- manipulator.prop1_name = 'length'
-
- for i in range(stair.n_step):
- stair.make_step(i, verts, faces, matids, uvs, nose_y=nose_y)
- if s < len(self.stairs) - 1 and self.steps_type != 'OPEN' and \
- 'Landing' in type(stair).__name__ and stair.next_type != "LANDING":
- f = len(verts) - 10
- faces.append((f, f + 1, f + 8, f + 9))
- matids.append(self.stairs[-1].idmat_bottom)
- u = verts[f + 1][2] - verts[f][2]
- v = (Vector(verts[f]) - Vector(verts[f + 9])).length
- uvs.append([(0, 0), (0, u), (v, u), (v, 0)])
-
- if self.steps_type != 'OPEN' and len(self.stairs) > 0:
- f = len(verts) - 10
- faces.append((f, f + 1, f + 2, f + 3, f + 4, f + 5, f + 6, f + 7, f + 8, f + 9))
- matids.append(self.stairs[-1].idmat_bottom)
- uvs.append([(0, 0), (.1, 0), (.2, 0), (.3, 0), (.4, 0), (.4, 1), (.3, 1), (.2, 1), (.1, 1), (0, 1)])
-
- def setup_user_defined_post(self, o, post_x, post_y, post_z):
- self.user_defined_post = o
- x = o.bound_box[6][0] - o.bound_box[0][0]
- y = o.bound_box[6][1] - o.bound_box[0][1]
- z = o.bound_box[6][2] - o.bound_box[0][2]
- self.user_defined_post_scale = Vector((post_x / x, post_y / -y, post_z / z))
- m = o.data
- # create vertex group lookup dictionary for names
- vgroup_names = {vgroup.index: vgroup.name for vgroup in o.vertex_groups}
- # create dictionary of vertex group assignments per vertex
- self.vertex_groups = [[vgroup_names[g.group] for g in v.groups] for v in m.vertices]
- # uvs
- uv_act = m.uv_layers.active
- if uv_act is not None:
- uv_layer = uv_act.data
- self.user_defined_uvs = [[uv_layer[li].uv for li in p.loop_indices] for p in m.polygons]
- else:
- self.user_defined_uvs = [[(0, 0) for i in p.vertices] for p in m.polygons]
- # material ids
- self.user_defined_mat = [p.material_index for p in m.polygons]
-
- def get_user_defined_post(self, tM, z0, z1, z2, slope, post_z, verts, faces, matids, uvs):
- f = len(verts)
- m = self.user_defined_post.data
- for i, g in enumerate(self.vertex_groups):
- co = m.vertices[i].co.copy()
- co.x *= self.user_defined_post_scale.x
- co.y *= self.user_defined_post_scale.y
- co.z *= self.user_defined_post_scale.z
- if 'Top' in g:
- co.z += z2
- elif 'Bottom' in g:
- co.z += 0
- else:
- co.z += z1
- if 'Slope' in g:
- co.z += co.y * slope
- verts.append(tM @ co)
- matids += self.user_defined_mat
- faces += [tuple([i + f for i in p.vertices]) for p in m.polygons]
- uvs += self.user_defined_uvs
-
- def get_post(self, post, post_x, post_y, post_z, post_alt, sub_offset_x,
- id_mat, verts, faces, matids, uvs, bottom="STEP"):
-
- n, dz, zs, zl = post
- slope = dz * post_y
-
- if self.user_defined_post is not None:
- if bottom == "STEP":
- z0 = zs
- else:
- z0 = zl
- z1 = zl - z0
- z2 = zl - z0
- x, y = -n.v.normalized()
- tM = Matrix([
- [x, y, 0, n.p.x],
- [y, -x, 0, n.p.y],
- [0, 0, 1, z0 + post_alt],
- [0, 0, 0, 1]
- ])
- self.get_user_defined_post(tM, z0, z1, z2, dz, post_z, verts, faces, matids, uvs)
- return
-
- z3 = zl + post_z + post_alt - slope
- z4 = zl + post_z + post_alt + slope
- if bottom == "STEP":
- z0 = zs + post_alt
- z1 = zs + post_alt
- else:
- z0 = zl + post_alt - slope
- z1 = zl + post_alt + slope
- vn = n.v.normalized()
- dx = post_x * vn
- dy = post_y * Vector((vn.y, -vn.x))
- oy = sub_offset_x * vn
- x0, y0 = n.p - dx + dy + oy
- x1, y1 = n.p - dx - dy + oy
- x2, y2 = n.p + dx - dy + oy
- x3, y3 = n.p + dx + dy + oy
- f = len(verts)
- verts.extend([(x0, y0, z0), (x0, y0, z3),
- (x1, y1, z1), (x1, y1, z4),
- (x2, y2, z1), (x2, y2, z4),
- (x3, y3, z0), (x3, y3, z3)])
- faces.extend([(f, f + 1, f + 3, f + 2),
- (f + 2, f + 3, f + 5, f + 4),
- (f + 4, f + 5, f + 7, f + 6),
- (f + 6, f + 7, f + 1, f),
- (f, f + 2, f + 4, f + 6),
- (f + 7, f + 5, f + 3, f + 1)])
- matids.extend([id_mat, id_mat, id_mat, id_mat, id_mat, id_mat])
- x = [(0, 0), (0, post_z), (post_x, post_z), (post_x, 0)]
- y = [(0, 0), (0, post_z), (post_y, post_z), (post_y, 0)]
- z = [(0, 0), (post_x, 0), (post_x, post_y), (0, post_y)]
- uvs.extend([x, y, x, y, z, z])
-
- def get_panel(self, subs, altitude, panel_x, panel_z, sub_offset_x, idmat, verts, faces, matids, uvs):
- n_subs = len(subs)
- if n_subs < 1:
- return
- f = len(verts)
- x0 = sub_offset_x - 0.5 * panel_x
- x1 = sub_offset_x + 0.5 * panel_x
- z0 = 0
- z1 = panel_z
- profile = [Vector((x0, z0)), Vector((x1, z0)), Vector((x1, z1)), Vector((x0, z1))]
- user_path_uv_v = []
- n_sections = n_subs - 1
- n, dz, zs, zl = subs[0]
- p0 = n.p
- v0 = n.v.normalized()
- for s, section in enumerate(subs):
- n, dz, zs, zl = section
- p1 = n.p
- if s < n_sections:
- v1 = subs[s + 1][0].v.normalized()
- dir = (v0 + v1).normalized()
- scale = 1 / cos(0.5 * acos(min(1, max(-1, v0.dot(v1)))))
- for p in profile:
- x, y = n.p + scale * p.x * dir
- z = zl + p.y + altitude
- verts.append((x, y, z))
- if s > 0:
- user_path_uv_v.append((p1 - p0).length)
- p0 = p1
- v0 = v1
-
- # build faces using Panel
- lofter = Lofter(
- # closed_shape, index, x, y, idmat
- True,
- [i for i in range(len(profile))],
- [p.x for p in profile],
- [p.y for p in profile],
- [idmat for i in range(len(profile))],
- closed_path=False,
- user_path_uv_v=user_path_uv_v,
- user_path_verts=n_subs
- )
- faces += lofter.faces(16, offset=f, path_type='USER_DEFINED')
- matids += lofter.mat(16, idmat, idmat, path_type='USER_DEFINED')
- v = Vector((0, 0))
- uvs += lofter.uv(16, v, v, v, v, 0, v, 0, 0, path_type='USER_DEFINED')
-
- def reset_shapes(self):
- for s, stair in enumerate(self.stairs):
- if 'Curved' in type(stair).__name__:
- stair.l_shape = self.parts[s].left_shape
- stair.r_shape = self.parts[s].right_shape
-
- def make_subs(self, height, step_depth, x, y, z, post_y, altitude, bottom, side, slice,
- post_spacing, sub_spacing, respect_edges, move_x, x_offset, sub_offset_x, mat,
- verts, faces, matids, uvs):
-
- n_steps = self.n_steps(step_depth)
- self.set_height(height / n_steps)
- n_stairs = len(self.stairs) - 1
- subs = []
-
- if side == "LEFT":
- offset = move_x - x_offset
- # offset_sub = offset - sub_offset_x
- else:
- offset = move_x + x_offset
- # offset_sub = offset + sub_offset_x
-
- for s, stair in enumerate(self.stairs):
- if 'Curved' in type(stair).__name__:
- if side == "LEFT":
- part = stair.l_arc
- shape = stair.l_shape
- else:
- part = stair.r_arc
- shape = stair.r_shape
- # Note: use left part as reference for post distances
- # use right part as reference for panels
- stair.l_arc, stair.l_t0, stair.l_t1, stair.l_tc = stair.set_offset(offset, shape)
- stair.r_arc, stair.r_t0, stair.r_t1, stair.r_tc = stair.set_offset(offset, shape)
- else:
- stair.l_line = stair.offset(offset)
- stair.r_line = stair.offset(offset)
- part = stair.l_line
-
- lerp_z = 0
- edge_t = 1
- edge_size = 0
- # interpolate z near end landing
- if 'Landing' in type(stair).__name__ and stair.next_type == 'STAIR':
- if not slice:
- line = stair.normal(1).offset(self.stairs[s + 1].step_depth)
- res, p, t_part = part.intersect(line)
- # does perpendicular line intersects circle ?
- if res:
- edge_size = self.stairs[s + 1].step_depth / stair.get_length(side)
- edge_t = 1 - edge_size
- else:
- # in this case, lerp z over one step
- lerp_z = stair.step_height
-
- t_step, n_step = stair.n_posts(post_spacing, side, respect_edges)
-
- # space between posts
- sp = stair.get_length(side)
- # post size
- t_post = post_y / sp
-
- if s == n_stairs:
- n_step += 1
- for i in range(n_step):
- res_t = stair.get_lerp_vect([], side, i, t_step, respect_edges)
- # subs
- if s < n_stairs or i < n_step - 1:
- res_t.append((i + 1) * t_step)
- for j in range(len(res_t) - 1):
- t0 = res_t[j] + t_post
- t1 = res_t[j + 1] - t_post
- dt = t1 - t0
- n_subs = int(sp * dt / sub_spacing)
- if n_subs > 0:
- t_subs = dt / n_subs
- for k in range(1, n_subs):
- t = t0 + k * t_subs
- stair.get_lerp_vect(subs, side, 1, t0 + k * t_subs, False)
- if t > edge_t:
- n, dz, z0, z1 = subs[-1]
- subs[-1] = n, dz, z0, z1 + (t - edge_t) / edge_size * stair.step_height
- if lerp_z > 0:
- n, dz, z0, z1 = subs[-1]
- subs[-1] = n, dz, z0, z1 + t * stair.step_height
-
- for i, post in enumerate(subs):
- self.get_post(post, x, y, z, altitude, sub_offset_x, mat, verts, faces, matids, uvs, bottom=bottom)
-
- def make_post(self, height, step_depth, x, y, z, altitude, side, post_spacing, respect_edges, move_x, x_offset, mat,
- verts, faces, matids, uvs):
- n_steps = self.n_steps(step_depth)
- self.set_height(height / n_steps)
- l_posts = []
- n_stairs = len(self.stairs) - 1
-
- for s, stair in enumerate(self.stairs):
- if type(stair).__name__ in ['CurvedStair', 'CurvedLanding']:
- stair.l_arc, stair.l_t0, stair.l_t1, stair.l_tc = stair.set_offset(move_x - x_offset, stair.l_shape)
- stair.r_arc, stair.r_t0, stair.r_t1, stair.r_tc = stair.set_offset(move_x + x_offset, stair.r_shape)
- else:
- stair.l_line = stair.offset(move_x - x_offset)
- stair.r_line = stair.offset(move_x + x_offset)
-
- t_step, n_step = stair.n_posts(post_spacing, side, respect_edges)
-
- if s == n_stairs:
- n_step += 1
- for i in range(n_step):
- stair.get_lerp_vect(l_posts, side, i, t_step, respect_edges)
-
- if s == n_stairs and i == n_step - 1:
- n, dz, z0, z1 = l_posts[-1]
- l_posts[-1] = (n, dz, z0 - stair.step_height, z1)
-
- for i, post in enumerate(l_posts):
- self.get_post(post, x, y, z, altitude, 0, mat, verts, faces, matids, uvs)
-
- def make_panels(self, height, step_depth, x, z, post_y, altitude, side, post_spacing,
- panel_dist, respect_edges, move_x, x_offset, sub_offset_x, mat, verts, faces, matids, uvs):
-
- n_steps = self.n_steps(step_depth)
- self.set_height(height / n_steps)
- subs = []
- n_stairs = len(self.stairs) - 1
-
- if side == "LEFT":
- offset = move_x - x_offset
- else:
- offset = move_x + x_offset
-
- for s, stair in enumerate(self.stairs):
-
- is_circle = False
- if 'Curved' in type(stair).__name__:
- if side == "LEFT":
- is_circle = stair.l_shape == "CIRCLE"
- shape = stair.l_shape
- else:
- is_circle = stair.r_shape == "CIRCLE"
- shape = stair.r_shape
- stair.l_arc, stair.l_t0, stair.l_t1, stair.l_tc = stair.set_offset(offset, shape)
- stair.r_arc, stair.r_t0, stair.r_t1, stair.r_tc = stair.set_offset(offset, shape)
- else:
- stair.l_line = stair.offset(offset)
- stair.r_line = stair.offset(offset)
-
- # space between posts
- sp = stair.get_length(side)
-
- t_step, n_step = stair.n_posts(post_spacing, side, respect_edges)
-
- if is_circle and 'Curved' in type(stair).__name__:
- panel_da = abs(stair.da) / pi * 180 / n_step
- panel_step = max(1, int(panel_da / 6))
- else:
- panel_step = 1
-
- # post size
- t_post = (post_y + panel_dist) / sp
-
- if s == n_stairs:
- n_step += 1
- for i in range(n_step):
- res_t = stair.get_lerp_vect([], side, i, t_step, respect_edges)
- # subs
- if s < n_stairs or i < n_step - 1:
- res_t.append((i + 1) * t_step)
- for j in range(len(res_t) - 1):
- t0 = res_t[j] + t_post
- t1 = res_t[j + 1] - t_post
- dt = t1 - t0
- t_curve = dt / panel_step
- if dt > 0:
- panel = []
- for k in range(panel_step):
- stair.get_lerp_vect(panel, side, 1, t_curve, True, t0_abs=t0 + k * t_curve)
- stair.get_lerp_vect(panel, side, 1, t1, False)
- subs.append(panel)
- for sub in subs:
- self.get_panel(sub, altitude, x, z, sub_offset_x, mat, verts, faces, matids, uvs)
-
- def make_part(self, height, step_depth, part_x, part_z, x_move, x_offset,
- z_offset, z_mode, steps_type, verts, faces, matids, uvs):
-
- params = [(stair.z_mode, stair.l_shape, stair.r_shape,
- stair.bottom_z, stair.steps_type) for stair in self.stairs]
-
- for stair in self.stairs:
- if x_offset > 0:
- stair.l_shape = stair.r_shape
- else:
- stair.r_shape = stair.l_shape
- stair.steps_type = steps_type
- stair.z_mode = "LINEAR"
- stair.bottom_z = part_z
- if 'Curved' in type(stair).__name__:
- stair.l_arc, stair.l_t0, stair.l_t1, stair.l_tc = \
- stair.set_offset(x_move + x_offset + 0.5 * part_x, stair.l_shape)
- stair.r_arc, stair.r_t0, stair.r_t1, stair.r_tc = \
- stair.set_offset(x_move + x_offset - 0.5 * part_x, stair.r_shape)
- else:
- stair.l_line = stair.offset(x_move + x_offset + 0.5 * part_x)
- stair.r_line = stair.offset(x_move + x_offset - 0.5 * part_x)
- n_steps = self.n_steps(step_depth)
- self.set_height(height / n_steps)
- for j, stair in enumerate(self.stairs):
- stair.z0 += z_offset + part_z
- stair.n_step *= 2
- stair.t_step /= 2
- stair.step_height /= 2
- for i in range(stair.n_step):
- stair.make_step(i, verts, faces, matids, uvs, nose_y=0)
- stair.n_step /= 2
- stair.t_step *= 2
- stair.step_height *= 2
- stair.z_mode = params[j][0]
- stair.l_shape = params[j][1]
- stair.r_shape = params[j][2]
- stair.bottom_z = params[j][3]
- stair.steps_type = params[j][4]
- stair.z0 -= z_offset + part_z
-
- def make_profile(self, profile, idmat, side, slice, height, step_depth,
- x_offset, z_offset, extend, verts, faces, matids, uvs):
-
- for stair in self.stairs:
- if 'Curved' in type(stair).__name__:
- stair.l_arc, stair.l_t0, stair.l_t1, stair.l_tc = stair.set_offset(-x_offset, stair.l_shape)
- stair.r_arc, stair.r_t0, stair.r_t1, stair.r_tc = stair.set_offset(x_offset, stair.r_shape)
- else:
- stair.l_line = stair.offset(-x_offset)
- stair.r_line = stair.offset(x_offset)
-
- n_steps = self.n_steps(step_depth)
- self.set_height(height / n_steps)
-
- n_stairs = len(self.stairs) - 1
-
- if n_stairs < 0:
- return
-
- sections = []
- sections.append([])
-
- # first step
- if extend != 0:
- t = -extend / self.stairs[0].length
- self.stairs[0].get_lerp_vect(sections[-1], side, 1, t, True)
-
- for s, stair in enumerate(self.stairs):
- n_step = 1
- is_circle = False
-
- if 'Curved' in type(stair).__name__:
- if side == "LEFT":
- part = stair.l_arc
- is_circle = stair.l_shape == "CIRCLE"
- else:
- part = stair.r_arc
- is_circle = stair.r_shape == "CIRCLE"
- else:
- if side == "LEFT":
- part = stair.l_line
- else:
- part = stair.r_line
-
- if is_circle:
- n_step = 3 * stair.n_step
-
- t_step = 1 / n_step
-
- last_t = 1.0
- do_last = True
- lerp_z = 0
- # last section 1 step before stair
- if 'Landing' in type(stair).__name__ and stair.next_type == 'STAIR':
- if not slice:
- line = stair.normal(1).offset(self.stairs[s + 1].step_depth)
- res, p, t_part = part.intersect(line)
- # does perpendicular line intersects circle ?
- if res:
- last_t = 1 - self.stairs[s + 1].step_depth / stair.get_length(side)
- if last_t < 0:
- do_last = False
- else:
- # in this case, lerp z over one step
- do_last = False
- lerp_z = stair.step_height
-
- if s == n_stairs:
- n_step += 1
-
- for i in range(n_step):
- res_t = stair.get_lerp_vect(sections[-1], side, i, t_step, True, z_offset=lerp_z)
- # remove corner section
- for cur_t in res_t:
- if cur_t > 0 and cur_t > last_t:
- sections[-1] = sections[-1][:-1]
-
- # last section 1 step before next stair start
- if 'Landing' in type(stair).__name__ and stair.next_type == 'STAIR':
- if do_last:
- stair.get_lerp_vect(sections[-1], side, 1, last_t, False)
- if slice:
- sections.append([])
- if extend > 0:
- t = -extend / self.stairs[s + 1].length
- self.stairs[s + 1].get_lerp_vect(sections[-1], side, 1, t, True)
-
- t = 1 + extend / self.stairs[-1].length
- self.stairs[-1].get_lerp_vect(sections[-1], side, 1, t, True)
-
- for cur_sect in sections:
- user_path_verts = len(cur_sect)
- f = len(verts)
- if user_path_verts > 0:
- user_path_uv_v = []
- n, dz, z0, z1 = cur_sect[-1]
- cur_sect[-1] = (n, dz, z0 - stair.step_height, z1)
- n_sections = user_path_verts - 1
- n, dz, zs, zl = cur_sect[0]
- p0 = n.p
- v0 = n.v.normalized()
- for s, section in enumerate(cur_sect):
- n, dz, zs, zl = section
- p1 = n.p
- if s < n_sections:
- v1 = cur_sect[s + 1][0].v.normalized()
- dir = (v0 + v1).normalized()
- scale = 1 / cos(0.5 * acos(min(1, max(-1, v0.dot(v1)))))
- for p in profile:
- x, y = n.p + scale * p.x * dir
- z = zl + p.y + z_offset
- verts.append((x, y, z))
- if s > 0:
- user_path_uv_v.append((p1 - p0).length)
- p0 = p1
- v0 = v1
-
- # build faces using Panel
- lofter = Lofter(
- # closed_shape, index, x, y, idmat
- True,
- [i for i in range(len(profile))],
- [p.x for p in profile],
- [p.y for p in profile],
- [idmat for i in range(len(profile))],
- closed_path=False,
- user_path_uv_v=user_path_uv_v,
- user_path_verts=user_path_verts
- )
- faces += lofter.faces(16, offset=f, path_type='USER_DEFINED')
- matids += lofter.mat(16, idmat, idmat, path_type='USER_DEFINED')
- v = Vector((0, 0))
- uvs += lofter.uv(16, v, v, v, v, 0, v, 0, 0, path_type='USER_DEFINED')
-
- def set_matids(self, id_materials):
- for stair in self.stairs:
- stair.set_matids(id_materials)
-
-
-def update(self, context):
- self.update(context)
-
-
-def update_manipulators(self, context):
- self.update(context, manipulable_refresh=True)
-
-
-def update_preset(self, context):
- auto_update = self.auto_update
- self.auto_update = False
- if self.presets == 'STAIR_I':
- self.n_parts = 1
- self.update_parts()
- self.parts[0].type = 'S_STAIR'
- elif self.presets == 'STAIR_L':
- self.n_parts = 3
- self.update_parts()
- self.parts[0].type = 'S_STAIR'
- self.parts[1].type = 'C_STAIR'
- self.parts[2].type = 'S_STAIR'
- self.da = pi / 2
- elif self.presets == 'STAIR_U':
- self.n_parts = 3
- self.update_parts()
- self.parts[0].type = 'S_STAIR'
- self.parts[1].type = 'D_STAIR'
- self.parts[2].type = 'S_STAIR'
- self.da = pi
- elif self.presets == 'STAIR_O':
- self.n_parts = 2
- self.update_parts()
- self.parts[0].type = 'D_STAIR'
- self.parts[1].type = 'D_STAIR'
- self.da = pi
- # keep auto_update state same
- # prevent unwanted load_preset update
- self.auto_update = auto_update
-
-
-materials_enum = (
- ('0', 'Ceiling', '', 0),
- ('1', 'White', '', 1),
- ('2', 'Concrete', '', 2),
- ('3', 'Wood', '', 3),
- ('4', 'Metal', '', 4),
- ('5', 'Glass', '', 5)
- )
-
-
-class archipack_stair_material(PropertyGroup):
- index : EnumProperty(
- items=materials_enum,
- default='4',
- update=update
- )
-
- def find_datablock_in_selection(self, context):
- """
- find witch selected object this instance belongs to
- provide support for "copy to selected"
- """
- selected = context.selected_objects[:]
- for o in selected:
- props = archipack_stair.datablock(o)
- if props:
- for part in props.rail_mat:
- if part == self:
- return props
- return None
-
- def update(self, context):
- props = self.find_datablock_in_selection(context)
- if props is not None:
- props.update(context)
-
-
-class archipack_stair_part(PropertyGroup):
- type : EnumProperty(
- items=(
- ('S_STAIR', 'Straight stair', '', 0),
- ('C_STAIR', 'Curved stair', '', 1),
- ('D_STAIR', 'Dual Curved stair', '', 2),
- ('S_LANDING', 'Straight landing', '', 3),
- ('C_LANDING', 'Curved landing', '', 4),
- ('D_LANDING', 'Dual Curved landing', '', 5)
- ),
- default='S_STAIR',
- update=update_manipulators
- )
- length : FloatProperty(
- name="Length",
- min=0.01,
- default=2.0,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- radius : FloatProperty(
- name="Radius",
- min=0.01,
- default=0.7,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- da : FloatProperty(
- name="Angle",
- min=-pi,
- max=pi,
- default=pi / 2,
- subtype='ANGLE', unit='ROTATION',
- update=update
- )
- left_shape : EnumProperty(
- items=(
- ('RECTANGLE', 'Straight', '', 0),
- ('CIRCLE', 'Curved ', '', 1)
- ),
- default='RECTANGLE',
- update=update
- )
- right_shape : EnumProperty(
- items=(
- ('RECTANGLE', 'Straight', '', 0),
- ('CIRCLE', 'Curved ', '', 1)
- ),
- default='RECTANGLE',
- update=update
- )
- manipulators : CollectionProperty(type=archipack_manipulator)
-
- def find_datablock_in_selection(self, context):
- """
- find witch selected object this instance belongs to
- provide support for "copy to selected"
- """
- selected = context.selected_objects[:]
- for o in selected:
- props = archipack_stair.datablock(o)
- if props:
- for part in props.parts:
- if part == self:
- return props
- return None
-
- def update(self, context, manipulable_refresh=False):
- props = self.find_datablock_in_selection(context)
- if props is not None:
- props.update(context, manipulable_refresh)
-
- def draw(self, layout, context, index, user_mode):
- if user_mode:
- box = layout.box()
- row = box.row()
- row.prop(self, "type", text=str(index + 1))
- if self.type in ['C_STAIR', 'C_LANDING', 'D_STAIR', 'D_LANDING']:
- row = box.row()
- row.prop(self, "radius")
- row = box.row()
- row.prop(self, "da")
- else:
- row = box.row()
- row.prop(self, "length")
- if self.type in ['C_STAIR', 'C_LANDING', 'D_STAIR', 'D_LANDING']:
- row = box.row(align=True)
- row.prop(self, "left_shape", text="")
- row.prop(self, "right_shape", text="")
- else:
- if self.type in ['S_STAIR', 'S_LANDING']:
- box = layout.box()
- row = box.row()
- row.prop(self, "length")
-
-
-class archipack_stair(ArchipackObject, Manipulable, PropertyGroup):
-
- parts : CollectionProperty(type=archipack_stair_part)
- n_parts : IntProperty(
- name="Parts",
- min=1,
- max=32,
- default=1, update=update_manipulators
- )
- step_depth : FloatProperty(
- name="Going",
- min=0.2,
- default=0.25,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- width : FloatProperty(
- name="Width",
- min=0.01,
- default=1.2,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- height : FloatProperty(
- name="Height",
- min=0.1,
- default=2.4, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- nose_y : FloatProperty(
- name="Depth",
- min=0.0,
- default=0.02, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- x_offset : FloatProperty(
- name="Offset",
- default=0.0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- nose_z : FloatProperty(
- name="Height",
- min=0.001,
- default=0.03, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- bottom_z : FloatProperty(
- name="Thickness",
- min=0.001,
- default=0.03, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- radius : FloatProperty(
- name="Radius",
- min=0.5,
- default=0.7,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- da : FloatProperty(
- name="Angle",
- min=-pi,
- max=pi,
- default=pi / 2,
- subtype='ANGLE', unit='ROTATION',
- update=update
- )
- total_angle : FloatProperty(
- name="Angle",
- min=-50 * pi,
- max=50 * pi,
- default=2 * pi,
- subtype='ANGLE', unit='ROTATION',
- update=update
- )
- steps_type : EnumProperty(
- name="Steps",
- items=(
- ('CLOSED', 'Closed', '', 0),
- ('FULL', 'Full height', '', 1),
- ('OPEN', 'Open ', '', 2)
- ),
- default='CLOSED',
- update=update
- )
- nose_type : EnumProperty(
- name="Nosing",
- items=(
- ('STRAIGHT', 'Straight', '', 0),
- ('OBLIQUE', 'Oblique', '', 1),
- ),
- default='STRAIGHT',
- update=update
- )
- left_shape : EnumProperty(
- items=(
- ('RECTANGLE', 'Straight', '', 0),
- ('CIRCLE', 'Curved ', '', 1)
- ),
- default='RECTANGLE',
- update=update
- )
- right_shape : EnumProperty(
- items=(
- ('RECTANGLE', 'Straight', '', 0),
- ('CIRCLE', 'Curved ', '', 1)
- ),
- default='RECTANGLE',
- update=update
- )
- z_mode : EnumProperty(
- name="Interp z",
- items=(
- ('STANDARD', 'Standard', '', 0),
- ('LINEAR', 'Bottom Linear', '', 1),
- ('LINEAR_TOP', 'All Linear', '', 2)
- ),
- default='STANDARD',
- update=update
- )
- presets : EnumProperty(
- items=(
- ('STAIR_I', 'I stair', '', 0),
- ('STAIR_L', 'L stair', '', 1),
- ('STAIR_U', 'U stair', '', 2),
- ('STAIR_O', 'O stair', '', 3),
- ('STAIR_USER', 'User defined stair', '', 4),
- ),
- default='STAIR_I', update=update_preset
- )
- left_post : BoolProperty(
- name='left',
- default=True,
- update=update
- )
- right_post : BoolProperty(
- name='right',
- default=True,
- update=update
- )
- post_spacing : FloatProperty(
- name="Spacing",
- min=0.1,
- default=1.0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- post_x : FloatProperty(
- name="Width",
- min=0.001,
- default=0.04, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- post_y : FloatProperty(
- name="Length",
- min=0.001,
- default=0.04, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- post_z : FloatProperty(
- name="Height",
- min=0.001,
- default=1, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- post_alt : FloatProperty(
- name="Altitude",
- min=-100,
- default=0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- post_offset_x : FloatProperty(
- name="Offset",
- min=-100.0, max=100,
- default=0.02, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- post_corners : BoolProperty(
- name="Only on edges",
- update=update,
- default=False
- )
- user_defined_post_enable : BoolProperty(
- name="User",
- update=update,
- default=True
- )
- user_defined_post : StringProperty(
- name="User defined",
- update=update
- )
- idmat_post : EnumProperty(
- name="Post",
- items=materials_enum,
- default='4',
- update=update
- )
- left_subs : BoolProperty(
- name='left',
- default=False,
- update=update
- )
- right_subs : BoolProperty(
- name='right',
- default=False,
- update=update
- )
- subs_spacing : FloatProperty(
- name="Spacing",
- min=0.05,
- default=0.10, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- subs_x : FloatProperty(
- name="Width",
- min=0.001,
- default=0.02, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- subs_y : FloatProperty(
- name="Length",
- min=0.001,
- default=0.02, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- subs_z : FloatProperty(
- name="Height",
- min=0.001,
- default=1, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- subs_alt : FloatProperty(
- name="Altitude",
- min=-100,
- default=0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- subs_offset_x : FloatProperty(
- name="Offset",
- min=-100.0, max=100,
- default=0.0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- subs_bottom : EnumProperty(
- name="Bottom",
- items=(
- ('STEP', 'Follow step', '', 0),
- ('LINEAR', 'Linear', '', 1),
- ),
- default='STEP',
- update=update
- )
- user_defined_subs_enable : BoolProperty(
- name="User",
- update=update,
- default=True
- )
- user_defined_subs : StringProperty(
- name="User defined",
- update=update
- )
- idmat_subs : EnumProperty(
- name="Subs",
- items=materials_enum,
- default='4',
- update=update
- )
- left_panel : BoolProperty(
- name='left',
- default=True,
- update=update
- )
- right_panel : BoolProperty(
- name='right',
- default=True,
- update=update
- )
- panel_alt : FloatProperty(
- name="Altitude",
- default=0.25, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- panel_x : FloatProperty(
- name="Width",
- min=0.001,
- default=0.01, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- panel_z : FloatProperty(
- name="Height",
- min=0.001,
- default=0.6, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- panel_dist : FloatProperty(
- name="Spacing",
- min=0.001,
- default=0.05, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- panel_offset_x : FloatProperty(
- name="Offset",
- default=0.0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- idmat_panel : EnumProperty(
- name="Panels",
- items=materials_enum,
- default='5',
- update=update
- )
- left_rail : BoolProperty(
- name="left",
- update=update,
- default=False
- )
- right_rail : BoolProperty(
- name="right",
- update=update,
- default=False
- )
- rail_n : IntProperty(
- name="#",
- default=1,
- min=0,
- max=31,
- update=update
- )
- rail_x : FloatVectorProperty(
- name="Width",
- default=[
- 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
- 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
- 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
- 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05
- ],
- size=31,
- min=0.001,
- precision=2, step=1,
- unit='LENGTH',
- update=update
- )
- rail_z : FloatVectorProperty(
- name="Height",
- default=[
- 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
- 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
- 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
- 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05
- ],
- size=31,
- min=0.001,
- precision=2, step=1,
- unit='LENGTH',
- update=update
- )
- rail_offset : FloatVectorProperty(
- name="Offset",
- default=[
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0
- ],
- size=31,
- precision=2, step=1,
- unit='LENGTH',
- update=update
- )
- rail_alt : FloatVectorProperty(
- name="Altitude",
- default=[
- 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
- 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
- 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
- 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
- ],
- size=31,
- precision=2, step=1,
- unit='LENGTH',
- update=update
- )
- rail_mat : CollectionProperty(type=archipack_stair_material)
-
- left_handrail : BoolProperty(
- name="left",
- update=update,
- default=True
- )
- right_handrail : BoolProperty(
- name="right",
- update=update,
- default=True
- )
- handrail_offset : FloatProperty(
- name="Offset",
- default=0.0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- handrail_alt : FloatProperty(
- name="Altitude",
- default=1.0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- handrail_extend : FloatProperty(
- name="Extend",
- default=0.1, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- handrail_slice_left : BoolProperty(
- name='Slice',
- default=True,
- update=update
- )
- handrail_slice_right : BoolProperty(
- name='Slice',
- default=True,
- update=update
- )
- handrail_profil : EnumProperty(
- name="Profil",
- items=(
- ('SQUARE', 'Square', '', 0),
- ('CIRCLE', 'Circle', '', 1),
- ('COMPLEX', 'Circle over square', '', 2)
- ),
- default='SQUARE',
- update=update
- )
- handrail_x : FloatProperty(
- name="Width",
- min=0.001,
- default=0.04, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- handrail_y : FloatProperty(
- name="Height",
- min=0.001,
- default=0.04, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- handrail_radius : FloatProperty(
- name="Radius",
- min=0.001,
- default=0.02, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
-
- left_string : BoolProperty(
- name="left",
- update=update,
- default=False
- )
- right_string : BoolProperty(
- name="right",
- update=update,
- default=False
- )
- string_x : FloatProperty(
- name="Width",
- min=-100.0,
- default=0.02, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- string_z : FloatProperty(
- name="Height",
- default=0.3, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- string_offset : FloatProperty(
- name="Offset",
- default=0.0, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
- string_alt : FloatProperty(
- name="Altitude",
- default=-0.04, precision=2, step=1,
- unit='LENGTH', subtype='DISTANCE',
- update=update
- )
-
- idmat_bottom : EnumProperty(
- name="Bottom",
- items=materials_enum,
- default='1',
- update=update
- )
- idmat_raise : EnumProperty(
- name="Raise",
- items=materials_enum,
- default='1',
- update=update
- )
- idmat_step_front : EnumProperty(
- name="Step front",
- items=materials_enum,
- default='3',
- update=update
- )
- idmat_top : EnumProperty(
- name="Top",
- items=materials_enum,
- default='3',
- update=update
- )
- idmat_side : EnumProperty(
- name="Side",
- items=materials_enum,
- default='1',
- update=update
- )
- idmat_step_side : EnumProperty(
- name="Step Side",
- items=materials_enum,
- default='3',
- update=update
- )
- idmat_handrail : EnumProperty(
- name="Handrail",
- items=materials_enum,
- default='3',
- update=update
- )
- idmat_string : EnumProperty(
- name="String",
- items=materials_enum,
- default='3',
- update=update
- )
-
- # UI layout related
- parts_expand : BoolProperty(
- default=False
- )
- steps_expand : BoolProperty(
- default=False
- )
- rail_expand : BoolProperty(
- default=False
- )
- idmats_expand : BoolProperty(
- default=False
- )
- handrail_expand : BoolProperty(
- default=False
- )
- string_expand : BoolProperty(
- default=False
- )
- post_expand : BoolProperty(
- default=False
- )
- panel_expand : BoolProperty(
- default=False
- )
- subs_expand : BoolProperty(
- default=False
- )
-
- auto_update : BoolProperty(
- options={'SKIP_SAVE'},
- default=True,
- update=update_manipulators
- )
-
- def setup_manipulators(self):
-
- if len(self.manipulators) == 0:
- s = self.manipulators.add()
- s.prop1_name = "width"
- s = self.manipulators.add()
- s.prop1_name = "height"
- s.normal = Vector((0, 1, 0))
-
- for i in range(self.n_parts):
- p = self.parts[i]
- n_manips = len(p.manipulators)
- if n_manips < 1:
- m = p.manipulators.add()
- m.type_key = 'SIZE'
- m.prop1_name = 'length'
-
- def update_parts(self):
-
- # remove rails materials
- for i in range(len(self.rail_mat), self.rail_n, -1):
- self.rail_mat.remove(i - 1)
-
- # add rails
- for i in range(len(self.rail_mat), self.rail_n):
- self.rail_mat.add()
-
- # remove parts
- for i in range(len(self.parts), self.n_parts, -1):
- self.parts.remove(i - 1)
-
- # add parts
- for i in range(len(self.parts), self.n_parts):
- self.parts.add()
-
- self.setup_manipulators()
-
- def update(self, context, manipulable_refresh=False):
-
- o = self.find_in_selection(context, self.auto_update)
-
- if o is None:
- return
-
- # clean up manipulators before any data model change
- if manipulable_refresh:
- self.manipulable_disable(context)
-
- self.update_parts()
-
- center = Vector((0, 0))
- verts = []
- faces = []
- matids = []
- uvs = []
- id_materials = [int(self.idmat_top), int(self.idmat_step_front), int(self.idmat_raise),
- int(self.idmat_side), int(self.idmat_bottom), int(self.idmat_step_side)]
-
- # depth at bottom
- bottom_z = self.bottom_z
- if self.steps_type == 'OPEN':
- # depth at front
- bottom_z = self.nose_z
-
- width_left = 0.5 * self.width - self.x_offset
- width_right = 0.5 * self.width + self.x_offset
-
- self.manipulators[0].set_pts([(-width_left, 0, 0), (width_right, 0, 0), (1, 0, 0)])
- self.manipulators[1].set_pts([(0, 0, 0), (0, 0, self.height), (1, 0, 0)])
-
- g = StairGenerator(self.parts)
- if self.presets == 'STAIR_USER':
- for part in self.parts:
- g.add_part(part.type, self.steps_type, self.nose_type, self.z_mode, self.nose_z,
- bottom_z, center, max(width_left + 0.01, width_right + 0.01, part.radius), part.da,
- width_left, width_right, part.length, part.left_shape, part.right_shape)
-
- elif self.presets == 'STAIR_O':
- n_parts = max(1, int(round(abs(self.total_angle) / pi, 0)))
- if self.total_angle > 0:
- dir = 1
- else:
- dir = -1
- last_da = self.total_angle - dir * (n_parts - 1) * pi
- if dir * last_da > pi:
- n_parts += 1
- last_da -= dir * pi
- abs_last = dir * last_da
-
- for part in range(n_parts - 1):
- g.add_part('D_STAIR', self.steps_type, self.nose_type, self.z_mode, self.nose_z,
- bottom_z, center, max(width_left + 0.01, width_right + 0.01, self.radius), dir * pi,
- width_left, width_right, 1.0, self.left_shape, self.right_shape)
- if round(abs_last, 2) > 0:
- if abs_last > pi / 2:
- g.add_part('C_STAIR', self.steps_type, self.nose_type, self.z_mode, self.nose_z,
- bottom_z, center, max(width_left + 0.01, width_right + 0.01, self.radius),
- dir * pi / 2,
- width_left, width_right, 1.0, self.left_shape, self.right_shape)
- g.add_part('C_STAIR', self.steps_type, self.nose_type, self.z_mode, self.nose_z,
- bottom_z, center, max(width_left + 0.01, width_right + 0.01, self.radius),
- last_da - dir * pi / 2,
- width_left, width_right, 1.0, self.left_shape, self.right_shape)
- else:
- g.add_part('C_STAIR', self.steps_type, self.nose_type, self.z_mode, self.nose_z,
- bottom_z, center, max(width_left + 0.01, width_right + 0.01, self.radius), last_da,
- width_left, width_right, 1.0, self.left_shape, self.right_shape)
- else:
- # STAIR_L STAIR_I STAIR_U
- for part in self.parts:
- g.add_part(part.type, self.steps_type, self.nose_type, self.z_mode, self.nose_z,
- bottom_z, center, max(width_left + 0.01, width_right + 0.01, self.radius), self.da,
- width_left, width_right, part.length, self.left_shape, self.right_shape)
-
- # Stair basis
- g.set_matids(id_materials)
- g.make_stair(self.height, self.step_depth, verts, faces, matids, uvs, nose_y=self.nose_y)
-
- # Ladder
- offset_x = 0.5 * self.width - self.post_offset_x
- post_spacing = self.post_spacing
- if self.post_corners:
- post_spacing = 10000
-
- if self.user_defined_post_enable:
- # user defined posts
- user_def_post = context.scene.objects.get(self.user_defined_post.strip())
- if user_def_post is not None and user_def_post.type == 'MESH':
- g.setup_user_defined_post(user_def_post, self.post_x, self.post_y, self.post_z)
-
- if self.left_post:
- g.make_post(self.height, self.step_depth, 0.5 * self.post_x, 0.5 * self.post_y,
- self.post_z, self.post_alt, 'LEFT', post_spacing, self.post_corners,
- self.x_offset, offset_x, int(self.idmat_post), verts, faces, matids, uvs)
-
- if self.right_post:
- g.make_post(self.height, self.step_depth, 0.5 * self.post_x, 0.5 * self.post_y,
- self.post_z, self.post_alt, 'RIGHT', post_spacing, self.post_corners,
- self.x_offset, offset_x, int(self.idmat_post), verts, faces, matids, uvs)
-
- # reset user def posts
- g.user_defined_post = None
-
- # user defined subs
- if self.user_defined_subs_enable:
- user_def_subs = context.scene.objects.get(self.user_defined_subs.strip())
- if user_def_subs is not None and user_def_subs.type == 'MESH':
- g.setup_user_defined_post(user_def_subs, self.subs_x, self.subs_y, self.subs_z)
-
- if self.left_subs:
- g.make_subs(self.height, self.step_depth, 0.5 * self.subs_x, 0.5 * self.subs_y,
- self.subs_z, 0.5 * self.post_y, self.subs_alt, self.subs_bottom, 'LEFT',
- self.handrail_slice_left, post_spacing, self.subs_spacing, self.post_corners,
- self.x_offset, offset_x, -self.subs_offset_x, int(self.idmat_subs), verts, faces, matids, uvs)
-
- if self.right_subs:
- g.make_subs(self.height, self.step_depth, 0.5 * self.subs_x, 0.5 * self.subs_y,
- self.subs_z, 0.5 * self.post_y, self.subs_alt, self.subs_bottom, 'RIGHT',
- self.handrail_slice_right, post_spacing, self.subs_spacing, self.post_corners,
- self.x_offset, offset_x, self.subs_offset_x, int(self.idmat_subs), verts, faces, matids, uvs)
-
- g.user_defined_post = None
-
- if self.left_panel:
- g.make_panels(self.height, self.step_depth, 0.5 * self.panel_x, self.panel_z, 0.5 * self.post_y,
- self.panel_alt, 'LEFT', post_spacing, self.panel_dist, self.post_corners,
- self.x_offset, offset_x, -self.panel_offset_x, int(self.idmat_panel), verts, faces, matids, uvs)
-
- if self.right_panel:
- g.make_panels(self.height, self.step_depth, 0.5 * self.panel_x, self.panel_z, 0.5 * self.post_y,
- self.panel_alt, 'RIGHT', post_spacing, self.panel_dist, self.post_corners,
- self.x_offset, offset_x, self.panel_offset_x, int(self.idmat_panel), verts, faces, matids, uvs)
-
- if self.right_rail:
- for i in range(self.rail_n):
- id_materials = [int(self.rail_mat[i].index) for j in range(6)]
- g.set_matids(id_materials)
- g.make_part(self.height, self.step_depth, self.rail_x[i], self.rail_z[i],
- self.x_offset, offset_x + self.rail_offset[i],
- self.rail_alt[i], 'LINEAR', 'CLOSED', verts, faces, matids, uvs)
-
- if self.left_rail:
- for i in range(self.rail_n):
- id_materials = [int(self.rail_mat[i].index) for j in range(6)]
- g.set_matids(id_materials)
- g.make_part(self.height, self.step_depth, self.rail_x[i], self.rail_z[i],
- self.x_offset, -offset_x - self.rail_offset[i],
- self.rail_alt[i], 'LINEAR', 'CLOSED', verts, faces, matids, uvs)
-
- if self.handrail_profil == 'COMPLEX':
- sx = self.handrail_x
- sy = self.handrail_y
- handrail = [Vector((sx * x, sy * y)) for x, y in [
- (-0.28, 1.83), (-0.355, 1.77), (-0.415, 1.695), (-0.46, 1.605), (-0.49, 1.51), (-0.5, 1.415),
- (-0.49, 1.315), (-0.46, 1.225), (-0.415, 1.135), (-0.355, 1.06), (-0.28, 1.0), (-0.255, 0.925),
- (-0.33, 0.855), (-0.5, 0.855), (-0.5, 0.0), (0.5, 0.0), (0.5, 0.855), (0.33, 0.855), (0.255, 0.925),
- (0.28, 1.0), (0.355, 1.06), (0.415, 1.135), (0.46, 1.225), (0.49, 1.315), (0.5, 1.415),
- (0.49, 1.51), (0.46, 1.605), (0.415, 1.695), (0.355, 1.77), (0.28, 1.83), (0.19, 1.875),
- (0.1, 1.905), (0.0, 1.915), (-0.095, 1.905), (-0.19, 1.875)]]
-
- elif self.handrail_profil == 'SQUARE':
- x = 0.5 * self.handrail_x
- y = self.handrail_y
- handrail = [Vector((-x, y)), Vector((-x, 0)), Vector((x, 0)), Vector((x, y))]
- elif self.handrail_profil == 'CIRCLE':
- r = self.handrail_radius
- handrail = [Vector((r * sin(0.1 * -a * pi), r * (0.5 + cos(0.1 * -a * pi)))) for a in range(0, 20)]
-
- if self.right_handrail:
- g.make_profile(handrail, int(self.idmat_handrail), "RIGHT", self.handrail_slice_right,
- self.height, self.step_depth, self.x_offset + offset_x + self.handrail_offset,
- self.handrail_alt, self.handrail_extend, verts, faces, matids, uvs)
-
- if self.left_handrail:
- g.make_profile(handrail, int(self.idmat_handrail), "LEFT", self.handrail_slice_left,
- self.height, self.step_depth, -self.x_offset + offset_x + self.handrail_offset,
- self.handrail_alt, self.handrail_extend, verts, faces, matids, uvs)
-
- w = 0.5 * self.string_x
- h = self.string_z
- string = [Vector((-w, 0)), Vector((w, 0)), Vector((w, h)), Vector((-w, h))]
-
- if self.right_string:
- g.make_profile(string, int(self.idmat_string), "RIGHT", False, self.height, self.step_depth,
- self.x_offset + 0.5 * self.width + self.string_offset,
- self.string_alt, 0, verts, faces, matids, uvs)
-
- if self.left_string:
- g.make_profile(string, int(self.idmat_string), "LEFT", False, self.height, self.step_depth,
- -self.x_offset + 0.5 * self.width + self.string_offset,
- self.string_alt, 0, verts, faces, matids, uvs)
-
- bmed.buildmesh(context, o, verts, faces, matids=matids, uvs=uvs, weld=True, clean=True)
-
- # enable manipulators rebuild
- if manipulable_refresh:
- self.manipulable_refresh = True
-
- self.restore_context(context)
-
- def manipulable_setup(self, context):
- """
- TODO: Implement the setup part as per parent object basis
-
- self.manipulable_disable(context)
- o = context.active_object
- for m in self.manipulators:
- self.manip_stack.append(m.setup(context, o, self))
-
- """
- self.manipulable_disable(context)
- o = context.active_object
-
- self.setup_manipulators()
-
- if self.presets != 'STAIR_O':
- for i, part in enumerate(self.parts):
- if i >= self.n_parts:
- break
- if "S_" in part.type or self.presets in ['STAIR_USER']:
- for j, m in enumerate(part.manipulators):
- self.manip_stack.append(m.setup(context, o, part))
-
- if self.presets in ['STAIR_U', 'STAIR_L']:
- self.manip_stack.append(self.parts[1].manipulators[0].setup(context, o, self))
-
- for m in self.manipulators:
- self.manip_stack.append(m.setup(context, o, self))
-
-
-class ARCHIPACK_PT_stair(Panel):
- bl_idname = "ARCHIPACK_PT_stair"
- bl_label = "Stair"
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- # bl_context = 'object'
- bl_category = 'Archipack'
-
- @classmethod
- def poll(cls, context):
- return archipack_stair.filter(context.active_object)
-
- def draw(self, context):
- prop = archipack_stair.datablock(context.active_object)
- if prop is None:
- return
- scene = context.scene
- layout = self.layout
- row = layout.row(align=True)
- row.operator('archipack.stair_manipulate', icon='VIEW_PAN')
- row = layout.row(align=True)
- row.prop(prop, 'presets', text="")
- box = layout.box()
- # box.label(text="Styles")
- row = box.row(align=True)
- # row.menu("ARCHIPACK_MT_stair_preset", text=bpy.types.ARCHIPACK_MT_stair_preset.bl_label)
- row.operator("archipack.stair_preset_menu", text=bpy.types.ARCHIPACK_OT_stair_preset_menu.bl_label)
- row.operator("archipack.stair_preset", text="", icon='ADD')
- row.operator("archipack.stair_preset", text="", icon='REMOVE').remove_active = True
- box = layout.box()
- box.prop(prop, 'width')
- box.prop(prop, 'height')
- box.prop(prop, 'bottom_z')
- box.prop(prop, 'x_offset')
- # box.prop(prop, 'z_mode')
- box = layout.box()
- row = box.row()
- if prop.parts_expand:
- row.prop(prop, 'parts_expand', icon="TRIA_DOWN", text="Parts", emboss=False)
- if prop.presets == 'STAIR_USER':
- box.prop(prop, 'n_parts')
- if prop.presets != 'STAIR_USER':
- row = box.row(align=True)
- row.prop(prop, "left_shape", text="")
- row.prop(prop, "right_shape", text="")
- row = box.row()
- row.prop(prop, "radius")
- row = box.row()
- if prop.presets == 'STAIR_O':
- row.prop(prop, 'total_angle')
- else:
- row.prop(prop, 'da')
- if prop.presets != 'STAIR_O':
- for i, part in enumerate(prop.parts):
- part.draw(layout, context, i, prop.presets == 'STAIR_USER')
- else:
- row.prop(prop, 'parts_expand', icon="TRIA_RIGHT", text="Parts", emboss=False)
-
- box = layout.box()
- row = box.row()
- if prop.steps_expand:
- row.prop(prop, 'steps_expand', icon="TRIA_DOWN", text="Steps", emboss=False)
- box.prop(prop, 'steps_type')
- box.prop(prop, 'step_depth')
- box.prop(prop, 'nose_type')
- box.prop(prop, 'nose_z')
- box.prop(prop, 'nose_y')
- else:
- row.prop(prop, 'steps_expand', icon="TRIA_RIGHT", text="Steps", emboss=False)
-
- box = layout.box()
- row = box.row(align=True)
- if prop.handrail_expand:
- row.prop(prop, 'handrail_expand', icon="TRIA_DOWN", text="Handrail", emboss=False)
- else:
- row.prop(prop, 'handrail_expand', icon="TRIA_RIGHT", text="Handrail", emboss=False)
-
- row.prop(prop, 'left_handrail')
- row.prop(prop, 'right_handrail')
-
- if prop.handrail_expand:
- box.prop(prop, 'handrail_alt')
- box.prop(prop, 'handrail_offset')
- box.prop(prop, 'handrail_extend')
- box.prop(prop, 'handrail_profil')
- if prop.handrail_profil != 'CIRCLE':
- box.prop(prop, 'handrail_x')
- box.prop(prop, 'handrail_y')
- else:
- box.prop(prop, 'handrail_radius')
- row = box.row(align=True)
- row.prop(prop, 'handrail_slice_left')
- row.prop(prop, 'handrail_slice_right')
-
- box = layout.box()
- row = box.row(align=True)
- if prop.string_expand:
- row.prop(prop, 'string_expand', icon="TRIA_DOWN", text="String", emboss=False)
- else:
- row.prop(prop, 'string_expand', icon="TRIA_RIGHT", text="String", emboss=False)
- row.prop(prop, 'left_string')
- row.prop(prop, 'right_string')
- if prop.string_expand:
- box.prop(prop, 'string_x')
- box.prop(prop, 'string_z')
- box.prop(prop, 'string_alt')
- box.prop(prop, 'string_offset')
-
- box = layout.box()
- row = box.row(align=True)
- if prop.post_expand:
- row.prop(prop, 'post_expand', icon="TRIA_DOWN", text="Post", emboss=False)
- else:
- row.prop(prop, 'post_expand', icon="TRIA_RIGHT", text="Post", emboss=False)
- row.prop(prop, 'left_post')
- row.prop(prop, 'right_post')
- if prop.post_expand:
- box.prop(prop, 'post_corners')
- if not prop.post_corners:
- box.prop(prop, 'post_spacing')
- box.prop(prop, 'post_x')
- box.prop(prop, 'post_y')
- box.prop(prop, 'post_z')
- box.prop(prop, 'post_alt')
- box.prop(prop, 'post_offset_x')
- row = box.row(align=True)
- row.prop(prop, 'user_defined_post_enable', text="")
- row.prop_search(prop, "user_defined_post", scene, "objects", text="")
-
- box = layout.box()
- row = box.row(align=True)
- if prop.subs_expand:
- row.prop(prop, 'subs_expand', icon="TRIA_DOWN", text="Subs", emboss=False)
- else:
- row.prop(prop, 'subs_expand', icon="TRIA_RIGHT", text="Subs", emboss=False)
-
- row.prop(prop, 'left_subs')
- row.prop(prop, 'right_subs')
- if prop.subs_expand:
- box.prop(prop, 'subs_spacing')
- box.prop(prop, 'subs_x')
- box.prop(prop, 'subs_y')
- box.prop(prop, 'subs_z')
- box.prop(prop, 'subs_alt')
- box.prop(prop, 'subs_offset_x')
- box.prop(prop, 'subs_bottom')
- row = box.row(align=True)
- row.prop(prop, 'user_defined_subs_enable', text="")
- row.prop_search(prop, "user_defined_subs", scene, "objects", text="")
-
- box = layout.box()
- row = box.row(align=True)
- if prop.panel_expand:
- row.prop(prop, 'panel_expand', icon="TRIA_DOWN", text="Panels", emboss=False)
- else:
- row.prop(prop, 'panel_expand', icon="TRIA_RIGHT", text="Panels", emboss=False)
- row.prop(prop, 'left_panel')
- row.prop(prop, 'right_panel')
- if prop.panel_expand:
- box.prop(prop, 'panel_dist')
- box.prop(prop, 'panel_x')
- box.prop(prop, 'panel_z')
- box.prop(prop, 'panel_alt')
- box.prop(prop, 'panel_offset_x')
-
- box = layout.box()
- row = box.row(align=True)
- if prop.rail_expand:
- row.prop(prop, 'rail_expand', icon="TRIA_DOWN", text="Rails", emboss=False)
- else:
- row.prop(prop, 'rail_expand', icon="TRIA_RIGHT", text="Rails", emboss=False)
- row.prop(prop, 'left_rail')
- row.prop(prop, 'right_rail')
- if prop.rail_expand:
- box.prop(prop, 'rail_n')
- for i in range(prop.rail_n):
- box = layout.box()
- box.label(text="Rail " + str(i + 1))
- box.prop(prop, 'rail_x', index=i)
- box.prop(prop, 'rail_z', index=i)
- box.prop(prop, 'rail_alt', index=i)
- box.prop(prop, 'rail_offset', index=i)
- box.prop(prop.rail_mat[i], 'index', text="")
-
- box = layout.box()
- row = box.row()
-
- if prop.idmats_expand:
- row.prop(prop, 'idmats_expand', icon="TRIA_DOWN", text="Materials", emboss=False)
- box.prop(prop, 'idmat_top')
- box.prop(prop, 'idmat_side')
- box.prop(prop, 'idmat_bottom')
- box.prop(prop, 'idmat_step_side')
- box.prop(prop, 'idmat_step_front')
- box.prop(prop, 'idmat_raise')
- box.prop(prop, 'idmat_handrail')
- box.prop(prop, 'idmat_panel')
- box.prop(prop, 'idmat_post')
- box.prop(prop, 'idmat_subs')
- box.prop(prop, 'idmat_string')
- else:
- row.prop(prop, 'idmats_expand', icon="TRIA_RIGHT", text="Materials", emboss=False)
-
-
-# ------------------------------------------------------------------
-# Define operator class to create object
-# ------------------------------------------------------------------
-
-
-class ARCHIPACK_OT_stair(ArchipackCreateTool, Operator):
- bl_idname = "archipack.stair"
- bl_label = "Stair"
- bl_description = "Create a Stair"
- bl_category = 'Archipack'
- bl_options = {'REGISTER', 'UNDO'}
-
- def create(self, context):
- m = bpy.data.meshes.new("Stair")
- o = bpy.data.objects.new("Stair", m)
- d = m.archipack_stair.add()
- self.link_object_to_scene(context, o)
- o.select_set(state=True)
- context.view_layer.objects.active = o
- self.load_preset(d)
- self.add_material(o)
- m.auto_smooth_angle = 0.20944
- return o
-
- # -----------------------------------------------------
- # Execute
- # -----------------------------------------------------
- def execute(self, context):
- if context.mode == "OBJECT":
- bpy.ops.object.select_all(action="DESELECT")
- o = self.create(context)
- o.location = context.scene.cursor.location
- o.select_set(state=True)
- context.view_layer.objects.active = o
- self.manipulate()
- return {'FINISHED'}
- else:
- self.report({'WARNING'}, "Archipack: Option only valid in Object mode")
- return {'CANCELLED'}
-
-# ------------------------------------------------------------------
-# Define operator class to manipulate object
-# ------------------------------------------------------------------
-
-
-class ARCHIPACK_OT_stair_manipulate(Operator):
- bl_idname = "archipack.stair_manipulate"
- bl_label = "Manipulate"
- bl_description = "Manipulate"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(self, context):
- return archipack_stair.filter(context.active_object)
-
- def invoke(self, context, event):
- d = archipack_stair.datablock(context.active_object)
- d.manipulable_invoke(context)
- return {'FINISHED'}
-
-
-# ------------------------------------------------------------------
-# Define operator class to load / save presets
-# ------------------------------------------------------------------
-
-
-class ARCHIPACK_OT_stair_preset_menu(PresetMenuOperator, Operator):
- bl_description = "Show Stair Presets"
- bl_idname = "archipack.stair_preset_menu"
- bl_label = "Stair style"
- preset_subdir = "archipack_stair"
-
-
-class ARCHIPACK_OT_stair_preset(ArchipackPreset, Operator):
- """Add a Stair Preset"""
- bl_idname = "archipack.stair_preset"
- bl_label = "Add Stair Style"
- preset_menu = "ARCHIPACK_OT_stair_preset_menu"
-
- @property
- def blacklist(self):
- return ['manipulators']
-
-
-def register():
- bpy.utils.register_class(archipack_stair_material)
- bpy.utils.register_class(archipack_stair_part)
- bpy.utils.register_class(archipack_stair)
- Mesh.archipack_stair = CollectionProperty(type=archipack_stair)
- bpy.utils.register_class(ARCHIPACK_PT_stair)
- bpy.utils.register_class(ARCHIPACK_OT_stair)
- bpy.utils.register_class(ARCHIPACK_OT_stair_preset_menu)
- bpy.utils.register_class(ARCHIPACK_OT_stair_preset)
- bpy.utils.register_class(ARCHIPACK_OT_stair_manipulate)
-
-
-def unregister():
- bpy.utils.unregister_class(archipack_stair_material)
- bpy.utils.unregister_class(archipack_stair_part)
- bpy.utils.unregister_class(archipack_stair)
- del Mesh.archipack_stair
- bpy.utils.unregister_class(ARCHIPACK_PT_stair)
- bpy.utils.unregister_class(ARCHIPACK_OT_stair)
- bpy.utils.unregister_class(ARCHIPACK_OT_stair_preset_menu)
- bpy.utils.unregister_class(ARCHIPACK_OT_stair_preset)
- bpy.utils.unregister_class(ARCHIPACK_OT_stair_manipulate)