1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
21 # ----------------------------------------------------------
22 # Automatic generation of shelves
23 # Author: Antonio Vazquez (antonioya)
25 # ----------------------------------------------------------
28 from bpy
.types
import Operator
, PropertyGroup
29 from bpy
.props
import FloatProperty
, BoolProperty
, IntProperty
, CollectionProperty
, EnumProperty
30 from .achm_tools
import *
33 # ------------------------------------------------------------------
34 # Define property group class for shelves properties
35 # ------------------------------------------------------------------
36 class ShelvesProperties(PropertyGroup
):
37 sX
= FloatProperty(name
='width', min=0.001, max=10, default
=1,
38 precision
=3, description
='Furniture width')
39 wY
= FloatProperty(name
='', min=-10, max=10, default
=0, precision
=3, description
='Modify y size')
40 wZ
= FloatProperty(name
='', min=-10, max=10, default
=0, precision
=3, description
='Modify z size')
41 # Cabinet position shift
42 pX
= FloatProperty(name
='', min=0, max=10, default
=0, precision
=3, description
='Position x shift')
43 pY
= FloatProperty(name
='', min=-10, max=10, default
=0, precision
=3, description
='Position y shift')
44 pZ
= FloatProperty(name
='', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
47 sNum
= IntProperty(name
='Shelves', min=0, max=12, default
=6, description
='Number total of shelves')
50 Z01
= FloatProperty(name
='zS1', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
51 Z02
= FloatProperty(name
='zS2', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
52 Z03
= FloatProperty(name
='zS3', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
53 Z04
= FloatProperty(name
='zS4', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
54 Z05
= FloatProperty(name
='zS5', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
55 Z06
= FloatProperty(name
='zS6', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
56 Z07
= FloatProperty(name
='zS7', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
57 Z08
= FloatProperty(name
='zS8', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
58 Z09
= FloatProperty(name
='zS9', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
59 Z10
= FloatProperty(name
='zS10', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
60 Z11
= FloatProperty(name
='zS11', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
61 Z12
= FloatProperty(name
='zS12', min=-10, max=10, default
=0, precision
=3, description
='Position z shift')
63 right
= BoolProperty(name
="Right", description
="Create right side", default
=True)
64 left
= BoolProperty(name
="Left", description
="Create left side", default
=True)
66 bpy
.utils
.register_class(ShelvesProperties
)
69 # ------------------------------------------------------------------
72 # ------------------------------------------------------------------
73 class AchmShelves(Operator
):
74 bl_idname
= "mesh.archimesh_shelves"
76 bl_description
= "Shelves Generator"
77 bl_category
= 'Archimesh'
78 bl_options
= {'REGISTER', 'UNDO'}
80 thickness
= FloatProperty(
81 name
='Side Thickness', min=0.001, max=5,
82 default
=0.03, precision
=3,
83 description
='Board thickness',
85 sthickness
= FloatProperty(
86 name
='Shelves Thickness', min=0.001, max=5,
87 default
=0.03, precision
=3,
88 description
='Board thickness',
90 depth
= FloatProperty(
91 name
='Depth', min=0.001, max=50,
92 default
=0.28, precision
=3,
93 description
='Default unit depth',
95 height
= FloatProperty(
96 name
='Height', min=0.001, max=50,
97 default
=2, precision
=3,
98 description
='Default unit height',
101 name
='Top', min=0, max=50,
102 default
=0.03, precision
=3,
103 description
='Default top shelf position',
105 bottom
= FloatProperty(
106 name
='Bottom', min=0, max=50,
107 default
=0.07, precision
=3,
108 description
='Default bottom self position',
110 stype
= EnumProperty(
112 ('1', "Full side", ""),
116 description
="Type of side construction",
120 name
="Floor origin in Z=0",
121 description
="Use Z=0 axis as vertical origin floor position",
125 shelves_num
= IntProperty(
126 name
='Number of Units',
129 description
='Number total of shelves units',
131 shelves
= CollectionProperty(type=ShelvesProperties
)
134 crt_mat
= BoolProperty(
135 name
="Create default Cycles materials",
136 description
="Create default materials for Cycles render",
140 # -----------------------------------------------------
141 # Draw (create UI interface)
142 # -----------------------------------------------------
143 # noinspection PyUnusedLocal
144 def draw(self
, context
):
146 space
= bpy
.context
.space_data
147 if not space
.local_view
:
148 # Imperial units warning
149 if bpy
.context
.scene
.unit_settings
.system
== "IMPERIAL":
151 row
.label("Warning: Imperial units not supported", icon
='COLOR_RED')
155 row
.prop(self
, 'thickness')
156 row
.prop(self
, 'sthickness')
158 row
.prop(self
, 'depth')
159 row
.prop(self
, 'height')
161 row
.prop(self
, 'top')
162 row
.prop(self
, 'bottom')
164 row
.prop(self
, 'stype')
165 row
.prop(self
, 'fitZ')
169 row
.prop(self
, 'shelves_num')
170 # Add menu for shelves
171 if self
.shelves_num
> 0:
172 for idx
in range(0, self
.shelves_num
):
174 add_shelves(self
, box
, idx
+ 1, self
.shelves
[idx
])
177 if not context
.scene
.render
.engine
== 'CYCLES':
179 box
.prop(self
, 'crt_mat')
182 row
.label("Warning: Operator does not work in local view mode", icon
='ERROR')
184 # -----------------------------------------------------
186 # -----------------------------------------------------
187 # noinspection PyUnusedLocal
188 def execute(self
, context
):
189 if bpy
.context
.mode
== "OBJECT":
190 # Create all elements
191 for i
in range(len(self
.shelves
) - 1, self
.shelves_num
):
195 create_shelves_mesh(self
)
198 self
.report({'WARNING'}, "Archimesh: Option only valid in Object mode")
202 # -----------------------------------------------------
203 # Add shelves parameters
204 # -----------------------------------------------------
205 def add_shelves(self
, box
, num
, sh
):
207 row
.label("Unit " + str(num
))
213 if self
.stype
!= "99":
215 row
.prop(sh
, 'right')
223 row
.prop(sh
, 'sNum', slider
=True)
258 # ------------------------------------------------------------------------------
260 # All custom values are passed using self container (self.myvariable)
261 # ------------------------------------------------------------------------------
262 def create_shelves_mesh(self
):
264 for o
in bpy
.data
.objects
:
267 bpy
.ops
.object.select_all(False)
269 generate_shelves(self
)
274 # ------------------------------------------------------------------------------
276 # All custom values are passed using self container (self.myvariable)
277 # ------------------------------------------------------------------------------
278 def generate_shelves(self
):
281 location
= bpy
.context
.scene
.cursor_location
282 myloc
= copy(location
) # copy location to keep 3D cursor position
289 # ------------------------------------------------------------------------------
291 # ------------------------------------------------------------------------------
292 for i
in range(0, self
.shelves_num
):
293 mydata
= create_unit(self
.stype
, "Shelves" + str(i
+ 1),
294 self
.thickness
, self
.sthickness
,
295 self
.shelves
[i
].sX
, self
.depth
+ self
.shelves
[i
].wY
, self
.height
+ self
.shelves
[i
].wZ
,
296 self
.shelves
[i
].pX
+ lastx
, myloc
[1] + self
.shelves
[i
].pY
, myloc
[2] + self
.shelves
[i
].pZ
,
297 self
.shelves
[i
].left
, self
.shelves
[i
].right
,
298 self
.shelves
[i
].sNum
,
299 (self
.shelves
[i
].Z01
, self
.shelves
[i
].Z02
, self
.shelves
[i
].Z03
,
300 self
.shelves
[i
].Z04
, self
.shelves
[i
].Z05
, self
.shelves
[i
].Z06
,
301 self
.shelves
[i
].Z07
, self
.shelves
[i
].Z08
, self
.shelves
[i
].Z09
,
302 self
.shelves
[i
].Z10
, self
.shelves
[i
].Z11
, self
.shelves
[i
].Z12
),
303 self
.top
, self
.bottom
)
304 boxes
.extend([mydata
[0]])
313 for o
in bpy
.data
.objects
:
317 boxes
[0].select
= True
318 bpy
.context
.scene
.objects
.active
= boxes
[0]
321 if self
.crt_mat
and bpy
.context
.scene
.render
.engine
== 'CYCLES':
322 mat
= create_diffuse_material("Shelves_material", False, 0.8, 0.8, 0.8)
324 set_material(box
, mat
)
329 # ------------------------------------------------------------------------------
330 # Create shelves unit
332 # stype: type of sides
333 # objName: Name for the new object
334 # thickness: wood thickness (sides)
335 # sthickness: wood thickness (shelves)
339 # pX: position X axis
340 # pY: position Y axis
341 # pZ: position Z axis
342 # right: True-> create right side
343 # left: True-> create left side
344 # shelves: Number of shelves
345 # zPos: List with z shift for each self
346 # top: position of top shelf
347 # bottom: position of bottom shelf
348 # ------------------------------------------------------------------------------
349 def create_unit(stype
, objname
, thickness
, sthickness
, sx
, sy
, sz
, px
, py
, pz
, left
, right
, shelves
, zpos
,
356 # no Sides, then no thickness
360 # ------------------------------
362 # ------------------------------
363 if left
and stype
!= "99":
366 myvertex
.extend([(0, 0, 0), (0, -sy
, 0), (0, -sy
, sz
), (0, 0, sz
),
367 (thickness
, 0, 0), (thickness
, -sy
, 0), (thickness
, -sy
, sz
), (thickness
, 0, sz
)])
368 myfaces
.extend([(v
, v
+ 1, v
+ 2, v
+ 3), (v
+ 4, v
+ 5, v
+ 6, v
+ 7), (v
, v
+ 4, v
+ 7, v
+ 3),
369 (v
, v
+ 1, v
+ 5, v
+ 4),
370 (v
+ 3, v
+ 2, v
+ 6, v
+ 7), (v
+ 1, v
+ 2, v
+ 6, v
+ 5)])
375 myvertex
.extend([(0, 0, 0), (0, -thickness
, 0), (0, -thickness
, sz
), (0, 0, sz
),
376 (thickness
, 0, 0), (thickness
, -thickness
, 0), (thickness
, -thickness
, sz
),
378 myfaces
.extend([(v
, v
+ 1, v
+ 2, v
+ 3), (v
+ 4, v
+ 5, v
+ 6, v
+ 7), (v
, v
+ 4, v
+ 7, v
+ 3),
379 (v
, v
+ 1, v
+ 5, v
+ 4),
380 (v
+ 3, v
+ 2, v
+ 6, v
+ 7), (v
+ 1, v
+ 2, v
+ 6, v
+ 5)])
383 myvertex
.extend([(0, -sy
+ thickness
, 0), (0, -sy
, 0), (0, -sy
, sz
), (0, -sy
+ thickness
, sz
),
384 (thickness
, -sy
+ thickness
, 0), (thickness
, -sy
, 0), (thickness
, -sy
, sz
),
385 (thickness
, -sy
+ thickness
, sz
)])
386 myfaces
.extend([(v
, v
+ 1, v
+ 2, v
+ 3), (v
+ 4, v
+ 5, v
+ 6, v
+ 7), (v
, v
+ 4, v
+ 7, v
+ 3),
387 (v
, v
+ 1, v
+ 5, v
+ 4),
388 (v
+ 3, v
+ 2, v
+ 6, v
+ 7), (v
+ 1, v
+ 2, v
+ 6, v
+ 5)])
394 if right
and stype
!= "99":
395 width
= sx
- thickness
398 myvertex
.extend([(width
, 0, 0), (width
, -sy
, 0), (width
, -sy
, sz
), (width
, 0, sz
),
399 (width
+ thickness
, 0, 0), (width
+ thickness
, -sy
, 0), (width
+ thickness
, -sy
, sz
),
400 (width
+ thickness
, 0, sz
)])
401 myfaces
.extend([(v
, v
+ 1, v
+ 2, v
+ 3), (v
+ 4, v
+ 5, v
+ 6, v
+ 7), (v
, v
+ 4, v
+ 7, v
+ 3),
402 (v
, v
+ 1, v
+ 5, v
+ 4), (v
+ 3, v
+ 2, v
+ 6, v
+ 7), (v
+ 1, v
+ 2, v
+ 6, v
+ 5)])
407 myvertex
.extend([(width
, 0, 0), (width
, -thickness
, 0), (width
, -thickness
, sz
), (width
, 0, sz
),
408 (width
+ thickness
, 0, 0), (width
+ thickness
, -thickness
, 0),
409 (width
+ thickness
, -thickness
, sz
), (width
+ thickness
, 0, sz
)])
410 myfaces
.extend([(v
, v
+ 1, v
+ 2, v
+ 3), (v
+ 4, v
+ 5, v
+ 6, v
+ 7), (v
, v
+ 4, v
+ 7, v
+ 3),
411 (v
, v
+ 1, v
+ 5, v
+ 4), (v
+ 3, v
+ 2, v
+ 6, v
+ 7), (v
+ 1, v
+ 2, v
+ 6, v
+ 5)])
415 [(width
, -sy
+ thickness
, 0), (width
, -sy
, 0), (width
, -sy
, sz
), (width
, -sy
+ thickness
, sz
),
416 (width
+ thickness
, -sy
+ thickness
, 0), (width
+ thickness
, -sy
, 0), (width
+ thickness
, -sy
, sz
),
417 (width
+ thickness
, -sy
+ thickness
, sz
)])
418 myfaces
.extend([(v
, v
+ 1, v
+ 2, v
+ 3), (v
+ 4, v
+ 5, v
+ 6, v
+ 7), (v
, v
+ 4, v
+ 7, v
+ 3),
419 (v
, v
+ 1, v
+ 5, v
+ 4), (v
+ 3, v
+ 2, v
+ 6, v
+ 7), (v
+ 1, v
+ 2, v
+ 6, v
+ 5)])
426 width
= sx
- thickness
427 posx
= posx
+ thickness
429 # calculate vertical spaces
430 dist
= sz
- top
- bottom
- sthickness
431 # if only top/bottom the space is not necessary
433 space
= dist
/ (shelves
- 1)
439 for x
in range(shelves
):
445 posz1
= sz
- top
- sthickness
447 posz2
= posz1
- sthickness
448 myvertex
.extend([(posx
, 0, posz1
+ zpos
[x
]), (posx
, -sy
, posz1
+ zpos
[x
]),
449 (posx
, -sy
, posz2
+ zpos
[x
]), (posx
, 0, posz2
+ zpos
[x
]),
450 (width
, 0, posz1
+ zpos
[x
]), (width
, -sy
, posz1
+ zpos
[x
]),
451 (width
, -sy
, posz2
+ zpos
[x
]), (width
, 0, posz2
+ zpos
[x
])])
454 [(v
, v
+ 1, v
+ 2, v
+ 3), (v
+ 4, v
+ 5, v
+ 6, v
+ 7), (v
, v
+ 4, v
+ 7, v
+ 3), (v
, v
+ 1, v
+ 5, v
+ 4),
455 (v
+ 3, v
+ 2, v
+ 6, v
+ 7), (v
+ 1, v
+ 2, v
+ 6, v
+ 5)])
459 mymesh
= bpy
.data
.meshes
.new(objname
)
460 myobject
= bpy
.data
.objects
.new(objname
, mymesh
)
462 myobject
.location
[0] = px
463 myobject
.location
[1] = py
464 myobject
.location
[2] = pz
465 bpy
.context
.scene
.objects
.link(myobject
)
467 mymesh
.from_pydata(myvertex
, [], myfaces
)
468 mymesh
.update(calc_edges
=True)
470 return myobject
, px
+ sx
- thickness