def draw_scs_looks_panel(layout, scene, active_object, scs_root_object): """Creates 'SCS Looks' settings sub-panel. :param layout: Blender UI Layout to draw to :type layout: bpy.types.UILayout :param scene: Blender Scene :type scene: bpy.types.Scene :param active_object: active object :type active_object: bpy.types.Object :param scs_root_object: SCS Root Object :type scs_root_object: bpy.types.Object """ layout_column = layout.column(align=True) layout_box = layout_column.box() if scene.scs_props.scs_look_panel_expand: # HEADER (COLLAPSIBLE - OPENED) row = layout_box.row() row.prop(scene.scs_props, 'scs_look_panel_expand', text="SCS Looks:", icon='TRIA_DOWN', icon_only=True, emboss=False) row.prop(scene.scs_props, 'scs_look_panel_expand', text=" ", icon='NONE', icon_only=True, emboss=False) layout_box = layout_column.box() # body box if len(_object_utils.gather_scs_roots(bpy.context.selected_objects)) > 1 and active_object is not scs_root_object: col = layout_box.box().column(align=True) row = col.row() row.label("WARNING", icon="ERROR") row = col.row() row.label("Can not edit looks! Selection has multiple game objects.") else: # more roots or active object is root object row = layout_box.row() row.template_list( 'SCSObjectLookSlots', list_id="", dataptr=scs_root_object, propname="scs_object_look_inventory", active_dataptr=scs_root_object.scs_props, active_propname="active_scs_look", rows=3, maxrows=5, type='DEFAULT', columns=9 ) # LIST BUTTONS col = row.column(align=True) col.operator('object.add_scs_look', text="", icon='ZOOMIN') col.operator('object.remove_scs_look', text="", icon='ZOOMOUT') else: row = layout_box.row() row.prop(scene.scs_props, 'scs_look_panel_expand', text="SCS Looks:", icon='TRIA_RIGHT', icon_only=True, emboss=False) row.prop(scene.scs_props, 'scs_look_panel_expand', text=" ", icon='NONE', icon_only=True, emboss=False)
def draw_scs_looks_panel(layout, active_object, scs_root_object, without_box=False): """Creates 'SCS Looks' settings sub-panel. :param layout: Blender UI Layout to draw to :type layout: bpy.types.UILayout :param active_object: active object :type active_object: bpy.types.Object :param scs_root_object: SCS Root Object :type scs_root_object: bpy.types.Object :param without_box: draw without extra box layout? :type without_box: bool """ layout_column = layout.column(align=True) if without_box: layout_box = layout_column else: layout_box = layout_column.box() if len(_object_utils.gather_scs_roots(bpy.context.selected_objects) ) > 1 and active_object is not scs_root_object: warning_box = layout_box.column(align=True) header = warning_box.box() header.label(text="WARNING", icon='ERROR') body = warning_box.box() col = body.column(align=True) col.label(text="Can not edit looks!") col.label(text="Selection has multiple game objects.") else: # more roots or active object is root object row = layout_box.row() row.template_list(SCS_TOOLS_UL_ObjectLookSlots.__name__, list_id="", dataptr=scs_root_object, propname="scs_object_look_inventory", active_dataptr=scs_root_object.scs_props, active_propname="active_scs_look", rows=3, maxrows=5, type='DEFAULT', columns=9) # LIST BUTTONS col = row.column(align=True) col.operator('object.scs_tools_add_look', text="", icon='ADD') col.operator('object.scs_tools_remove_active_look', text="", icon='REMOVE')
def execute(self, context): lprint("I " + self.bl_label + "...") from io_scs_tools.internals.shader_presets import cache as _shader_presets_cache from io_scs_tools.utils import get_shader_presets_inventory as _get_shader_presets_inventory mat = context.material mat_scs_props = mat.scs_props """:type: io_scs_tools.properties.material.MaterialSCSTools""" preset = _get_shader_presets_inventory()[mat_scs_props.active_shader_preset_name] """:type: io_scs_tools.properties.world.ShaderPresetsInventoryItem""" # extract only flavor effect part of string flavor_effect_part = mat_scs_props.mat_effect_name[len(preset.effect):] new_flavor_state = not self.flavor_enabled flavors_suffix = "" for flavor in preset.flavors: flavor_variant_found = False for flavor_variant in flavor.variants: if flavor_variant.name == self.flavor_name: # add founded flavor to flavors suffix only if enabled if new_flavor_state: flavors_suffix += "." + flavor_variant.name flavor_variant_found = True break # if one variant of flavor is found skip all other variants if flavor_variant_found: continue # make sure to add all other enabled flavors to flavors suffix for flavor_variant in flavor.variants: is_in_middle = "." + flavor_variant.name + "." in flavor_effect_part is_on_end = flavor_effect_part.endswith("." + flavor_variant.name) if is_in_middle or is_on_end: flavors_suffix += "." + flavor_variant.name # finally set new shader data to material section = _shader_presets_cache.get_section(preset, flavors_suffix) context.material.scs_props.mat_effect_name = preset.effect + flavors_suffix _material_utils.set_shader_data_to_material(context.material, section) # sync shader types on all scs roots by updating looks on them # to avoid different shader types on different scs roots for same material for scs_root in _object_utils.gather_scs_roots(bpy.data.objects): _looks.update_look_from_material(scs_root, mat, True) return {'FINISHED'}
def get_objects_for_export(self): """Get objects for export, list filtered and extended depending on export scope. :return: list of objects to export calculated from selection :rtype: list[bpy.types.Object] """ # if cached, just return if self.cached_objects: return self.cached_objects objs_to_export = [] export_scope = _get_scs_globals().export_scope if export_scope == "selection": for root in _object_utils.gather_scs_roots( bpy.context.selected_objects): objs_to_export.append(root) children = _object_utils.get_children(root) children_unselected = [] children_selected = [] for child_obj in children: if child_obj.select_get(): children_selected.append(child_obj) elif child_obj.users_scene: # unlinked objects shouldn't be exported children_unselected.append(child_obj) # if any children was selected make sure, to export only them if len(children_selected) > 0: objs_to_export.extend(children_selected) else: objs_to_export.extend(children_unselected) elif export_scope == "scene": objs_to_export = tuple(bpy.context.scene.objects) elif export_scope == "scenes": scenes_objs = set() for scene in bpy.data.scenes: scenes_objs.update(scene.objects) objs_to_export = tuple(scenes_objs) # cache filtered list, to be able to retrive it quickly on second call self.cached_objects = objs_to_export return self.cached_objects
def post_load(scene): # get Blender Tools version from last blend file load last_load_bt_ver = _get_scs_globals().last_load_bt_version scs_roots = None """ Applies fixes for v0.6 or less: 1. fixes reflection textures tga's for tobjs as TOBJ load is now supported and unlock that textures 2. calls update on all set textures to correct paths for them 3. tries to fix active shader preset name for materials, because of new flavor system """ if _info_utils.cmp_ver_str(last_load_bt_ver, "0.6") <= 0: print("INFO\t- Applying fixes for version <= 0.6") for material in bpy.data.materials: # ignore materials not related to blender tools if material.scs_props.mat_effect_name == "": continue for tex_type in material.scs_props.get_texture_types().keys(): texture_attr_str = "shader_texture_" + tex_type if texture_attr_str in material.scs_props.keys(): # 1. fix reflection textures if tex_type == "reflection": is_building_ref = material.scs_props[texture_attr_str].endswith("/bulding_ref.tga") is_generic_s = material.scs_props[texture_attr_str].endswith("material/environment/generic_s.tga") is_glass_interior = material.scs_props.active_shader_preset_name == "glass - interior" is_dif_spec_weight_add_env = material.scs_props.active_shader_preset_name == "dif.spec.weight.add.env" is_truckpaint = material.scs_props.active_shader_preset_name.startswith("truckpaint") # fix paths if is_building_ref: material.scs_props[texture_attr_str] = material.scs_props[texture_attr_str][:-4] material.scs_props[texture_attr_str + "_locked"] = False elif is_generic_s: if is_glass_interior: material.scs_props[texture_attr_str] = "//material/environment/interior_reflection" elif is_dif_spec_weight_add_env: material.scs_props[texture_attr_str] = "//material/environment/generic_reflection" else: material.scs_props[texture_attr_str] = "//material/environment/vehicle_reflection" # unlock reflection textures everywhere except on truckpaint shader if not is_truckpaint: material.scs_props[texture_attr_str + "_locked"] = False # acquire roots on demand only once scs_roots = _object_utils.gather_scs_roots(bpy.data.objects) if not scs_roots else scs_roots # propagate reflection texture change on all of the looks. # NOTE: We can afford write through because old BT had all reflection textures locked # meaning user had to use same texture on all looks # NOTE#2: Printouts like: # "Look with ID: X doesn't have entry for material 'X' in SCS Root 'X', # property 'shader_texture_reflection' won't be updated!" # are expected here, because we don't use any safety check, # if material is used on the mesh objects inside scs root for scs_root in scs_roots: _looks.write_through(scs_root, material, texture_attr_str) # 2. trigger update function for path reload and reload of possible missing textures update_func = getattr(material.scs_props, "update_" + texture_attr_str, None) if update_func: update_func(material) # ignore already properly set materials if material.scs_props.active_shader_preset_name in _get_shader_presets_inventory(): continue # 3. try to recover "active_shader_preset_name" from none flavor times Blender Tools material_textures = {} if "scs_shader_attributes" in material and "textures" in material["scs_shader_attributes"]: for texture in material["scs_shader_attributes"]["textures"].values(): tex_id = texture["Tag"].split(":")[1] tex_value = texture["Value"] material_textures[tex_id] = tex_value (preset_name, preset_section) = _material_utils.find_preset(material.scs_props.mat_effect_name, material_textures) if preset_name: material.scs_props.active_shader_preset_name = preset_name # acquire roots on demand only once scs_roots = _object_utils.gather_scs_roots(bpy.data.objects) if not scs_roots else scs_roots # make sure to fix active preset shader name in all looks # NOTE: Printouts like: # "Look with ID: X doesn't have entry for material 'X' in SCS Root 'X', # property 'active_shader_preset_name' won't be updated!" # are expected here, because we don't use any safety check, # if material is used on the mesh objects inside scs root for scs_root in scs_roots: _looks.write_through(scs_root, material, "active_shader_preset_name") # as last update "last load" Blender Tools version to current _get_scs_globals().last_load_bt_version = get_tools_version()
def execute(self, context): material = context.active_object.active_material if not material or not hasattr(material.scs_props, self.property_str): return {'CANCELLED'} scs_roots = [] active_scs_root = _object_utils.get_scs_root(context.active_object) if active_scs_root: scs_roots.append(active_scs_root) if self.is_ctrl: scs_roots = _object_utils.gather_scs_roots(bpy.data.objects) if self.is_shift or not self.is_ctrl: # WT either on active only or all SCS roots; (Shift + Ctrl) or none altered_looks = 0 for scs_root in scs_roots: altered_looks += _looks.write_through(scs_root, material, self.property_str) if altered_looks > 0: message = "Write through successfully altered %s looks on %s SCS Root Objects!" % (altered_looks, len(scs_roots)) else: message = "Nothing to write through." self.report({'INFO'}, message) elif self.is_ctrl: # special WT only into the same look of other SCS Roots # get current look id look_i = active_scs_root.scs_props.active_scs_look look_name = active_scs_root.scs_object_look_inventory[look_i].name if look_i >= 0 else None if look_name is None: self.report({'WARNING'}, "Aborting as current object is not in any SCS Game Object, parent it to SCS Root first!") return {'CANCELLED'} altered_looks = 0 for scs_root in scs_roots: # ignore active root if scs_root == active_scs_root: continue look_id = -1 # search for same look by name on other scs root for look in scs_root.scs_object_look_inventory: if look.name == look_name: look_id = look.id break if _looks.write_prop_to_look(scs_root, look_id, material, self.property_str): altered_looks += 1 if len(scs_roots) - 1 != altered_looks: self.report({'WARNING'}, "WT partially done, same look was found on %s/%s other SCS Root Objects!" % (altered_looks, len(scs_roots) - 1)) else: self.report({'INFO'}, "Write through altered property on %s other SCS Root Objects!" % altered_looks) return {'FINISHED'}