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
.scene
.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
.scene
.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
:
82 myobject
.select
= True
83 bpy
.context
.scene
.objects
.active
= myobject
84 if bpy
.context
.scene
.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
.scene
.objects
.active
= myobject
93 if bpy
.context
.scene
.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(False)
105 myobject
.select
= True
106 bpy
.context
.scene
.objects
.active
= myobject
107 if bpy
.context
.scene
.objects
.active
.name
== myobject
.name
:
108 bpy
.ops
.object.modifier_add(type='MIRROR')
109 for mod
in myobject
.modifiers
:
110 if mod
.type == 'MIRROR':
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(False)
134 myobject
.select
= True
135 bpy
.context
.scene
.objects
.active
= myobject
136 if bpy
.context
.scene
.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
.scene
.objects
.active
= myobject
166 if bpy
.context
.scene
.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
.scene
.objects
.active
= myobject
179 if bpy
.context
.scene
.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
.scene
.objects
.active
= myobject
194 if bpy
.context
.scene
.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
.scene
.objects
.active
= myobject
206 if bpy
.context
.scene
.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
.scene
.objects
.active
= myobject
215 myobject
.select
= True
216 bpy
.context
.object.active_material_index
= idx
217 if bpy
.context
.scene
.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
= True
230 bpy
.context
.scene
.objects
.active
= myobject
231 if bpy
.context
.scene
.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
= True
247 bpy
.context
.scene
.objects
.active
= myobject
248 if bpy
.context
.scene
.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
= True
276 bpy
.context
.scene
.objects
.active
= myobject
277 if bpy
.context
.scene
.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
= True
292 bpy
.context
.scene
.objects
.active
= myobject
293 if bpy
.context
.scene
.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
) # viewport color
333 nodes
= mat
.node_tree
.nodes
335 # support for multilanguage
336 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
337 node
.name
= 'Diffuse BSDF'
338 node
.label
= 'Diffuse BSDF'
340 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
341 node
.location
= 200, 320
343 node
= nodes
.new('ShaderNodeBsdfGlossy')
344 node
.name
= 'Glossy_0'
345 node
.location
= 200, 0
347 node
= nodes
.new('ShaderNodeMixShader')
349 node
.inputs
[0].default_value
= mix
350 node
.location
= 500, 160
352 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
353 node
.location
= 1100, 160
356 outn
= nodes
['Diffuse BSDF'].outputs
[0]
357 inn
= nodes
['Mix_0'].inputs
[1]
358 mat
.node_tree
.links
.new(outn
, inn
)
360 outn
= nodes
['Glossy_0'].outputs
[0]
361 inn
= nodes
['Mix_0'].inputs
[2]
362 mat
.node_tree
.links
.new(outn
, inn
)
364 if twosides
is False:
365 outn
= nodes
['Mix_0'].outputs
[0]
366 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
367 mat
.node_tree
.links
.new(outn
, inn
)
370 node
= nodes
.new('ShaderNodeNewGeometry')
371 node
.name
= 'Input_1'
372 node
.location
= -80, -70
374 node
= nodes
.new('ShaderNodeBsdfDiffuse')
375 node
.name
= 'Diffuse_1'
376 node
.inputs
[0].default_value
= [0.30, 0.30, 0.30, 1]
377 node
.location
= 200, -280
379 node
= nodes
.new('ShaderNodeMixShader')
381 node
.inputs
[0].default_value
= mix
382 node
.location
= 800, -70
384 outn
= nodes
['Input_1'].outputs
[6]
385 inn
= nodes
['Mix_1'].inputs
[0]
386 mat
.node_tree
.links
.new(outn
, inn
)
388 outn
= nodes
['Diffuse_1'].outputs
[0]
389 inn
= nodes
['Mix_1'].inputs
[2]
390 mat
.node_tree
.links
.new(outn
, inn
)
392 outn
= nodes
['Mix_0'].outputs
[0]
393 inn
= nodes
['Mix_1'].inputs
[1]
394 mat
.node_tree
.links
.new(outn
, inn
)
396 outn
= nodes
['Mix_1'].outputs
[0]
397 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
398 mat
.node_tree
.links
.new(outn
, inn
)
403 # --------------------------------------------------------------------
404 # Create cycles translucent material
405 # --------------------------------------------------------------------
406 def create_translucent_material(matname
, replace
, r
, g
, b
, rv
=0.8, gv
=0.8, bv
=0.8, mix
=0.1):
407 # Avoid duplicate materials
409 matlist
= bpy
.data
.materials
411 if m
.name
== matname
:
414 mat
= bpy
.data
.materials
.new(matname
)
415 mat
.diffuse_color
= (rv
, gv
, bv
) # viewport color
417 nodes
= mat
.node_tree
.nodes
419 # support for multilanguage
420 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
421 node
.name
= 'Diffuse BSDF'
422 node
.label
= 'Diffuse BSDF'
424 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
425 node
.location
= 200, 320
427 node
= nodes
.new('ShaderNodeBsdfTranslucent')
428 node
.name
= 'Translucent_0'
429 node
.location
= 200, 0
431 node
= nodes
.new('ShaderNodeMixShader')
433 node
.inputs
[0].default_value
= mix
434 node
.location
= 500, 160
436 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
437 node
.location
= 1100, 160
440 outn
= nodes
['Diffuse BSDF'].outputs
[0]
441 inn
= nodes
['Mix_0'].inputs
[1]
442 mat
.node_tree
.links
.new(outn
, inn
)
444 outn
= nodes
['Translucent_0'].outputs
[0]
445 inn
= nodes
['Mix_0'].inputs
[2]
446 mat
.node_tree
.links
.new(outn
, inn
)
448 outn
= nodes
['Mix_0'].outputs
[0]
449 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
450 mat
.node_tree
.links
.new(outn
, inn
)
455 # --------------------------------------------------------------------
456 # Create cycles glass material
457 # --------------------------------------------------------------------
458 def create_glass_material(matname
, replace
, rv
=0.333, gv
=0.342, bv
=0.9):
459 # Avoid duplicate materials
461 matlist
= bpy
.data
.materials
463 if m
.name
== matname
:
466 mat
= bpy
.data
.materials
.new(matname
)
468 mat
.diffuse_color
= (rv
, gv
, bv
)
469 nodes
= mat
.node_tree
.nodes
471 # support for multilanguage
472 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
473 mat
.node_tree
.nodes
.remove(node
) # remove not used
475 node
= nodes
.new('ShaderNodeLightPath')
476 node
.name
= 'Light_0'
477 node
.location
= 10, 160
479 node
= nodes
.new('ShaderNodeBsdfRefraction')
480 node
.name
= 'Refraction_0'
481 node
.inputs
[2].default_value
= 1 # IOR 1.0
482 node
.location
= 250, 400
484 node
= nodes
.new('ShaderNodeBsdfGlossy')
485 node
.name
= 'Glossy_0'
486 node
.distribution
= 'SHARP'
487 node
.location
= 250, 100
489 node
= nodes
.new('ShaderNodeBsdfTransparent')
490 node
.name
= 'Transparent_0'
491 node
.location
= 500, 10
493 node
= nodes
.new('ShaderNodeMixShader')
495 node
.inputs
[0].default_value
= 0.035
496 node
.location
= 500, 160
498 node
= nodes
.new('ShaderNodeMixShader')
500 node
.inputs
[0].default_value
= 0.1
501 node
.location
= 690, 290
503 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
504 node
.location
= 920, 290
507 outn
= nodes
['Light_0'].outputs
[1]
508 inn
= nodes
['Mix_1'].inputs
[0]
509 mat
.node_tree
.links
.new(outn
, inn
)
511 outn
= nodes
['Refraction_0'].outputs
[0]
512 inn
= nodes
['Mix_0'].inputs
[1]
513 mat
.node_tree
.links
.new(outn
, inn
)
515 outn
= nodes
['Glossy_0'].outputs
[0]
516 inn
= nodes
['Mix_0'].inputs
[2]
517 mat
.node_tree
.links
.new(outn
, inn
)
519 outn
= nodes
['Mix_0'].outputs
[0]
520 inn
= nodes
['Mix_1'].inputs
[1]
521 mat
.node_tree
.links
.new(outn
, inn
)
523 outn
= nodes
['Transparent_0'].outputs
[0]
524 inn
= nodes
['Mix_1'].inputs
[2]
525 mat
.node_tree
.links
.new(outn
, inn
)
527 outn
= nodes
['Mix_1'].outputs
[0]
528 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
529 mat
.node_tree
.links
.new(outn
, inn
)
534 # ---------------------------------------------
535 # Create cycles transparents material
536 # --------------------------------------------------------------------
537 def create_transparent_material(matname
, replace
, r
=1, g
=1, b
=1, alpha
=0):
538 # Avoid duplicate materials
540 matlist
= bpy
.data
.materials
542 if m
.name
== matname
:
545 mat
= bpy
.data
.materials
.new(matname
)
547 mat
.diffuse_color
= (r
, g
, b
)
548 nodes
= mat
.node_tree
.nodes
550 # support for multilanguage
551 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
552 mat
.node_tree
.nodes
.remove(node
) # remove not used
554 node
= nodes
.new('ShaderNodeBsdfTransparent')
555 node
.name
= 'Transparent_0'
556 node
.location
= 250, 160
557 node
.inputs
[0].default_value
= [r
, g
, b
, alpha
]
559 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
560 node
.location
= 700, 160
563 outn
= nodes
['Transparent_0'].outputs
[0]
564 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
565 mat
.node_tree
.links
.new(outn
, inn
)
570 # --------------------------------------------------------------------
571 # Create cycles glossy material
572 # --------------------------------------------------------------------
573 def create_glossy_material(matname
, replace
, r
, g
, b
, rv
=0.578, gv
=0.555, bv
=0.736, rvalue
=0.2):
574 # Avoid duplicate materials
576 matlist
= bpy
.data
.materials
578 if m
.name
== matname
:
581 mat
= bpy
.data
.materials
.new(matname
)
583 mat
.diffuse_color
= (rv
, gv
, bv
)
584 nodes
= mat
.node_tree
.nodes
586 # support for multilanguage
587 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
588 mat
.node_tree
.nodes
.remove(node
) # remove not used
590 node
= nodes
.new('ShaderNodeBsdfGlossy')
591 node
.name
= 'Glossy_0'
592 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
593 node
.inputs
[1].default_value
= rvalue
594 node
.location
= 200, 160
596 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
597 node
.location
= 700, 160
600 outn
= nodes
['Glossy_0'].outputs
[0]
601 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
602 mat
.node_tree
.links
.new(outn
, inn
)
607 # --------------------------------------------------------------------
608 # Create cycles emission material
609 # --------------------------------------------------------------------
610 def create_emission_material(matname
, replace
, r
, g
, b
, energy
):
611 # Avoid duplicate materials
613 matlist
= bpy
.data
.materials
615 if m
.name
== matname
:
618 mat
= bpy
.data
.materials
.new(matname
)
620 nodes
= mat
.node_tree
.nodes
622 # support for multilanguage
623 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
624 mat
.node_tree
.nodes
.remove(node
) # remove not used
626 node
= nodes
.new('ShaderNodeEmission')
627 node
.name
= 'Emission_0'
628 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
629 node
.inputs
[1].default_value
= energy
630 node
.location
= 200, 160
632 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
633 node
.location
= 700, 160
636 outn
= nodes
['Emission_0'].outputs
[0]
637 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
638 mat
.node_tree
.links
.new(outn
, inn
)
643 # --------------------------------------------------------------------
644 # Create cycles glass material
645 # --------------------------------------------------------------------
646 def create_old_glass_material(matname
, replace
, rv
=0.352716, gv
=0.760852, bv
=0.9):
647 # Avoid duplicate materials
649 matlist
= bpy
.data
.materials
651 if m
.name
== matname
:
654 mat
= bpy
.data
.materials
.new(matname
)
656 mat
.diffuse_color
= (rv
, gv
, bv
)
657 nodes
= mat
.node_tree
.nodes
659 # support for multilanguage
660 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
661 mat
.node_tree
.nodes
.remove(node
) # remove not used
663 node
= nodes
.new('ShaderNodeLightPath')
664 node
.name
= 'Light_0'
665 node
.location
= 10, 160
667 node
= nodes
.new('ShaderNodeBsdfGlass')
668 node
.name
= 'Glass_0'
669 node
.location
= 250, 300
671 node
= nodes
.new('ShaderNodeBsdfTransparent')
672 node
.name
= 'Transparent_0'
673 node
.location
= 250, 0
675 node
= nodes
.new('ShaderNodeMixShader')
677 node
.inputs
[0].default_value
= 0.1
678 node
.location
= 500, 160
680 node
= nodes
.new('ShaderNodeMixShader')
682 node
.inputs
[0].default_value
= 0.1
683 node
.location
= 690, 290
685 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
686 node
.location
= 920, 290
689 outn
= nodes
['Light_0'].outputs
[1]
690 inn
= nodes
['Mix_0'].inputs
[0]
691 mat
.node_tree
.links
.new(outn
, inn
)
693 outn
= nodes
['Light_0'].outputs
[2]
694 inn
= nodes
['Mix_1'].inputs
[0]
695 mat
.node_tree
.links
.new(outn
, inn
)
697 outn
= nodes
['Glass_0'].outputs
[0]
698 inn
= nodes
['Mix_0'].inputs
[1]
699 mat
.node_tree
.links
.new(outn
, inn
)
701 outn
= nodes
['Transparent_0'].outputs
[0]
702 inn
= nodes
['Mix_0'].inputs
[2]
703 mat
.node_tree
.links
.new(outn
, inn
)
705 outn
= nodes
['Mix_0'].outputs
[0]
706 inn
= nodes
['Mix_1'].inputs
[1]
707 mat
.node_tree
.links
.new(outn
, inn
)
709 outn
= nodes
['Mix_1'].outputs
[0]
710 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
711 mat
.node_tree
.links
.new(outn
, inn
)
716 # --------------------------------------------------------------------
717 # Create cycles brick texture material
718 # --------------------------------------------------------------------
719 def create_brick_material(matname
, replace
, r
, g
, b
, rv
=0.8, gv
=0.636, bv
=0.315):
720 # Avoid duplicate materials
722 matlist
= bpy
.data
.materials
724 if m
.name
== matname
:
727 mat
= bpy
.data
.materials
.new(matname
)
729 mat
.diffuse_color
= (rv
, gv
, bv
)
730 nodes
= mat
.node_tree
.nodes
732 # support for multilanguage
733 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
734 node
.name
= 'Diffuse BSDF'
735 node
.label
= 'Diffuse BSDF'
737 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
738 node
.location
= 500, 160
740 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
741 node
.location
= 700, 160
743 node
= nodes
.new('ShaderNodeTexBrick')
744 node
.name
= 'Brick_0'
745 node
.inputs
[3].default_value
= [0.407, 0.411, 0.394, 1] # mortar color
746 node
.inputs
[4].default_value
= 3 # scale
747 node
.inputs
[5].default_value
= 0.001 # mortar
748 node
.inputs
[7].default_value
= 0.60 # size_w
749 node
.inputs
[8].default_value
= 0.30 # size_h
750 node
.location
= 300, 160
752 node
= nodes
.new('ShaderNodeRGB')
754 node
.outputs
[0].default_value
= [r
, g
, b
, 1]
755 node
.location
= 70, 160
758 outn
= nodes
['RGB_0'].outputs
['Color']
759 inn
= nodes
['Brick_0'].inputs
['Color1']
760 mat
.node_tree
.links
.new(outn
, inn
)
762 inn
= nodes
['Brick_0'].inputs
['Color2']
763 mat
.node_tree
.links
.new(outn
, inn
)
765 outn
= nodes
['Brick_0'].outputs
['Color']
766 inn
= nodes
['Diffuse BSDF'].inputs
['Color']
767 mat
.node_tree
.links
.new(outn
, inn
)
772 # --------------------------------------------------------------------
773 # Create cycles fabric texture material
774 # --------------------------------------------------------------------
775 def create_fabric_material(matname
, replace
, r
, g
, b
, rv
=0.8, gv
=0.636, bv
=0.315):
776 # Avoid duplicate materials
778 matlist
= bpy
.data
.materials
780 if m
.name
== matname
:
783 mat
= bpy
.data
.materials
.new(matname
)
785 mat
.diffuse_color
= (rv
, gv
, bv
)
786 nodes
= mat
.node_tree
.nodes
788 # support for multilanguage
789 node
= nodes
[get_node_index(nodes
, 'BSDF_DIFFUSE')]
790 node
.name
= 'Diffuse BSDF'
791 node
.label
= 'Diffuse BSDF'
793 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
794 node
.location
= 810, 270
796 node
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')]
797 node
.location
= 1210, 320
799 node
= nodes
.new('ShaderNodeTexCoord')
800 node
.name
= 'UVCoordinates'
801 node
.location
= 26, 395
803 node
= nodes
.new('ShaderNodeMapping')
804 node
.name
= 'UVMapping'
805 node
.location
= 266, 380
810 # ===========================================================================
812 # ===========================================================================
815 realpath
= path
.join(path
.dirname(__file__
), "images", "fabric_diffuse.png")
816 print("Loading: " + realpath
)
818 img
= bpy
.data
.images
.load(realpath
)
820 raise NameError("Cannot load image %s" % realpath
)
822 # Create image texture from image
823 ctex
= bpy
.data
.textures
.new('ColorTex', type='IMAGE')
826 node
= nodes
.new('ShaderNodeTexImage')
828 node
.image
= ctex
.image
829 node
.location
= 615, 350
831 node
= nodes
.new('ShaderNodeBsdfTransparent')
832 node
.name
= 'Transparent1'
833 node
.location
= 810, 395
834 node
.inputs
[0].default_value
= [r
, g
, b
, 1]
836 node
= nodes
.new('ShaderNodeAddShader')
838 node
.location
= 1040, 356
841 outn
= nodes
['UVCoordinates'].outputs
['UV']
842 inn
= nodes
['UVMapping'].inputs
['Vector']
843 mat
.node_tree
.links
.new(outn
, inn
)
845 outn
= nodes
['UVMapping'].outputs
['Vector']
846 inn
= nodes
['Image1'].inputs
['Vector']
847 mat
.node_tree
.links
.new(outn
, inn
)
849 outn
= nodes
['Image1'].outputs
['Color']
850 inn
= nodes
['Diffuse BSDF'].inputs
['Color']
851 mat
.node_tree
.links
.new(outn
, inn
)
853 outn
= nodes
['Transparent1'].outputs
['BSDF']
854 inn
= nodes
['Add1'].inputs
[0]
855 mat
.node_tree
.links
.new(outn
, inn
)
857 outn
= nodes
['Diffuse BSDF'].outputs
['BSDF']
858 inn
= nodes
['Add1'].inputs
[1]
859 mat
.node_tree
.links
.new(outn
, inn
)
861 outn
= nodes
['Add1'].outputs
['Shader']
862 inn
= nodes
[get_node_index(nodes
, 'OUTPUT_MATERIAL')].inputs
[0]
863 mat
.node_tree
.links
.new(outn
, inn
)
868 # --------------------------------------------------------------------
870 # --------------------------------------------------------------------
871 def copy_binfile(fromfile
, tofile
):
872 with
open(fromfile
, 'rb') as f1
:
873 with
open(tofile
, 'wb') as f2
:
875 mybytes
= f1
.read(1024)
882 # --------------------------------------------------------------------
883 # Parent object (keep positions)
884 # --------------------------------------------------------------------
885 def parentobject(parentobj
, childobj
):
886 # noinspection PyBroadException
888 bpy
.ops
.object.select_all(action
='DESELECT')
889 bpy
.context
.scene
.objects
.active
= parentobj
890 parentobj
.select
= True
891 childobj
.select
= True
892 bpy
.ops
.object.parent_set(type='OBJECT', keep_transform
=False)
898 # ------------------------------------------------------------------------------
901 # objName: Object name
905 # tube: True create a tube, False only sides
906 # ------------------------------------------------------------------------------
907 def create_control_box(objname
, x
, y
, z
, tube
=True):
908 myvertex
= [(-x
/ 2, 0, 0.0),
918 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)]
920 myfaces
= [(0, 4, 5, 1), (2, 6, 7, 3)]
922 mesh
= bpy
.data
.meshes
.new(objname
)
923 myobject
= bpy
.data
.objects
.new(objname
, mesh
)
925 myobject
.location
= bpy
.context
.scene
.cursor_location
926 bpy
.context
.scene
.objects
.link(myobject
)
928 mesh
.from_pydata(myvertex
, [], myfaces
)
929 mesh
.update(calc_edges
=True)
934 # ------------------------------------------------------------------------------
935 # Remove all children objects
936 # ------------------------------------------------------------------------------
937 def remove_children(myobject
):
939 for child
in myobject
.children
:
940 # noinspection PyBroadException
942 # noinspection PyBroadException
944 # remove child relationship
945 for grandchild
in child
.children
:
946 grandchild
.parent
= None
948 for mod
in child
.modifiers
:
949 bpy
.ops
.object.modifier_remove(name
=mod
.name
)
953 if child
.type == 'MESH':
956 bpy
.ops
.object.delete()
957 bpy
.data
.meshes
.remove(old
)
958 if child
.type == 'CURVE':
960 bpy
.ops
.object.delete()
965 # --------------------------------------------------------------------
967 # --------------------------------------------------------------------
968 def get_allparents(myobj
):
971 while obj
.parent
is not None:
981 # --------------------------------------------------------------------
982 # Verify all faces are in vertice group to avoid Blander crash
984 # Review the faces array and remove any vertex out of the range
985 # this avoid any bug that can appear avoiding Blender crash
986 # --------------------------------------------------------------------
987 def check_mesh_errors(myvertices
, myfaces
):
988 vmax
= len(myvertices
)
993 if v
< 0 or v
> vmax
:
994 print("Face=" + str(f
) + "->removed vertex=" + str(v
))