def draw(self, context): if addon_exists("kitops"): from kitops.addon.interface.panel import KO_PT_ui KO_PT_ui.draw(self, context) from kitops.addon.utility.addon import preference preference = preference() self.layout.separator() row = self.layout.row() row.label(text='Sort Modifiers') row.prop(preference, 'sort_modifiers', text='') if preference.sort_modifiers: row = self.layout.row(align=True) row.alignment = 'RIGHT' row.prop(preference, 'sort_bevel', text='', icon='MOD_BEVEL') row.prop(preference, 'sort_weighted_normal', text='', icon='MOD_NORMALEDIT') row.prop(preference, 'sort_array', text='', icon='MOD_ARRAY') row.prop(preference, 'sort_mirror', text='', icon='MOD_MIRROR') row.prop(preference, 'sort_simple_deform', text='', icon='MOD_SIMPLEDEFORM') row.prop(preference, 'sort_triangulate', text='', icon='MOD_TRIANGULATE')
def draw(self, context): """Draw all options for the user to input to.""" layout = self.layout scene = context.scene option = addon.option() col = layout.column(align=True) col.operator('ko.synth_bake', text="Bake Object", icon='EXPERIMENTAL') col.operator('ko.remove_wire_inserts', text='Remove Unused Wire INSERTs', icon='MESH_ICOSPHERE') col.operator('ko.synth_refresh_kpacks', text='Refresh KIT OPS KPACKS', icon='FILE_REFRESH') # col.operator('ko.synth_recalc_normals', text='Recalculate Normals', icon='NORMALS_FACE') TODO recalculate normals may still be introduced col.operator('ko.synth_reset_all', text='Reset SYNTH Settings', icon='DECORATE_OVERRIDE') col.separator() col.label(text='KIT OPS') kitops_preference = kitops_addon.preference() box = col.box() row = box.row() row.label(text='Mode') row.prop(kitops_preference, 'mode', expand=True)
def insert_add(op, context, boolean_solver): if bpy.app.version[1] > 90: kitops_preference = kitops_addon.preference() old_boolean_solver_ref = kitops_preference.boolean_solver uid = '' try: if bpy.app.version[1] > 90: kitops_preference.boolean_solver = boolean_solver uid = insert.add(op, context) except OSError: report_message = 'Failed to load .blend file for INSERT.' op.report({'ERROR'}, report_message) finally: if bpy.app.version[1] > 90: kitops_preference.boolean_solver = old_boolean_solver_ref return uid
def add_random_insert(op, context, layer, inserts, insert_frame_cache, rng=np.random.RandomState(123456), insert_name_ignore_list=[]): """Searches for and returns a random INSERT.""" option = addon.option() layer_inserts = [ insert for insert in inserts if insert.insert_name not in insert_name_ignore_list ] # construct probability profile p = [] total = len(layer_inserts) total_probabilities = 0 probabilities = [] for insert_entry in layer_inserts: if insert_entry.is_enabled: probability = insert_entry.proportionality else: probability = 0 probabilities.append(probability) total_probabilities += probability if total_probabilities != 0: for probability in probabilities: p.append(probability / total_probabilities) random_insert_index = rng.choice(range(0, len(layer_inserts)), p=p) random_insert = layer_inserts[random_insert_index] category_name = random_insert.category if bpy.app.version[1] > 90: kitops_preference = kitops_addon.preference() old_boolean_solver_ref = kitops_preference.boolean_solver try: if bpy.app.version[1] > 90: kitops_preference.boolean_solver = layer.boolean_solver for index, category in enumerate(option.kpack.categories): if category.name == category_name: if index < len(option.kpack.categories): category_item = option.kpack.categories[index] for index, blend in enumerate(category_item.blends): if blend.name == random_insert.insert_name: op.location = blend.location insert_obj = insert_frame_cache.get_insert_frame( op) if insert_obj is None: # will we ever retrieve an insert? all_equal = True for insert_entry in layer_inserts: if insert_entry.is_enabled and insert_entry.proportionality > 0: all_equal &= ( insert_entry.insert_name == random_insert.insert_name) if all_equal: return None, None else: return add_random_insert( op, context, layer, inserts, insert_frame_cache, rng, insert_name_ignore_list) # cleanup(op, context) return insert_obj, random_insert finally: if bpy.app.version[1] > 90: kitops_preference.boolean_solver = old_boolean_solver_ref return None, None
def to_object(self, op, context, convert_matrix): op.location = self.op_location if context.scene.kitopssynth.preview_mode and context.scene.kitopssynth.preview_type == 'FAST': #we're gonna draw something instead based on object bounding box.... kitops_preference = kitops_addon.preference() basename = os.path.basename(op.location) collection_name = regex.clean_name( basename[:-6].title(), use_re=kitops_preference.clean_datablock_names) insert_name = collection_name + " Preview" me = bpy.data.meshes.new(insert_name) insert_obj = bpy.data.objects.new(insert_name, me) insert_obj.kitopssynth_insert.is_preview_insert = True insert_obj.kitops.id = id.uuid() insert_obj.location = self.cache_location insert_obj.matrix_world = self.cache_matrix insert_obj.scale = self.cache_scale insert_obj.rotation_euler = self.cache_euler insert_obj.color = context.scene.kitopssynth.preview_color bm = bmesh.new() i = 0 for loc in self.bound_box: # v = bm.verts.new(insert_obj.matrix_world.inverted() @ Vector(loc)) v = bm.verts.new(loc) v.index = i i += 1 bm.verts.ensure_lookup_table() if len(bm.verts) == 8: bm.faces.new( [bm.verts[0], bm.verts[1], bm.verts[2], bm.verts[3]]) bm.faces.new( [bm.verts[7], bm.verts[6], bm.verts[5], bm.verts[4]]) bm.faces.new( [bm.verts[0], bm.verts[4], bm.verts[5], bm.verts[1]]) bm.faces.new( [bm.verts[5], bm.verts[6], bm.verts[2], bm.verts[1]]) bm.faces.new( [bm.verts[7], bm.verts[4], bm.verts[0], bm.verts[3]]) bm.faces.new( [bm.verts[7], bm.verts[3], bm.verts[2], bm.verts[6]]) bm.to_mesh(me) bm.free() if 'INSERTS' not in bpy.data.collections: context.scene.collection.children.link( bpy.data.collections.new(name='INSERTS')) collection_name = regex.clean_name( basename[:-6].title(), use_re=kitops_preference.clean_datablock_names) if collection_name not in bpy.data.collections: bpy.data.collections['INSERTS'].children.link( bpy.data.collections.new(name=collection_name)) bpy.data.collections[collection_name].objects.link(insert_obj) else: uid = insert_add(op, context, self.boolean_solver) insert_obj = get_insert(uid) if insert_obj == None: return None insert_obj.kitopssynth_insert.is_preview_insert = context.scene.kitopssynth.preview_mode # determine delta between central location and actual center. origin = insert_obj.location natural_center = 0.125 * sum( (Vector(b) for b in insert_obj.bound_box), Vector()) natural_center = insert_obj.matrix_world @ natural_center natural_center[2] = origin[2] rotated_origin = _rotate_around_pivot( natural_center, origin, self.kitopssynth.intended_rotation) local_vector = (rotated_origin - natural_center) * self.scale mx_inv = convert_matrix.inverted() mx_norm = mx_inv.transposed().to_3x3() delta_vector = mx_norm @ local_vector # assign the object's transform properties point = self.location + delta_vector insert_obj.hide_viewport = self.hide_viewport insert_obj.location = point insert_obj.matrix_world = self.matrix_world insert_obj.matrix_world.translation = point insert_obj.rotation_euler.rotate_axis( "Z", self.kitopssynth.intended_rotation) insert_obj.scale = self.scale if context.scene.kitopssynth.preview_mode and context.scene.kitopssynth.preview_type == "WIREFRAME": set_display_type(insert_obj.kitops.id, 'WIRE') insert.parent_objects(insert_obj, context.scene.kitopssynth_target_obj) cleanup(op, context) return insert_obj
def inserts_add_layer(prop, context, layer, new_insert_objs, cleanup=True): '''Main code for handling layout and distribution of INSERTs''' #Temporary set to regular mode if SMART mode is set to improve performance. kitops_preference = kitops_addon.preference() old_mode = kitops_preference.mode kitops_preference.mode = 'REGULAR' try: # see if there is an existing reference to INSERTS in this selection. If not, create a new one. target_obj = context.scene.kitopssynth_target_obj insert_entry_map = None # Is this the active layer? is_active_layer = context.scene.kitopssynth.layers[ context.scene.kitopssynth.layer_index].name == layer.name old_active = context.active_object layer_id = layer.name if layer_id not in target_obj.kitopssynth_layer_face_map: face_map_ref = target_obj.kitopssynth_layer_face_map.add() face_map_ref.name = layer_id face_ids = target_obj.kitopssynth_layer_face_map[layer_id].face_ids reset_selection = False if is_active_layer or not len(face_ids): # update the layer -> face selection mapping from the existing face selection face_id_list = property.generate_face_id_list(target_obj) face_ids.clear() for face_id in face_id_list: face_ids.add().face_id = face_id else: reset_selection = True # get the layer -> face selection mapping from the existing layer and set accordingly. old_face_selection_ids = [] obj = target_obj bm = bmesh.new() if obj.mode == 'EDIT': bm = bmesh.from_edit_mesh(obj.data) elif obj.mode == 'OBJECT': bm.from_mesh(obj.data) for f in bm.faces: if f.select: old_face_selection_ids.append(f.index) f.select_set(False) bm.faces.ensure_lookup_table() for face_id_entry in face_ids: face_id = face_id_entry.face_id bm.faces[face_id].select_set(True) if obj.mode == 'EDIT': bmesh.update_edit_mesh(obj.data) elif obj.mode == 'OBJECT': bm.to_mesh(obj.data) bm.free() face_id_list = property.generate_face_id_list(target_obj) if context.active_object: bpy.ops.ko.synth_clear_layer('INVOKE_DEFAULT', layer_uid=layer.name, delete_all=True) #if we have no face selections after this, just do nothing. if len(face_id_list): key = property.generate_insert_map_key(target_obj, face_id_list) # just create a new entry for target objects -> inserts. insert_entry_map = target_obj.kitopssynth_insert_map[ key] if key in target_obj.kitopssynth_insert_map else target_obj.kitopssynth_insert_map.add( ) insert_entry_map.name = key # intitialise points and cache them. distribution_class_name = layer.distribution distributor = getattr(distributors, distribution_class_name)() new_insert_objs_to_add = distributor.distribute( prop, context, layer) new_insert_objs.extend(new_insert_objs_to_add) layer_to_update = insert_entry_map.layers[ layer. name] if layer.name in insert_entry_map.layers else insert_entry_map.layers.add( ) layer_to_update.name = layer.name for insert_obj in new_insert_objs_to_add: if insert_obj is not None: layer_to_update.inserts.add().insert_obj = insert_obj # reset the selection for next time. context.view_layer.objects.active = old_active if reset_selection: obj = target_obj bm = bmesh.new() if obj.mode == 'EDIT': bm = bmesh.from_edit_mesh(obj.data) elif obj.mode == 'OBJECT': bm.from_mesh(obj.data) for f in bm.faces: f.select_set(False) bm.faces.ensure_lookup_table() for f_index in old_face_selection_ids: bm.faces[f_index].select_set(True) if obj.mode == 'EDIT': bmesh.update_edit_mesh(obj.data) elif obj.mode == 'OBJECT': bm.to_mesh(obj.data) bm.free() if cleanup: cleanup() finally: kitops_preference.mode = old_mode