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 from importlib
import reload
26 from blenderkit
import utils
, ui
32 def append_brush(file_name
, brushname
=None, link
=False, fake_user
=True):
34 with bpy
.data
.libraries
.load(file_name
, link
=link
, relative
=True) as (data_from
, data_to
):
35 for m
in data_from
.brushes
:
36 if m
== brushname
or brushname
is None:
39 brush
= bpy
.data
.brushes
[brushname
]
41 brush
.use_fake_user
= True
45 def append_material(file_name
, matname
=None, link
=False, fake_user
=True):
46 '''append a material type asset'''
47 # first, we have to check if there is a material with same name
48 # in previous step there's check if the imported material
49 # is already in the scene, so we know same name != same material
51 mats_before
= bpy
.data
.materials
.keys()
53 with bpy
.data
.libraries
.load(file_name
, link
=link
, relative
=True) as (data_from
, data_to
):
54 for m
in data_from
.materials
:
55 if m
== matname
or matname
is None:
56 data_to
.materials
= [m
]
61 # we have to find the new material :(
62 for mname
in bpy
.data
.materials
.keys():
63 if mname
not in mats_before
:
64 mat
= bpy
.data
.materials
[mname
]
68 mat
.use_fake_user
= True
73 def append_scene(file_name
, scenename
=None, link
=False, fake_user
=False):
74 '''append a scene type asset'''
75 with bpy
.data
.libraries
.load(file_name
, link
=link
, relative
=True) as (data_from
, data_to
):
76 for s
in data_from
.scenes
:
77 if s
== scenename
or scenename
is None:
80 scene
= bpy
.data
.scenes
[scenename
]
82 scene
.use_fake_user
= True
83 # scene has to have a new uuid, so user reports aren't screwed.
84 scene
['uuid'] = str(uuid
.uuid4())
88 def link_collection(file_name
, obnames
=[], location
=(0, 0, 0), link
=False, parent
= None, **kwargs
):
89 '''link an instanced group - model type asset'''
90 sel
= utils
.selection_get()
92 with bpy
.data
.libraries
.load(file_name
, link
=link
, relative
=True) as (data_from
, data_to
):
94 for col
in data_from
.collections
:
95 print('linking this ', col
)
96 if col
== kwargs
['name']:
97 data_to
.collections
= [col
]
100 if kwargs
.get('rotation') is not None:
101 rotation
= kwargs
['rotation']
103 bpy
.ops
.object.empty_add(type='PLAIN_AXES', location
=location
, rotation
=rotation
)
104 main_object
= bpy
.context
.view_layer
.objects
.active
105 main_object
.instance_type
= 'COLLECTION'
107 main_object
.parent
= parent
108 main_object
.matrix_world
.translation
= location
110 for col
in bpy
.data
.collections
:
111 if col
.library
is not None:
112 fp
= bpy
.path
.abspath(col
.library
.filepath
)
113 fp1
= bpy
.path
.abspath(file_name
)
115 main_object
.instance_collection
= col
118 main_object
.name
= main_object
.instance_collection
.name
120 # bpy.ops.wm.link(directory=file_name + "/Collection/", filename=kwargs['name'], link=link, instance_collections=True,
122 # main_object = bpy.context.view_layer.objects.active
123 # if kwargs.get('rotation') is not None:
124 # main_object.rotation_euler = kwargs['rotation']
125 # main_object.location = location
127 utils
.selection_set(sel
)
128 return main_object
, []
131 def append_particle_system(file_name
, obnames
=[], location
=(0, 0, 0), link
=False, **kwargs
):
132 '''link an instanced group - model type asset'''
135 with bpy
.data
.libraries
.load(file_name
, link
=link
, relative
=True) as (data_from
, data_to
):
136 for ps
in data_from
.particles
:
138 data_to
.particles
= pss
140 s
= bpy
.context
.scene
141 sel
= utils
.selection_get()
143 target_object
= bpy
.context
.scene
.objects
.get(kwargs
['target_object'])
144 if target_object
is not None and target_object
.type == 'MESH':
145 target_object
.select_set(True)
146 bpy
.context
.view_layer
.objects
.active
= target_object
149 # now let's tune this ps to the particular objects area:
151 for p
in target_object
.data
.polygons
:
153 count
= int(ps
.count
* totarea
)
154 if ps
.child_type
in ('INTERPOLATED', 'SIMPLE'):
155 total_count
= count
* ps
.rendered_child_count
156 disp_count
= count
* ps
.child_nbr
160 total_max_threshold
= 50000
161 # emitting too many parent particles just kills blender now:
162 if count
> total_max_threshold
:
163 ratio
= round(count
/ total_max_threshold
)
165 if ps
.child_type
in ('INTERPOLATED', 'SIMPLE'):
166 ps
.rendered_child_count
*= ratio
168 ps
.child_type
= 'INTERPOLATED'
169 ps
.rendered_child_count
= ratio
170 count
= max(2, int(count
/ ratio
))
171 ps
.display_percentage
= min(ps
.display_percentage
, max(1, int(100 * threshold
/ total_count
)))
174 bpy
.ops
.object.particle_system_add()
175 target_object
.particle_systems
[-1].settings
= ps
177 target_object
.select_set(False)
178 utils
.selection_set(sel
)
179 return target_object
, []
182 def append_objects(file_name
, obnames
=[], location
=(0, 0, 0), link
=False, **kwargs
):
183 '''append objects into scene individually'''
185 with bpy
.data
.libraries
.load(file_name
, link
=link
, relative
=True) as (data_from
, data_to
):
187 for ob
in data_from
.objects
:
188 if ob
in obnames
or obnames
== []:
190 data_to
.objects
= sobs
191 # data_to.objects = data_from.objects#[name for name in data_from.objects if name.startswith("house")]
194 scene
= bpy
.context
.scene
195 sel
= utils
.selection_get()
196 bpy
.ops
.object.select_all(action
='DESELECT')
198 return_obs
= [] # this might not be needed, but better be sure to rewrite the list.
202 for obj
in data_to
.objects
:
204 # if obj.name not in scene.objects:
205 scene
.collection
.objects
.link(obj
)
206 if obj
.parent
is None:
207 obj
.location
= location
210 # we need to unhide object so make_local op can use those too.
212 if obj
.hide_viewport
:
213 hidden_objects
.append(obj
)
214 obj
.hide_viewport
= False
215 return_obs
.append(obj
)
216 # Only after all objects are in scene! Otherwise gets broken relationships
218 bpy
.ops
.object.make_local(type='SELECT_OBJECT')
219 for ob
in hidden_objects
:
220 ob
.hide_viewport
= True
222 if kwargs
.get('rotation') is not None:
223 main_object
.rotation_euler
= kwargs
['rotation']
225 if kwargs
.get('parent') is not None:
226 main_object
.parent
= bpy
.data
.objects
[kwargs
['parent']]
227 main_object
.matrix_world
.translation
= location
229 bpy
.ops
.object.select_all(action
='DESELECT')
231 utils
.selection_set(sel
)
234 return main_object
, return_obs