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 # support routines and general functions
23 # Author: Antonio Vazquez (antonioya)
25 # ----------------------------------------------------------
26 # noinspection PyUnresolvedReferences
31 # --------------------------------------------------------------------
32 # Get length Blender units
33 # --------------------------------------------------------------------
34 def get_blendunits(units
):
35 if bpy
.context
.scene
.unit_settings
.system
== "IMPERIAL":
41 # --------------------------------------------------------------------
43 # True= faces to inside
44 # False= faces to outside
45 # --------------------------------------------------------------------
46 def set_normals(myobject
, direction
=False):
47 bpy
.context
.view_layer
.objects
.active
= myobject
49 bpy
.ops
.object.mode_set(mode
='EDIT')
51 bpy
.ops
.mesh
.select_all(action
='SELECT')
52 # recalculate outside normals
53 bpy
.ops
.mesh
.normals_make_consistent(inside
=direction
)
54 # go object mode again
55 bpy
.ops
.object.editmode_toggle()
58 # --------------------------------------------------------------------
60 # --------------------------------------------------------------------
61 def remove_doubles(myobject
):
62 bpy
.context
.view_layer
.objects
.active
= myobject
64 bpy
.ops
.object.mode_set(mode
='EDIT')
66 bpy
.ops
.mesh
.select_all(action
='SELECT')
68 bpy
.ops
.mesh
.remove_doubles()
69 # go object mode again
70 bpy
.ops
.object.editmode_toggle()
73 # --------------------------------------------------------------------
75 # --------------------------------------------------------------------
76 def set_smooth(myobject
):
78 for o
in bpy
.data
.objects
:
79 if o
.select_get() is True:
82 myobject
.select_set(True)
83 bpy
.context
.view_layer
.objects
.active
= myobject
84 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
85 bpy
.ops
.object.shade_smooth()
88 # --------------------------------------------------------------------
89 # Add modifier (subdivision)
90 # --------------------------------------------------------------------
91 def set_modifier_subsurf(myobject
):
92 bpy
.context
.view_layer
.objects
.active
= myobject
93 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
94 bpy
.ops
.object.modifier_add(type='SUBSURF')
95 for mod
in myobject
.modifiers
:
96 if mod
.type == 'SUBSURF':
100 # --------------------------------------------------------------------
101 # Add modifier (mirror)
102 # --------------------------------------------------------------------
103 def set_modifier_mirror(myobject
, axis
="Y"):
104 bpy
.ops
.object.select_all(action
='DESELECT')
105 myobject
.select_set(True)
106 bpy
.context
.view_layer
.objects
.active
= myobject
107 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
108 bpy
.ops
.object.modifier_add(type='MIRROR')
109 for mod
in myobject
.modifiers
:
110 if mod
.type == 'MIRROR':
112 mod
.use_axis
[0] = True
114 mod
.use__axis
[0] = False
117 mod
.use_axis
[1] = True
119 mod
.use_axis
[1] = False
122 mod
.use_axis
[2] = True
124 mod
.use_axis
[2] = False
129 # --------------------------------------------------------------------
130 # Add modifier (array)
131 # --------------------------------------------------------------------
132 def set_modifier_array(myobject
, axis
, move
, repeat
, fix
=False, fixmove
=0, zmove
=0):
133 bpy
.ops
.object.select_all(action
='DESELECT')
134 myobject
.select_set(True)
135 bpy
.context
.view_layer
.objects
.active
= myobject
136 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
137 bpy
.ops
.object.modifier_add(type='ARRAY')
138 for mod
in myobject
.modifiers
:
139 if mod
.type == 'ARRAY':
140 if mod
.name
== "Array":
141 mod
.name
= "Array_" + axis
143 mod
.use_constant_offset
= fix
145 mod
.relative_offset_displace
[0] = move
146 mod
.constant_offset_displace
[0] = fixmove
147 mod
.relative_offset_displace
[1] = 0.0
148 mod
.constant_offset_displace
[1] = 0.0
149 mod
.relative_offset_displace
[2] = 0.0
150 mod
.constant_offset_displace
[2] = zmove
153 mod
.relative_offset_displace
[0] = 0.0
154 mod
.constant_offset_displace
[0] = 0.0
155 mod
.relative_offset_displace
[1] = move
156 mod
.constant_offset_displace
[1] = fixmove
157 mod
.relative_offset_displace
[2] = 0.0
158 mod
.constant_offset_displace
[2] = 0.0
161 # --------------------------------------------------------------------
162 # Add modifier (curve)
163 # --------------------------------------------------------------------
164 def set_modifier_curve(myobject
, mycurve
):
165 bpy
.context
.view_layer
.objects
.active
= myobject
166 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
167 bpy
.ops
.object.modifier_add(type='CURVE')
168 for mod
in myobject
.modifiers
:
169 if mod
.type == 'CURVE':
170 mod
.deform_axis
= 'POS_X'
174 # --------------------------------------------------------------------
175 # Add modifier (solidify)
176 # --------------------------------------------------------------------
177 def set_modifier_solidify(myobject
, width
):
178 bpy
.context
.view_layer
.objects
.active
= myobject
179 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
180 bpy
.ops
.object.modifier_add(type='SOLIDIFY')
181 for mod
in myobject
.modifiers
:
182 if mod
.type == 'SOLIDIFY':
183 mod
.thickness
= width
184 mod
.use_even_offset
= True
185 mod
.use_quality_normals
= True
189 # --------------------------------------------------------------------
190 # Add modifier (boolean)
191 # --------------------------------------------------------------------
192 def set_modifier_boolean(myobject
, bolobject
):
193 bpy
.context
.view_layer
.objects
.active
= myobject
194 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
195 bpy
.ops
.object.modifier_add(type='BOOLEAN')
196 mod
= myobject
.modifiers
[len(myobject
.modifiers
) - 1]
197 mod
.operation
= 'DIFFERENCE'
198 mod
.object = bolobject
201 # --------------------------------------------------------------------
202 # Set material to object
203 # --------------------------------------------------------------------
204 def set_material(myobject
, mymaterial
):
205 bpy
.context
.view_layer
.objects
.active
= myobject
206 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
207 myobject
.data
.materials
.append(mymaterial
)
210 # --------------------------------------------------------------------
211 # Set material to selected faces
212 # --------------------------------------------------------------------
213 def set_material_faces(myobject
, idx
):
214 bpy
.context
.view_layer
.objects
.active
= myobject
215 myobject
.select_set(True)
216 bpy
.context
.object.active_material_index
= idx
217 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
218 bpy
.ops
.object.mode_set(mode
='EDIT')
219 bpy
.ops
.object.material_slot_assign()
221 bpy
.ops
.mesh
.select_all(action
='DESELECT')
222 bpy
.ops
.object.mode_set(mode
='OBJECT')
225 # --------------------------------------------------------------------
227 # --------------------------------------------------------------------
228 def select_faces(myobject
, selface
, clear
):
229 myobject
.select_set(True)
230 bpy
.context
.view_layer
.objects
.active
= myobject
231 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
232 # deselect everything
234 bpy
.ops
.object.mode_set(mode
='EDIT')
235 bpy
.ops
.mesh
.select_all(action
='DESELECT')
237 # reselect the originally selected face
238 bpy
.ops
.object.mode_set(mode
='OBJECT')
239 myobject
.data
.polygons
[selface
].select
= True
242 # --------------------------------------------------------------------
244 # --------------------------------------------------------------------
245 def select_vertices(myobject
, selvertices
, clear
=True):
246 myobject
.select_set(True)
247 bpy
.context
.view_layer
.objects
.active
= myobject
248 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
249 # deselect everything
251 bpy
.ops
.object.mode_set(mode
='EDIT')
252 bpy
.ops
.mesh
.select_all(action
='DESELECT')
255 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
256 sel_mode
= bpy
.context
.tool_settings
.mesh_select_mode
258 bpy
.context
.tool_settings
.mesh_select_mode
= [True, False, False]
259 bpy
.ops
.object.mode_set(mode
='OBJECT', toggle
=False)
261 for i
in selvertices
:
262 myobject
.data
.vertices
[i
].select
= True
264 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
265 bpy
.context
.tool_settings
.mesh_select_mode
= sel_mode
266 bpy
.ops
.object.mode_set(mode
='OBJECT')
269 # --------------------------------------------------------------------
271 # --------------------------------------------------------------------
272 def mark_seam(myobject
):
273 # noinspection PyBroadException
275 myobject
.select_set(True)
276 bpy
.context
.view_layer
.objects
.active
= myobject
277 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
278 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
279 bpy
.ops
.mesh
.mark_seam()
280 bpy
.ops
.object.mode_set(mode
='OBJECT')
282 bpy
.ops
.object.mode_set(mode
='OBJECT')
285 # --------------------------------------------------------------------
287 # --------------------------------------------------------------------
288 def unwrap_mesh(myobject
, allfaces
=True):
289 # noinspection PyBroadException
291 myobject
.select_set(True)
292 bpy
.context
.view_layer
.objects
.active
= myobject
293 if bpy
.context
.view_layer
.objects
.active
.name
== myobject
.name
:
295 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
297 bpy
.ops
.mesh
.select_all(action
='DESELECT')
298 bpy
.ops
.mesh
.select_all()
300 bpy
.ops
.object.mode_set(mode
='OBJECT')
302 bpy
.ops
.object.mode_set(mode
='OBJECT')
305 # --------------------------------------------------------------------
306 # Get Node Index(multilanguage support)
307 # --------------------------------------------------------------------
308 def get_node_index(nodes
, datatype
):
311 if m
.type == datatype
:
319 # --------------------------------------------------------------------
320 # Create cycles diffuse material
321 # --------------------------------------------------------------------
322 def create_diffuse_material(matname
, replace
, r
, g
, b
, rv
=0.8, gv
=0.8, bv
=0.8, mix
=0.1, twosides
=False):
323 # Avoid duplicate materials
325 matlist
= bpy
.data
.materials
327 if m
.name
== matname
:
330 mat
= bpy
.data
.materials
.new(matname
)
331 mat
.diffuse_color
= (rv
, gv
, bv
, 1.0) # viewport color
333 nodes
= mat
.node_tree
.nodes
335 # support for multilanguage
336 node
= nodes
.new('ShaderNodeBsdfDiffuse')
337 node
.name
= 'Diffuse BSDF'
338 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
339 node
.location
= 200, 320
341 node
= nodes
.new('ShaderNodeBsdfGlossy')
342 node
.name
= 'Glossy_0'
343 node
.location
= 200, 0
345 node
= nodes
.new('ShaderNodeMixShader')
347 node
.inputs
[0].default_value
= mix
348 node
.location
= 500, 160
350 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
351 node
.location
= 1100, 160
354 outn
= nodes
['Diffuse BSDF'].outputs
[0]
355 inn
= nodes
['Mix_0'].inputs
[1]
356 mat
.node_tree
.links
.new(outn
, inn
)
358 outn
= nodes
['Glossy_0'].outputs
[0]
359 inn
= nodes
['Mix_0'].inputs
[2]
360 mat
.node_tree
.links
.new(outn
, inn
)
362 if twosides
is False:
363 outn
= nodes
['Mix_0'].outputs
[0]
364 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
365 mat
.node_tree
.links
.new(outn
, inn
)
368 node
= nodes
.new('ShaderNodeNewGeometry')
369 node
.name
= 'Input_1'
370 node
.location
= -80, -70
372 node
= nodes
.new('ShaderNodeBsdfDiffuse')
373 node
.name
= 'Diffuse_1'
374 node
.inputs
[0].default_value
= [0.30, 0.30, 0.30, 1]
375 node
.location
= 200, -280
377 node
= nodes
.new('ShaderNodeMixShader')
379 node
.inputs
[0].default_value
= mix
380 node
.location
= 800, -70
382 outn
= nodes
['Input_1'].outputs
[6]
383 inn
= nodes
['Mix_1'].inputs
[0]
384 mat
.node_tree
.links
.new(outn
, inn
)
386 outn
= nodes
['Diffuse_1'].outputs
[0]
387 inn
= nodes
['Mix_1'].inputs
[2]
388 mat
.node_tree
.links
.new(outn
, inn
)
390 outn
= nodes
['Mix_0'].outputs
[0]
391 inn
= nodes
['Mix_1'].inputs
[1]
392 mat
.node_tree
.links
.new(outn
, inn
)
394 outn
= nodes
['Mix_1'].outputs
[0]
395 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
396 mat
.node_tree
.links
.new(outn
, inn
)
401 # --------------------------------------------------------------------
402 # Create cycles translucent material
403 # --------------------------------------------------------------------
404 def create_translucent_material(matname
, replace
, r
, g
, b
, rv
=0.8, gv
=0.8, bv
=0.8, mix
=0.1):
405 # Avoid duplicate materials
407 matlist
= bpy
.data
.materials
409 if m
.name
== matname
:
412 mat
= bpy
.data
.materials
.new(matname
)
413 mat
.diffuse_color
= (rv
, gv
, bv
, 1.0) # viewport color
415 nodes
= mat
.node_tree
.nodes
417 # support for multilanguage
418 node
= nodes
.new('ShaderNodeBsdfDiffuse')
419 node
.name
= 'Diffuse BSDF'
420 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
421 node
.location
= 200, 320
423 node
= nodes
.new('ShaderNodeBsdfTranslucent')
424 node
.name
= 'Translucent_0'
425 node
.location
= 200, 0
427 node
= nodes
.new('ShaderNodeMixShader')
429 node
.inputs
[0].default_value
= mix
430 node
.location
= 500, 160
432 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
433 node
.location
= 1100, 160
436 outn
= nodes
['Diffuse BSDF'].outputs
[0]
437 inn
= nodes
['Mix_0'].inputs
[1]
438 mat
.node_tree
.links
.new(outn
, inn
)
440 outn
= nodes
['Translucent_0'].outputs
[0]
441 inn
= nodes
['Mix_0'].inputs
[2]
442 mat
.node_tree
.links
.new(outn
, inn
)
444 outn
= nodes
['Mix_0'].outputs
[0]
445 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
446 mat
.node_tree
.links
.new(outn
, inn
)
451 # --------------------------------------------------------------------
452 # Create cycles glass material
453 # --------------------------------------------------------------------
454 def create_glass_material(matname
, replace
, rv
=0.333, gv
=0.342, bv
=0.9):
455 # Avoid duplicate materials
457 matlist
= bpy
.data
.materials
459 if m
.name
== matname
:
462 mat
= bpy
.data
.materials
.new(matname
)
464 mat
.diffuse_color
= (rv
, gv
, bv
, 1.0)
465 nodes
= mat
.node_tree
.nodes
467 # support for multilanguage
468 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
469 mat
.node_tree
.nodes
.remove(node
) # remove not used
471 node
= nodes
.new('ShaderNodeLightPath')
472 node
.name
= 'Light_0'
473 node
.location
= 10, 160
475 node
= nodes
.new('ShaderNodeBsdfRefraction')
476 node
.name
= 'Refraction_0'
477 node
.inputs
[2].default_value
= 1 # IOR 1.0
478 node
.location
= 250, 400
480 node
= nodes
.new('ShaderNodeBsdfGlossy')
481 node
.name
= 'Glossy_0'
482 node
.distribution
= 'SHARP'
483 node
.location
= 250, 100
485 node
= nodes
.new('ShaderNodeBsdfTransparent')
486 node
.name
= 'Transparent_0'
487 node
.location
= 500, 10
489 node
= nodes
.new('ShaderNodeMixShader')
491 node
.inputs
[0].default_value
= 0.035
492 node
.location
= 500, 160
494 node
= nodes
.new('ShaderNodeMixShader')
496 node
.inputs
[0].default_value
= 0.1
497 node
.location
= 690, 290
499 node
= nodes
.new('ShaderNodeOutputMaterial')
500 node
.name
= 'OUTPUT_MATERIAL'
501 node
.location
= 920, 290
504 outn
= nodes
['Light_0'].outputs
[1]
505 inn
= nodes
['Mix_1'].inputs
[0]
506 mat
.node_tree
.links
.new(outn
, inn
)
508 outn
= nodes
['Refraction_0'].outputs
[0]
509 inn
= nodes
['Mix_0'].inputs
[1]
510 mat
.node_tree
.links
.new(outn
, inn
)
512 outn
= nodes
['Glossy_0'].outputs
[0]
513 inn
= nodes
['Mix_0'].inputs
[2]
514 mat
.node_tree
.links
.new(outn
, inn
)
516 outn
= nodes
['Mix_0'].outputs
[0]
517 inn
= nodes
['Mix_1'].inputs
[1]
518 mat
.node_tree
.links
.new(outn
, inn
)
520 outn
= nodes
['Transparent_0'].outputs
[0]
521 inn
= nodes
['Mix_1'].inputs
[2]
522 mat
.node_tree
.links
.new(outn
, inn
)
524 outn
= nodes
['Mix_1'].outputs
[0]
525 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
526 mat
.node_tree
.links
.new(outn
, inn
)
531 # ---------------------------------------------
532 # Create cycles transparents material
533 # --------------------------------------------------------------------
534 def create_transparent_material(matname
, replace
, r
=1, g
=1, b
=1, alpha
=0):
535 # Avoid duplicate materials
537 matlist
= bpy
.data
.materials
539 if m
.name
== matname
:
542 mat
= bpy
.data
.materials
.new(matname
)
544 mat
.diffuse_color
= (r
, g
, b
, 1.0)
545 nodes
= mat
.node_tree
.nodes
547 # support for multilanguage
548 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
549 mat
.node_tree
.nodes
.remove(node
) # remove not used
551 node
= nodes
.new('ShaderNodeBsdfTransparent')
552 node
.name
= 'Transparent_0'
553 node
.location
= 250, 160
554 node
.inputs
[0].default_value
= [r
, g
, b
, alpha
]
556 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
557 node
.location
= 700, 160
560 outn
= nodes
['Transparent_0'].outputs
[0]
561 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
562 mat
.node_tree
.links
.new(outn
, inn
)
567 # --------------------------------------------------------------------
568 # Create cycles glossy material
569 # --------------------------------------------------------------------
570 def create_glossy_material(matname
, replace
, r
, g
, b
, rv
=0.578, gv
=0.555, bv
=0.736, rvalue
=0.2):
571 # Avoid duplicate materials
573 matlist
= bpy
.data
.materials
575 if m
.name
== matname
:
578 mat
= bpy
.data
.materials
.new(matname
)
580 mat
.diffuse_color
= (rv
, gv
, bv
, 1.0)
581 nodes
= mat
.node_tree
.nodes
583 # support for multilanguage
584 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
585 mat
.node_tree
.nodes
.remove(node
) # remove not used
587 node
= nodes
.new('ShaderNodeBsdfGlossy')
588 node
.name
= 'Glossy_0'
589 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
590 node
.inputs
[1].default_value
= rvalue
591 node
.location
= 200, 160
593 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
594 node
.location
= 700, 160
597 outn
= nodes
['Glossy_0'].outputs
[0]
598 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
599 mat
.node_tree
.links
.new(outn
, inn
)
604 # --------------------------------------------------------------------
605 # Create cycles emission material
606 # --------------------------------------------------------------------
607 def create_emission_material(matname
, replace
, r
, g
, b
, energy
):
608 # Avoid duplicate materials
610 matlist
= bpy
.data
.materials
612 if m
.name
== matname
:
615 mat
= bpy
.data
.materials
.new(matname
)
617 nodes
= mat
.node_tree
.nodes
619 # support for multilanguage
620 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
621 mat
.node_tree
.nodes
.remove(node
) # remove not used
623 node
= nodes
.new('ShaderNodeEmission')
624 node
.name
= 'Emission_0'
625 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
626 node
.inputs
[1].default_value
= energy
627 node
.location
= 200, 160
629 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
630 node
.location
= 700, 160
633 outn
= nodes
['Emission_0'].outputs
[0]
634 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
635 mat
.node_tree
.links
.new(outn
, inn
)
640 # --------------------------------------------------------------------
641 # Create cycles glass material
642 # --------------------------------------------------------------------
643 def create_old_glass_material(matname
, replace
, rv
=0.352716, gv
=0.760852, bv
=0.9):
644 # Avoid duplicate materials
646 matlist
= bpy
.data
.materials
648 if m
.name
== matname
:
651 mat
= bpy
.data
.materials
.new(matname
)
653 mat
.diffuse_color
= (rv
, gv
, bv
, 1.0)
654 nodes
= mat
.node_tree
.nodes
656 # support for multilanguage
657 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
658 mat
.node_tree
.nodes
.remove(node
) # remove not used
660 node
= nodes
.new('ShaderNodeLightPath')
661 node
.name
= 'Light_0'
662 node
.location
= 10, 160
664 node
= nodes
.new('ShaderNodeBsdfGlass')
665 node
.name
= 'Glass_0'
666 node
.location
= 250, 300
668 node
= nodes
.new('ShaderNodeBsdfTransparent')
669 node
.name
= 'Transparent_0'
670 node
.location
= 250, 0
672 node
= nodes
.new('ShaderNodeMixShader')
674 node
.inputs
[0].default_value
= 0.1
675 node
.location
= 500, 160
677 node
= nodes
.new('ShaderNodeMixShader')
679 node
.inputs
[0].default_value
= 0.1
680 node
.location
= 690, 290
682 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
683 node
.location
= 920, 290
686 outn
= nodes
['Light_0'].outputs
[1]
687 inn
= nodes
['Mix_0'].inputs
[0]
688 mat
.node_tree
.links
.new(outn
, inn
)
690 outn
= nodes
['Light_0'].outputs
[2]
691 inn
= nodes
['Mix_1'].inputs
[0]
692 mat
.node_tree
.links
.new(outn
, inn
)
694 outn
= nodes
['Glass_0'].outputs
[0]
695 inn
= nodes
['Mix_0'].inputs
[1]
696 mat
.node_tree
.links
.new(outn
, inn
)
698 outn
= nodes
['Transparent_0'].outputs
[0]
699 inn
= nodes
['Mix_0'].inputs
[2]
700 mat
.node_tree
.links
.new(outn
, inn
)
702 outn
= nodes
['Mix_0'].outputs
[0]
703 inn
= nodes
['Mix_1'].inputs
[1]
704 mat
.node_tree
.links
.new(outn
, inn
)
706 outn
= nodes
['Mix_1'].outputs
[0]
707 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
708 mat
.node_tree
.links
.new(outn
, inn
)
713 # --------------------------------------------------------------------
714 # Create cycles brick texture material
715 # --------------------------------------------------------------------
716 def create_brick_material(matname
, replace
, r
, g
, b
, rv
=0.8, gv
=0.636, bv
=0.315):
717 # Avoid duplicate materials
719 matlist
= bpy
.data
.materials
721 if m
.name
== matname
:
724 mat
= bpy
.data
.materials
.new(matname
)
726 mat
.diffuse_color
= (rv
, gv
, bv
, 1.0)
727 nodes
= mat
.node_tree
.nodes
729 # support for multilanguage
730 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
731 node
.name
= 'Diffuse BSDF'
732 node
.label
= 'Diffuse BSDF'
734 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
735 node
.location
= 500, 160
737 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
738 node
.location
= 700, 160
740 node
= nodes
.new('ShaderNodeTexBrick')
741 node
.name
= 'Brick_0'
742 node
.inputs
[3].default_value
= [0.407, 0.411, 0.394, 1] # mortar color
743 node
.inputs
[4].default_value
= 3 # scale
744 node
.inputs
[5].default_value
= 0.001 # mortar
745 node
.inputs
[7].default_value
= 0.60 # size_w
746 node
.inputs
[8].default_value
= 0.30 # size_h
747 node
.location
= 300, 160
749 node
= nodes
.new('ShaderNodeRGB')
751 node
.outputs
[0].default_value
= [r
, g
, b
, 1]
752 node
.location
= 70, 160
755 outn
= nodes
['RGB_0'].outputs
['Color']
756 inn
= nodes
['Brick_0'].inputs
['Color1']
757 mat
.node_tree
.links
.new(outn
, inn
)
759 inn
= nodes
['Brick_0'].inputs
['Color2']
760 mat
.node_tree
.links
.new(outn
, inn
)
762 outn
= nodes
['Brick_0'].outputs
['Color']
763 inn
= nodes
['Diffuse BSDF'].inputs
['Color']
764 mat
.node_tree
.links
.new(outn
, inn
)
769 # --------------------------------------------------------------------
770 # Create cycles fabric texture material
771 # --------------------------------------------------------------------
772 def create_fabric_material(matname
, replace
, r
, g
, b
, rv
=0.8, gv
=0.636, bv
=0.315):
773 # Avoid duplicate materials
775 matlist
= bpy
.data
.materials
777 if m
.name
== matname
:
780 mat
= bpy
.data
.materials
.new(matname
)
782 mat
.diffuse_color
= (rv
, gv
, bv
, 1.0)
783 nodes
= mat
.node_tree
.nodes
785 # support for multilanguage
786 node
= nodes
.new('ShaderNodeBsdfDiffuse')
787 node
.name
= 'Diffuse BSDF'
788 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
789 node
.location
= 810, 270
791 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
792 node
.location
= 1210, 320
794 node
= nodes
.new('ShaderNodeTexCoord')
795 node
.name
= 'UVCoordinates'
796 node
.location
= 26, 395
798 node
= nodes
.new('ShaderNodeMapping')
799 node
.name
= 'UVMapping'
800 node
.location
= 266, 380
801 node
.inputs
['Scale'].default_value
[0] = 1000
802 node
.inputs
['Scale'].default_value
[1] = 1000
803 node
.inputs
['Scale'].default_value
[2] = 1000
805 # ===========================================================================
807 # ===========================================================================
810 realpath
= path
.join(path
.dirname(__file__
), "images", "fabric_diffuse.png")
811 print("Loading: " + realpath
)
813 img
= bpy
.data
.images
.load(realpath
)
815 raise NameError("Cannot load image %s" % realpath
)
817 # Create image texture from image
818 ctex
= bpy
.data
.textures
.new('ColorTex', type='IMAGE')
821 node
= nodes
.new('ShaderNodeTexImage')
823 node
.image
= ctex
.image
824 node
.location
= 615, 350
826 node
= nodes
.new('ShaderNodeBsdfTransparent')
827 node
.name
= 'Transparent1'
828 node
.location
= 810, 395
829 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
831 node
= nodes
.new('ShaderNodeAddShader')
833 node
.location
= 1040, 356
836 outn
= nodes
['UVCoordinates'].outputs
['UV']
837 inn
= nodes
['UVMapping'].inputs
['Vector']
838 mat
.node_tree
.links
.new(outn
, inn
)
840 outn
= nodes
['UVMapping'].outputs
['Vector']
841 inn
= nodes
['Image1'].inputs
['Vector']
842 mat
.node_tree
.links
.new(outn
, inn
)
844 outn
= nodes
['Image1'].outputs
['Color']
845 inn
= nodes
['Diffuse BSDF'].inputs
['Color']
846 mat
.node_tree
.links
.new(outn
, inn
)
848 outn
= nodes
['Transparent1'].outputs
['BSDF']
849 inn
= nodes
['Add1'].inputs
[0]
850 mat
.node_tree
.links
.new(outn
, inn
)
852 outn
= nodes
['Diffuse BSDF'].outputs
['BSDF']
853 inn
= nodes
['Add1'].inputs
[1]
854 mat
.node_tree
.links
.new(outn
, inn
)
856 outn
= nodes
['Add1'].outputs
['Shader']
857 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
858 mat
.node_tree
.links
.new(outn
, inn
)
863 # --------------------------------------------------------------------
865 # --------------------------------------------------------------------
866 def copy_binfile(fromfile
, tofile
):
867 with
open(fromfile
, 'rb') as f1
:
868 with
open(tofile
, 'wb') as f2
:
870 mybytes
= f1
.read(1024)
877 # --------------------------------------------------------------------
878 # Parent object (keep positions)
879 # --------------------------------------------------------------------
880 def parentobject(parentobj
, childobj
):
881 # noinspection PyBroadException
883 bpy
.ops
.object.select_all(action
='DESELECT')
884 bpy
.context
.view_layer
.objects
.active
= parentobj
885 parentobj
.select_set(True)
886 childobj
.select_set(True)
887 bpy
.ops
.object.parent_set(type='OBJECT', keep_transform
=False)
893 # ------------------------------------------------------------------------------
896 # objName: Object name
900 # tube: True create a tube, False only sides
901 # ------------------------------------------------------------------------------
902 def create_control_box(objname
, x
, y
, z
, tube
=True):
903 myvertex
= [(-x
/ 2, 0, 0.0),
913 myfaces
= [(0, 1, 2, 3), (0, 4, 5, 1), (1, 5, 6, 2), (3, 7, 4, 0), (2, 6, 7, 3), (5, 4, 7, 6)]
915 myfaces
= [(0, 4, 5, 1), (2, 6, 7, 3)]
917 mesh
= bpy
.data
.meshes
.new(objname
)
918 myobject
= bpy
.data
.objects
.new(objname
, mesh
)
920 myobject
.location
= bpy
.context
.scene
.cursor
.location
921 bpy
.context
.collection
.objects
.link(myobject
)
923 mesh
.from_pydata(myvertex
, [], myfaces
)
924 mesh
.update(calc_edges
=True)
929 # ------------------------------------------------------------------------------
930 # Remove all children objects
931 # ------------------------------------------------------------------------------
932 def remove_children(myobject
):
934 for child
in myobject
.children
:
935 # noinspection PyBroadException
937 # noinspection PyBroadException
939 # remove child relationship
940 for grandchild
in child
.children
:
941 grandchild
.parent
= None
943 for mod
in child
.modifiers
:
944 bpy
.ops
.object.modifier_remove(name
=mod
.name
)
948 if child
.type == 'MESH':
950 child
.select_set(True)
951 bpy
.ops
.object.delete()
952 bpy
.data
.meshes
.remove(old
)
953 if child
.type == 'CURVE':
954 child
.select_set(True)
955 bpy
.ops
.object.delete()
960 # --------------------------------------------------------------------
962 # --------------------------------------------------------------------
963 def get_allparents(myobj
):
966 while obj
.parent
is not None:
976 # --------------------------------------------------------------------
977 # Verify all faces are in vertice group to avoid Blander crash
979 # Review the faces array and remove any vertex out of the range
980 # this avoid any bug that can appear avoiding Blender crash
981 # --------------------------------------------------------------------
982 def check_mesh_errors(myvertices
, myfaces
):
983 vmax
= len(myvertices
)
988 if v
< 0 or v
> vmax
:
989 print("Face=" + str(f
) + "->removed vertex=" + str(v
))