From 0bf58270d1f2bb919c50faac21d2701fc3c42857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 13 Jun 2022 00:45:46 +0200 Subject: [PATCH 01/15] Support for 'tsnmapcalc' Flavor Small modification that adds support for 'tsnmapcalc' flavor mostly used in road templates models, where road texture use normal map. --- addon/io_scs_tools/properties/material.py | 60 ++++++++++++++++++++++- addon/io_scs_tools/shader_presets.txt | 27 +++++++++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/addon/io_scs_tools/properties/material.py b/addon/io_scs_tools/properties/material.py index b37db79..4fed34c 100644 --- a/addon/io_scs_tools/properties/material.py +++ b/addon/io_scs_tools/properties/material.py @@ -273,7 +273,8 @@ def get_texture_types(): """ return {'base', 'reflection', 'over', 'oclu', 'mask', 'mult', 'iamod', 'lightmap', 'paintjob', 'flakenoise', 'nmap', 'base_1', 'mult_1', 'detail', 'nmap_detail', 'layer0', 'layer1', - 'sky_weather_base_a', 'sky_weather_base_b', 'sky_weather_over_a', 'sky_weather_over_b'} + 'sky_weather_base_a', 'sky_weather_base_b', 'sky_weather_over_a', 'sky_weather_over_b', + 'nmap_over'} def get_id(self): """Gets unique ID for material within current Blend file. If ID does not exists yet it's calculated. @@ -420,6 +421,12 @@ def update_shader_texture_nmap_detail(self, context): def update_shader_texture_nmap_detail_settings(self, context): __update_shader_texture_tobj_file__(self, context, "nmap_detail") + def update_shader_texture_nmap_over(self, context): + __update_shader_texture__(self, context, "nmap_over") + + def update_shader_texture_nmap_over_settings(self, context): + __update_shader_texture_tobj_file__(self, context, "nmap_over") + def update_shader_texture_oclu(self, context): __update_shader_texture__(self, context, "oclu") @@ -1380,6 +1387,57 @@ def update_shader_texture_sky_weather_over_b_settings(self, context): options={'HIDDEN'}, ) + # TEXTURE: NMAP_OVER + shader_texture_nmap_over: StringProperty( + name="Texture NMap Over", + description="Texture Nmap Over for active Material", + default=_MAT_consts.unset_bitmap_filepath, + options={'HIDDEN'}, + subtype='NONE', + update=update_shader_texture_nmap_over, + ) + shader_texture_nmap_over_imported_tobj: StringProperty( + name="Imported TOBJ Path", + description="Use imported TOBJ path reference which will be exported into material (NOTE: export will not take care of any TOBJ files!)", + default="", + update=__update_look__ + ) + shader_texture_nmap_over_locked: BoolProperty( + name="Texture Locked", + description="Tells if texture is locked and should not be changed by user(intended for internal usage only)", + default=False + ) + shader_texture_nmap_over_map_type: StringProperty( + name="Texture Map Type", + description="Stores texture mapping type and should not be changed by user(intended for internal usage only)", + default="2d" + ) + shader_texture_nmap_over_settings: EnumProperty( + name="Settings", + description="TOBJ settings for this texture", + items=__get_texture_settings__(), + default=set(), + options={'ENUM_FLAG'}, + update=update_shader_texture_nmap_over_settings + ) + shader_texture_nmap_over_tobj_load_time: StringProperty( + name="Last TOBJ load time", + description="Time string of last loading", + default="", + ) + shader_texture_nmap_over_use_imported: BoolProperty( + name="Use Imported", + description="Use custom provided path for TOBJ reference", + default=False, + update=__update_look__ + ) + shader_texture_nmap_over_uv: CollectionProperty( + name="Texture Nmap Over UV Sets", + description="Texture Nmap Over UV sets for active Material", + type=UVMappingItem, + options={'HIDDEN'}, + ) + # TEXTURE: OCCLUSION shader_texture_oclu: StringProperty( name="Texture Oclu", diff --git a/addon/io_scs_tools/shader_presets.txt b/addon/io_scs_tools/shader_presets.txt index e50e68b..40c9445 100644 --- a/addon/io_scs_tools/shader_presets.txt +++ b/addon/io_scs_tools/shader_presets.txt @@ -904,7 +904,7 @@ Shader { Shader { PresetName: "dif.spec.weight" Effect: "eut2.dif.spec.weight" - Flavors: ( "NMAP_TS|NMAP_TS_UV|NMAP_TS_16|NMAP_TS_UV_16" "SHADOW" "PAINT" "TEXGEN0" "ASAFEW" "ALPHA" "DEPTH" "BLEND_OVER|BLEND_MULT|BLEND_ADD" ) + Flavors: ( "NMAP_TS|NMAP_TS_UV|NMAP_TS_16|NMAP_TS_UV_16|NMAP_TS_CALC" "SHADOW" "PAINT" "TEXGEN0" "ASAFEW" "ALPHA" "DEPTH" "BLEND_OVER|BLEND_MULT|BLEND_ADD" ) Flags: 0 Attribute { Format: FLOAT3 @@ -1106,7 +1106,7 @@ Shader { Shader { PresetName: "dif.spec.weight.weight.dif.spec.weight" Effect: "eut2.dif.spec.weight.weight.dif.spec.weight" - Flavors: ( "SHADOW" "TEXGEN0" "TEXGEN1" "ALPHA" ) + Flavors: ( "NMAP_TS_CALC_OVER" "SHADOW" "TEXGEN0" "TEXGEN1" "ALPHA" ) Flags: 0 Attribute { Format: FLOAT3 @@ -2002,6 +2002,29 @@ Flavor { TexCoord: ( 6 ) } } +Flavor { + Type: "NMAP_TS_CALC" + Name: "tsnmapcalc" + Texture { + Tag: "texture[X]:texture_nmap" + Value: "" + TexCoord: ( 0 ) + } +} +Flavor { + Type: "NMAP_TS_CALC_OVER" + Name: "tsnmapcalc" + Texture { + Tag: "texture[X]:texture_nmap" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_nmap_over" + Value: "" + TexCoord: ( 1 ) + } +} Flavor { Type: "NOCULL" Name: "nocull" From aeeecf8f3fadef27aef08bda0d4cb4452adcf015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 13 Jun 2022 02:01:22 +0200 Subject: [PATCH 02/15] Support for 'tsnmapcalc' Flavor Fast fix that add tsnmapcalc to Shader Editor --- addon/io_scs_tools/internals/shaders/shader.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addon/io_scs_tools/internals/shaders/shader.py b/addon/io_scs_tools/internals/shaders/shader.py index 9e1c713..2c69859 100644 --- a/addon/io_scs_tools/internals/shaders/shader.py +++ b/addon/io_scs_tools/internals/shaders/shader.py @@ -71,6 +71,9 @@ def setup_nodes(material, effect, attr_dict, tex_dict, tex_settings_dict, recrea if effect.endswith(".tsnmap16") or ".tsnmap16." in effect: flavors["nmap"] = True + if effect.endswith(".tsnmapcalc") or ".tsnmapcalc." in effect: + flavors["nmap"] = True + if effect.endswith(".indenv") or ".indenv." in effect: flavors["indenv"] = True From 7b0780282768bab5658a9fcc12c2bef92643b37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Sun, 22 Sep 2024 21:08:22 +0200 Subject: [PATCH 03/15] amod support, aliasing nmap, aux fix * Added support for "dif.spec.amod.dif.spec" shader. It's not perfect, but it should be enough to work with models. (Col_alpha: 0.25 = full Base, 0.0/0.5 = Full Over. Idk why it's divided that way.) * Added condition to allow aliasing materials with "tsnmap" flavor, like it is made in "/material/terrain/" dir. * Fixed aux[0] and aux[1] (changed from float2 to float4 - texgen_X_rot and unused/nmap rot? idk) --- .gitignore | 1 + .../internals/shaders/eut2/__init__.py | 4 + .../eut2/dif_spec_amod_dif_spec/__init__.py | 225 ++++++++++++++++++ addon/io_scs_tools/properties/material.py | 15 ++ addon/io_scs_tools/shader_presets.txt | 70 +++++- addon/io_scs_tools/supported_effects.bin | Bin 221908 -> 190106 bytes addon/io_scs_tools/ui/material.py | 3 + 7 files changed, 311 insertions(+), 7 deletions(-) create mode 100644 addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py diff --git a/.gitignore b/.gitignore index c668405..1779ade 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ var/ *.egg-info/ .installed.cfg *.egg +.vs/ # PyInstaller # Usually these files are written by a python script from a template diff --git a/addon/io_scs_tools/internals/shaders/eut2/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/__init__.py index 973e499..d883946 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/__init__.py @@ -131,6 +131,10 @@ def get_shader(effect): elif effect.startswith("dif.spec.over.dif.opac"): from io_scs_tools.internals.shaders.eut2.dif_spec_over_dif_opac import DifSpecOverDifOpac as Shader + + elif effect.startswith("dif.spec.amod.dif.spec"): + + from io_scs_tools.internals.shaders.eut2.dif_spec_amod_dif_spec import DifSpecAmodDifSpec as Shader elif effect.startswith("dif.spec.mult.dif.spec.iamod.dif.spec"): diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py new file mode 100644 index 0000000..0fe1d09 --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py @@ -0,0 +1,225 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2015-2019: SCS Software + +from io_scs_tools.consts import Mesh as _MESH_consts +from io_scs_tools.internals.shaders.eut2.dif_spec import DifSpec +from io_scs_tools.utils import material as _material_utils + +class DifSpecAmodDifSpec(DifSpec): + SEC_UVMAP_NODE = "SecondUVMap" + VCOLOR_SCALE_NODE = "VertexColorScale" + VCOLOR_SUBTRACT_NODE = "VertexColorSubtract" + VCOLOR_ABS_NODE = "VertexColorAbsolute" + VCOLOR_INVERT_NODE = "VertexColorInvert" + MASK_TEX_NODE = "MaskTex" + OVER_TEX_NODE = "OverTex" + MASK_COLOR_INVERT_NODE = "MaskColorInvert" + MASK_VCOLOR_MIX_NODE = "MaskVertexColorMix" + MASK_COLOR_MIX_NODE = "MaskColorMix" + + @staticmethod + def get_name(): + """Get name of this shader file with full modules path.""" + return __name__ + + @staticmethod + def init(node_tree): + """Initialize node tree with links for this shader. + + :param node_tree: node tree on which this shader should be created + :type node_tree: bpy.types.NodeTree + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + # init parent + DifSpec.init(node_tree, disable_remap_alpha=False) + + base_tex_n = node_tree.nodes[DifSpec.BASE_TEX_NODE] + vcol_multi_n = node_tree.nodes[DifSpec.VCOLOR_MULT_NODE] + vcol_group_n = node_tree.nodes[DifSpec.VCOL_GROUP_NODE] + + # node creation + # - column 0 - + sec_uvmap_n = node_tree.nodes.new("ShaderNodeUVMap") + sec_uvmap_n.name = DifSpecAmodDifSpec.SEC_UVMAP_NODE + sec_uvmap_n.label = DifSpecAmodDifSpec.SEC_UVMAP_NODE + sec_uvmap_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1000) + sec_uvmap_n.uv_map = _MESH_consts.none_uv + + # - column 2 - + vcol_scale_n = node_tree.nodes.new("ShaderNodeVectorMath") + vcol_scale_n.name = DifSpecAmodDifSpec.VCOLOR_SCALE_NODE + vcol_scale_n.label = DifSpecAmodDifSpec.VCOLOR_SCALE_NODE + vcol_scale_n.location = (start_pos_x + pos_x_shift, start_pos_y + 1200) + vcol_scale_n.operation = "MULTIPLY" + vcol_scale_n.inputs[1].default_value = (2,) * 3 + + mask_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + mask_tex_n.name = DifSpecAmodDifSpec.MASK_TEX_NODE + mask_tex_n.label = DifSpecAmodDifSpec.MASK_TEX_NODE + mask_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 1000) + mask_tex_n.width = 140 + + over_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + over_tex_n.name = DifSpecAmodDifSpec.OVER_TEX_NODE + over_tex_n.label = DifSpecAmodDifSpec.OVER_TEX_NODE + over_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 700) + over_tex_n.width = 140 + + # - column 3 - + vcol_subtract_n = node_tree.nodes.new("ShaderNodeVectorMath") + vcol_subtract_n.name = DifSpecAmodDifSpec.VCOLOR_SUBTRACT_NODE + vcol_subtract_n.label = DifSpecAmodDifSpec.VCOLOR_SUBTRACT_NODE + vcol_subtract_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1200) + vcol_subtract_n.operation = "SUBTRACT" + vcol_subtract_n.inputs[1].default_value = (1,) * 3 + + mask_invert_n = node_tree.nodes.new("ShaderNodeInvert") + mask_invert_n.name = DifSpecAmodDifSpec.MASK_COLOR_INVERT_NODE + mask_invert_n.label = DifSpecAmodDifSpec.MASK_COLOR_INVERT_NODE + mask_invert_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1000) + mask_invert_n.inputs[0].default_value = 1 + + # - column 4 - + vcol_abs_n = node_tree.nodes.new("ShaderNodeVectorMath") + vcol_abs_n.name = DifSpecAmodDifSpec.VCOLOR_ABS_NODE + vcol_abs_n.label = DifSpecAmodDifSpec.VCOLOR_ABS_NODE + vcol_abs_n.location = (start_pos_x + pos_x_shift * 3, start_pos_y + 1100) + vcol_abs_n.operation = "ABSOLUTE" + + # - column 5 - + vcol_invert_n = node_tree.nodes.new("ShaderNodeInvert") + vcol_invert_n.name = DifSpecAmodDifSpec.VCOLOR_INVERT_NODE + vcol_invert_n.label = DifSpecAmodDifSpec.VCOLOR_INVERT_NODE + vcol_invert_n.location = (start_pos_x + pos_x_shift * 4, start_pos_y + 1100) + vcol_invert_n.inputs[0].default_value = 1 + + # - column 6 - + mask_vcol_mix_n = node_tree.nodes.new("ShaderNodeMixRGB") + mask_vcol_mix_n.name = DifSpecAmodDifSpec.MASK_VCOLOR_MIX_NODE + mask_vcol_mix_n.label = DifSpecAmodDifSpec.MASK_VCOLOR_MIX_NODE + mask_vcol_mix_n.location = (start_pos_x + pos_x_shift * 5, start_pos_y + 1100) + mask_vcol_mix_n.blend_type = "MIX" + mask_vcol_mix_n.inputs['Color2'].default_value = (1,) * 4 + + # - column 7 - + mask_color_mix_n = node_tree.nodes.new("ShaderNodeMixRGB") + mask_color_mix_n.name = DifSpecAmodDifSpec.MASK_COLOR_MIX_NODE + mask_color_mix_n.label = DifSpecAmodDifSpec.MASK_COLOR_MIX_NODE + mask_color_mix_n.location = (start_pos_x + pos_x_shift * 6, start_pos_y + 1050) + mask_color_mix_n.blend_type = "MIX" + + + + # links creation + # - Column 0 - + node_tree.links.new(vcol_group_n.outputs[1], vcol_scale_n.inputs[0]) + node_tree.links.new(sec_uvmap_n.outputs['UV'], mask_tex_n.inputs['Vector']) + node_tree.links.new(sec_uvmap_n.outputs['UV'], over_tex_n.inputs['Vector']) + + # - Column 2 - + node_tree.links.new(base_tex_n.outputs['Color'], mask_color_mix_n.inputs['Color2']) + node_tree.links.new(vcol_scale_n.outputs['Vector'], vcol_subtract_n.inputs[0]) + node_tree.links.new(mask_tex_n.outputs['Color'], mask_invert_n.inputs['Color']) + node_tree.links.new(over_tex_n.outputs['Color'], mask_color_mix_n.inputs['Color1']) + + # - Column 3 - + node_tree.links.new(vcol_subtract_n.outputs['Vector'], vcol_abs_n.inputs[0]) + node_tree.links.new(mask_invert_n.outputs['Color'], mask_vcol_mix_n.inputs['Color1']) + + # - Column 4 - + node_tree.links.new(vcol_abs_n.outputs['Vector'], vcol_invert_n.inputs['Color']) + + # - Column 5 - + node_tree.links.new(vcol_invert_n.outputs['Color'], mask_vcol_mix_n.inputs['Fac']) + + # - Column 6 - + node_tree.links.new(mask_vcol_mix_n.outputs['Color'], mask_color_mix_n.inputs['Fac']) + + # - Column 7 - + node_tree.links.new(mask_color_mix_n.outputs['Color'], vcol_multi_n.inputs[1]) + + + @staticmethod + def set_over_uv(node_tree, uv_layer): + """Set UV layer to overlying texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for over texture + :type uv_layer: str + """ + + if uv_layer is None or uv_layer == "": + uv_layer = _MESH_consts.none_uv + + node_tree.nodes[DifSpecAmodDifSpec.SEC_UVMAP_NODE].uv_map = uv_layer + + @staticmethod + def set_mask_texture(node_tree, image): + """Set mask texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assigned to over texture node + :type image: bpy.types.Texture + """ + + node_tree.nodes[DifSpecAmodDifSpec.MASK_TEX_NODE].image = image + + @staticmethod + def set_mask_texture_settings(node_tree, settings): + """Set mask texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + # Commented because of texture linear colorspace problems in render + # _material_utils.set_texture_settings_to_node(node_tree.nodes[DifSpecAmodDifSpec.MASK_TEX_NODE], settings) + + @staticmethod + def set_over_texture(node_tree, image): + """Set over texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assigned to mult texture node + :type image: bpy.types.Texture + """ + + node_tree.nodes[DifSpecAmodDifSpec.OVER_TEX_NODE].image = image + + @staticmethod + def set_over_texture_settings(node_tree, settings): + """Set mask texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + _material_utils.set_texture_settings_to_node(node_tree.nodes[DifSpecAmodDifSpec.OVER_TEX_NODE], settings) + \ No newline at end of file diff --git a/addon/io_scs_tools/properties/material.py b/addon/io_scs_tools/properties/material.py index 4fed34c..1a361a3 100644 --- a/addon/io_scs_tools/properties/material.py +++ b/addon/io_scs_tools/properties/material.py @@ -342,6 +342,9 @@ def update_shader_attribute_tint(self, context): def update_shader_attribute_tint_opacity(self, context): __update_shader_attribute__(self, context, "tint_opacity") + + def update_shader_attribute_amod_decal_blending_factors(self, context): + __update_shader_attribute__(self, context, "amod_decal_blending_factors") def update_shader_texture_base(self, context): __update_shader_texture__(self, context, "base") @@ -712,6 +715,18 @@ def update_shader_texture_sky_weather_over_b_settings(self, context): options={'HIDDEN'}, update=update_shader_attribute_tint_opacity ) + + shader_attribute_amod_decal_blending_factors: FloatVectorProperty( + name="Amod Decal Blending Factors", + description="SCS shader 'Amod Blending' value", + default=(1.0, 1.0), + min=0, max=1, + step=1, precision=2, + options={'HIDDEN'}, + subtype='NONE', + size=2, + update=update_shader_attribute_amod_decal_blending_factors, + ) shader_attribute_queue_bias: IntProperty( name="Queue Bias", diff --git a/addon/io_scs_tools/shader_presets.txt b/addon/io_scs_tools/shader_presets.txt index 40c9445..00ad8fc 100644 --- a/addon/io_scs_tools/shader_presets.txt +++ b/addon/io_scs_tools/shader_presets.txt @@ -858,7 +858,7 @@ Shader { Shader { PresetName: "dif.spec.over.dif.opac" Effect: "eut2.dif.spec.over.dif.opac" - Flavors: ( "SHADOW" "PAINT" "TEXGEN0" "TEXGEN1" "ALPHA" "DEPTH" "BLEND_OVER|BLEND_ADD" ) + Flavors: ( "SHADOW" "PAINT" "TEXGEN0" "TEXGEN1" "ALPHA" "DEPTH" "BLEND_OVER|BLEND_ADD|ENVMAP" ) Flags: 0 Attribute { Format: FLOAT3 @@ -1776,6 +1776,58 @@ Shader { TexCoord: ( 1 ) } } +Shader { + PresetName: "dif.spec.amod.dif.spec" + Effect: "eut2.dif.spec.amod.dif.spec" + Flavors: ( "NMAP_TS|NMAP_TS_UV|NMAP_TS_16|NMAP_TS_UV_16" "SHADOW" "ASAFEWA" ) + Flags: 0 + Attribute { + Format: FLOAT3 + Tag: "diffuse" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT3 + Tag: "specular" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "amod_decal_blending_factors" + Value: ( 1.0 1.0 ) + Hide: "True" + } + Attribute { + Format: FLOAT + Tag: "shininess" + Value: ( 20.0 ) + } + Attribute { + Format: FLOAT + Tag: "add_ambient" + Value: ( 0.0 ) + } + Attribute { + Format: FLOAT + Tag: "reflection" + Value: ( 1.0 ) + } + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_mask" + Value: "" + TexCoord: ( 1 ) + } + Texture { + Tag: "texture[X]:texture_over" + Value: "" + TexCoord: ( 1 ) + } +} Flavor { Type: "AIRBRUSH" Name: "airbrush" @@ -1803,6 +1855,10 @@ Flavor { Type: "ASAFEW" Name: "asafew" } +Flavor { + Type: "ASAFEWA" + Name: "asafew.a" +} Flavor { Type: "AWHITE" Name: "awhite" @@ -2098,19 +2154,19 @@ Flavor { Type: "TEXGEN0" Name: "tg0" Attribute { - Format: FLOAT2 + Format: FLOAT4 Tag: "aux[0]" - FriendlyTag: "TexGen0 Scale (X,Z)" - Value: ( 10.0 10.0 ) + FriendlyTag: "TexGen0 Scale (X,Z,ROT_BASE,ROT_NMAP)" + Value: ( 10.0 10.0 0.0 0.0 ) } } Flavor { Type: "TEXGEN1" Name: "tg1" Attribute { - Format: FLOAT2 + Format: FLOAT4 Tag: "aux[1]" - FriendlyTag: "TexGen1 Scale (X,Z)" - Value: ( 8.0 8.0 ) + FriendlyTag: "TexGen1 Scale (X,Z,ROT_BASE,ROT_NMAP)" + Value: ( 8.0 8.0 0.0 0.0 ) } } diff --git a/addon/io_scs_tools/supported_effects.bin b/addon/io_scs_tools/supported_effects.bin index 2f3338b873814391f5710ed61e350a2e9b94d66f..50a04993855fe1007ce092ad987226e83de3cd07 100644 GIT binary patch literal 190106 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 i1<8pO4xijFRVwDD$??`Ayz~%xTlvpz Date: Mon, 23 Sep 2024 15:19:18 +0200 Subject: [PATCH 04/15] Support for custom company locators Added support for custom unloading/loading locators in "Spawn Point" -> "Custom" setting. Custom (un)loading settings allow you, to set parking difficulty, max trailer lenght and trailer type like "Company" tool in ME. --- addon/io_scs_tools/consts.py | 40 ++++++++++++++++ addon/io_scs_tools/exp/pip/exporter.py | 2 + addon/io_scs_tools/exp/pip/spawn_point.py | 21 ++++++++ addon/io_scs_tools/imp/pip.py | 20 ++++++-- addon/io_scs_tools/properties/object.py | 58 ++++++++++++++++++++++- addon/io_scs_tools/ui/object.py | 13 +++++ 6 files changed, 149 insertions(+), 5 deletions(-) diff --git a/addon/io_scs_tools/consts.py b/addon/io_scs_tools/consts.py index 0ee4826..cb732e8 100644 --- a/addon/io_scs_tools/consts.py +++ b/addon/io_scs_tools/consts.py @@ -444,6 +444,46 @@ class PIF: TYPE_END = 0x00020000 TYPE_CROSS_SHARP = 0x00040000 + class PSPCF: + """Constants represetning spawn point custom flags. + """ + # Difficulties + RAIL_MASK = 0x0000000F + RAIL_NONE = 0x00000000 + RAIL_EASY = 0x00000001 + RAIL_MEDIUM = 0x00000002 + RAIL_HARD = 0x00000003 + RAIL_RIGID = 0x00000004 # ?? idk + RAIL_LOAD = 0x00000005 + + # Lenght + LENGHT_MASK = 0x000000F0 + LENGHT_14 = 0x00000000 + LENGHT_15 = 0x00000010 + LENGHT_16 = 0x00000020 + LENGHT_17 = 0x00000030 + LENGHT_18 = 0x00000040 + LENGHT_19 = 0x00000050 + LENGHT_20 = 0x00000060 + LENGHT_21 = 0x00000070 + LENGHT_22 = 0x00000080 + LENGHT_23 = 0x00000090 + LENGHT_24 = 0x000000A0 + LENGHT_25 = 0x000000B0 + LENGHT_26 = 0x000000C0 + LENGHT_27 = 0x000000D0 + LENGHT_28 = 0x000000E0 + UNLIMITED = 0x000000F0 + + # Rule + TRAILER_MASK = 0x000F0000 + TRAILER_ANY = 0x00000000 + TRAILER_BOX = 0x00010000 + TRAILER_TANK = 0x00020000 + TRAILER_DUMP_BULK = 0x00030000 + TRAILER_PLATFORM_LOG_CONT = 0x00040000 + TRAILER_LIVESTOCK = 0x00050000 + TRAILER_LOG = 0x00060000 class Bones: init_scale_key = "scs_init_scale" diff --git a/addon/io_scs_tools/exp/pip/exporter.py b/addon/io_scs_tools/exp/pip/exporter.py index 8f5a785..e03ac9e 100644 --- a/addon/io_scs_tools/exp/pip/exporter.py +++ b/addon/io_scs_tools/exp/pip/exporter.py @@ -327,6 +327,8 @@ def execute(dirpath, filename, name_suffix, prefab_locator_list, offset_matrix, spawn_point.set_type(int(locator_scs_props.locator_prefab_spawn_type)) + spawn_point.set_flags(locator_scs_props) + pip_spawn_points.append(spawn_point) # semaphores creation diff --git a/addon/io_scs_tools/exp/pip/spawn_point.py b/addon/io_scs_tools/exp/pip/spawn_point.py index 095a675..b30cd81 100644 --- a/addon/io_scs_tools/exp/pip/spawn_point.py +++ b/addon/io_scs_tools/exp/pip/spawn_point.py @@ -44,6 +44,7 @@ def __init__(self, name): self.__position = (0.,) * 3 self.__rotation = (1.,) + (0.,) * 3 self.__type = 0 # NONE + self.__flags = 0 # NONE SpawnPoint.__global_spawn_point_counter += 1 @@ -74,6 +75,25 @@ def set_type(self, sp_type): """ self.__type = sp_type + def set_flags(self, sp_flags): + """Set flags of spawn point. + + NOTE: there is no safety check if value is valid, + make sure that prefab locator properties are synced with PSPCF_* consts. + + :param sp_flags: integer flags of spawn point + :type sp_flags: int + """ + + # parking difficulty + self.__flags |= int(sp_flags.locator_prefab_custom_parking_difficulty) + + # lenght + self.__flags |= int(sp_flags.locator_prefab_custom_lenght) + + # rule + self.__flags |= int(sp_flags.locator_prefab_custom_rule) + def get_as_section(self): """Get spawn point information represented with SectionData structure class. @@ -86,5 +106,6 @@ def get_as_section(self): section.props.append(("Position", ["&&", tuple(self.__position)])) section.props.append(("Rotation", ["&&", tuple(self.__rotation)])) section.props.append(("Type", self.__type)) + section.props.append(("Flags", self.__flags)) return section diff --git a/addon/io_scs_tools/imp/pip.py b/addon/io_scs_tools/imp/pip.py index 6da37c3..9efe5b0 100644 --- a/addon/io_scs_tools/imp/pip.py +++ b/addon/io_scs_tools/imp/pip.py @@ -207,7 +207,7 @@ def _get_sign_properties(section): def _get_spawn_properties(section): """Receives a Spawn section and returns its properties in its own variables. For any item that fails to be found, it returns None.""" - spawn_name = spawn_position = spawn_rotation = spawn_type = None + spawn_name = spawn_position = spawn_rotation = spawn_type = spawn_flags = None for prop in section.props: if prop[0] in ("", "#"): pass @@ -219,9 +219,11 @@ def _get_spawn_properties(section): spawn_rotation = prop[1] elif prop[0] == "Type": spawn_type = prop[1] + elif prop[0] == "Flags": + spawn_flags = prop[1] else: lprint('\nW Unknown property in "Spawn" data: "%s"!', prop[0]) - return spawn_name, spawn_position, spawn_rotation, spawn_type + return spawn_name, spawn_position, spawn_rotation, spawn_type, spawn_flags def _get_t_light_properties(section): @@ -450,12 +452,19 @@ def _create_spawn_locator( spawn_name, spawn_position, spawn_rotation, - spawn_type + spawn_type, + spawn_flags ): locator = _object_utils.create_locator_empty(spawn_name, spawn_position, spawn_rotation, (1, 1, 1), 0.1, 'Prefab') if locator: locator.scs_props.locator_prefab_type = 'Spawn Point' locator.scs_props.locator_prefab_spawn_type = str(spawn_type) + + # flags + locator.scs_props.locator_prefab_custom_parking_difficulty = str(spawn_flags & _PL_consts.PSPCF.RAIL_MASK) + locator.scs_props.locator_prefab_custom_lenght = str(spawn_flags & _PL_consts.PSPCF.LENGHT_MASK) + locator.scs_props.locator_prefab_custom_rule = str(spawn_flags & _PL_consts.PSPCF.TRAILER_MASK) + return locator @@ -732,7 +741,8 @@ def load(filepath, terrain_points_trans): (spawn_name, spawn_position, spawn_rotation, - spawn_type) = _get_spawn_properties(section) + spawn_type, + spawn_flags) = _get_spawn_properties(section) if spawn_name is None: spawn_name = str('Sign_Locator_' + str(spawn_index)) @@ -744,6 +754,7 @@ def load(filepath, terrain_points_trans): spawn_position, spawn_rotation, spawn_type, + spawn_flags, ) spawn_index += 1 elif section.type == 'Semaphore': # former "TrafficLight" @@ -915,6 +926,7 @@ def load(filepath, terrain_points_trans): spawn_points_data[name][1], spawn_points_data[name][2], spawn_points_data[name][3], + spawn_points_data[name][4], # sp_flags ) if loc: _print_locator_result(loc, "Spawn Point", name) diff --git a/addon/io_scs_tools/properties/object.py b/addon/io_scs_tools/properties/object.py index 606c9d3..68a394c 100644 --- a/addon/io_scs_tools/properties/object.py +++ b/addon/io_scs_tools/properties/object.py @@ -850,7 +850,7 @@ def locator_prefab_type_update(self, context): (_PL_consts.PSP.CAMERA_POINT, (str(_PL_consts.PSP.CAMERA_POINT), "Camera Point", "")), (_PL_consts.PSP.COMPANY_POS, (str(_PL_consts.PSP.COMPANY_POS), "Company Point", "")), (_PL_consts.PSP.COMPANY_UNLOAD_POS, (str(_PL_consts.PSP.COMPANY_UNLOAD_POS), "Company Unload Point", "")), - # (_PL_consts.PSP.CUSTOM, (str(_PL_consts.PSP.CUSTOM), "Custom", "")), + (_PL_consts.PSP.CUSTOM, (str(_PL_consts.PSP.CUSTOM), "Custom", "")), (_PL_consts.PSP.GARAGE_POS, (str(_PL_consts.PSP.GARAGE_POS), "Garage Point", "")), (_PL_consts.PSP.GAS_POS, (str(_PL_consts.PSP.GAS_POS), "Gas Station", "")), # (_PL_consts.PSP.HOTEL, (str(_PL_consts.PSP.HOTEL), "Hotel", "")), @@ -878,6 +878,62 @@ def locator_prefab_type_update(self, context): items=enum_spawn_type_items.values(), default=str(_PL_consts.PSP.NONE), ) + enum_custom_parking_difficulty_items = OrderedDict([ + (_PL_consts.PSPCF.RAIL_NONE, (str(_PL_consts.PSPCF.RAIL_NONE), "None", "")), + (_PL_consts.PSPCF.RAIL_EASY, (str(_PL_consts.PSPCF.RAIL_EASY), "Unload (Easy)", "")), + (_PL_consts.PSPCF.RAIL_MEDIUM, (str(_PL_consts.PSPCF.RAIL_MEDIUM), "Unload (Medium)", "")), + (_PL_consts.PSPCF.RAIL_HARD, (str(_PL_consts.PSPCF.RAIL_HARD), "Unload (Hard)", "")), + (_PL_consts.PSPCF.RAIL_RIGID, (str(_PL_consts.PSPCF.RAIL_RIGID), "Unload (Rigid?)", "")), + (_PL_consts.PSPCF.RAIL_LOAD, (str(_PL_consts.PSPCF.RAIL_LOAD), "Load", "")), + ]) + # LOCATORS - PREFAB - SPAWN POINTS (CUSTOM) + locator_prefab_custom_parking_difficulty: EnumProperty( + name="Parking Difficulty", + description="Current parking difficulty", + items=enum_custom_parking_difficulty_items.values(), + default=str(_PL_consts.PSPCF.RAIL_NONE), + ) + enum_custom_lenght_items = OrderedDict([ + (_PL_consts.PSPCF.LENGHT_14, (str(_PL_consts.PSPCF.LENGHT_14), "14 m", "")), + (_PL_consts.PSPCF.LENGHT_15, (str(_PL_consts.PSPCF.LENGHT_15), "15 m", "")), + (_PL_consts.PSPCF.LENGHT_16, (str(_PL_consts.PSPCF.LENGHT_16), "16 m", "")), + (_PL_consts.PSPCF.LENGHT_17, (str(_PL_consts.PSPCF.LENGHT_17), "17 m", "")), + (_PL_consts.PSPCF.LENGHT_18, (str(_PL_consts.PSPCF.LENGHT_18), "18 m", "")), + (_PL_consts.PSPCF.LENGHT_19, (str(_PL_consts.PSPCF.LENGHT_19), "19 m", "")), + (_PL_consts.PSPCF.LENGHT_20, (str(_PL_consts.PSPCF.LENGHT_20), "20 m", "")), + (_PL_consts.PSPCF.LENGHT_21, (str(_PL_consts.PSPCF.LENGHT_21), "21 m", "")), + (_PL_consts.PSPCF.LENGHT_22, (str(_PL_consts.PSPCF.LENGHT_22), "22 m", "")), + (_PL_consts.PSPCF.LENGHT_23, (str(_PL_consts.PSPCF.LENGHT_23), "23 m", "")), + (_PL_consts.PSPCF.LENGHT_24, (str(_PL_consts.PSPCF.LENGHT_24), "24 m", "")), + (_PL_consts.PSPCF.LENGHT_25, (str(_PL_consts.PSPCF.LENGHT_25), "25 m", "")), + (_PL_consts.PSPCF.LENGHT_26, (str(_PL_consts.PSPCF.LENGHT_26), "26 m", "")), + (_PL_consts.PSPCF.LENGHT_27, (str(_PL_consts.PSPCF.LENGHT_27), "27 m", "")), + (_PL_consts.PSPCF.LENGHT_28, (str(_PL_consts.PSPCF.LENGHT_28), "28 m", "")), + (_PL_consts.PSPCF.UNLIMITED, (str(_PL_consts.PSPCF.UNLIMITED), "Unlimited", "")), + ]) + locator_prefab_custom_lenght: EnumProperty( + name="Trailer Lenght", + description="Max trailer lenght", + options={'HIDDEN'}, + items=enum_custom_lenght_items.values(), + default=str(_PL_consts.PSPCF.LENGHT_14), + ) + enum_custom_rule_items = OrderedDict([ + (_PL_consts.PSPCF.TRAILER_ANY, (str(_PL_consts.PSPCF.TRAILER_ANY), "Any Trailer", "")), + (_PL_consts.PSPCF.TRAILER_BOX, (str(_PL_consts.PSPCF.TRAILER_BOX), "Box Trailer", "")), + (_PL_consts.PSPCF.TRAILER_TANK, (str(_PL_consts.PSPCF.TRAILER_TANK), "Tank Trailer", "")), + (_PL_consts.PSPCF.TRAILER_DUMP_BULK, (str(_PL_consts.PSPCF.TRAILER_DUMP_BULK), "Dump & Bulk", "")), + (_PL_consts.PSPCF.TRAILER_PLATFORM_LOG_CONT, (str(_PL_consts.PSPCF.TRAILER_PLATFORM_LOG_CONT), "Platform, Log & Container", "")), + (_PL_consts.PSPCF.TRAILER_LIVESTOCK, (str(_PL_consts.PSPCF.TRAILER_LIVESTOCK), "Livestock", "")), + (_PL_consts.PSPCF.TRAILER_LOG, (str(_PL_consts.PSPCF.TRAILER_LOG), "Log Trailer", "")), + ]) + locator_prefab_custom_rule: EnumProperty( + name="Trailer Type", + description="Trailer type", + options={'HIDDEN'}, + items=enum_custom_rule_items.values(), + default=str(_PL_consts.PSPCF.TRAILER_ANY), + ) # LOCATORS - PREFAB - TRAFFIC LIGHTS (SEMAPHORES) enum_tsem_id_items = OrderedDict([(-1, ('-1', "None", ""))]) for i in range(_PL_consts.TSEM_COUNT_MAX): diff --git a/addon/io_scs_tools/ui/object.py b/addon/io_scs_tools/ui/object.py index 4294a55..209232a 100644 --- a/addon/io_scs_tools/ui/object.py +++ b/addon/io_scs_tools/ui/object.py @@ -366,8 +366,21 @@ def draw_prefab_spawn_point(layout, obj): layout.use_property_split = True layout.use_property_decorate = False + # spawn type layout.prop(obj.scs_props, 'locator_prefab_spawn_type') + # check if Spawn Type = Custom (9) + if obj.scs_props.locator_prefab_spawn_type == str(_PL_consts.PSP.CUSTOM): + # parking difficulty + layout.prop(obj.scs_props, 'locator_prefab_custom_parking_difficulty') + + # lenght + layout.prop(obj.scs_props, 'locator_prefab_custom_lenght') + + # rule (trailer type) + layout.prop(obj.scs_props, 'locator_prefab_custom_rule') + + @staticmethod def draw_prefab_semaphore(layout, obj): layout.use_property_split = True From 0e076239a5a24f5b7cc9e15f2552c442bb613e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 23 Sep 2024 16:13:01 +0200 Subject: [PATCH 05/15] Fix error when import .pip without "Flags" * Fixed error when you try import old .pip file, without "Flags" attribute inside "SpawnPoint". --- addon/io_scs_tools/imp/pip.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addon/io_scs_tools/imp/pip.py b/addon/io_scs_tools/imp/pip.py index 9efe5b0..890eec4 100644 --- a/addon/io_scs_tools/imp/pip.py +++ b/addon/io_scs_tools/imp/pip.py @@ -749,6 +749,9 @@ def load(filepath, terrain_points_trans): else: spawn_name = _name_utils.get_unique(spawn_name, spawn_points_data.keys()) + if spawn_flags is None: + spawn_flags = int(0) + spawn_points_data[spawn_name] = ( spawn_index, spawn_position, From 2c737707f6948a960c641e4d975ca009be1d805f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Fri, 4 Oct 2024 20:20:18 +0200 Subject: [PATCH 06/15] Fixes with custom spawn point, bgl remove * Custom spawn point fixes (now unload/load is separeted from parking difficulty) * Added visual colored shape showing depot place, size and difficulty * BGL module was replaced by GPU in one place * Some blf.size fixes (removed unnecessary arg) --- addon/io_scs_tools/consts.py | 17 ++-- addon/io_scs_tools/exp/pip/spawn_point.py | 3 + addon/io_scs_tools/imp/pip.py | 12 ++- addon/io_scs_tools/internals/open_gl/core.py | 28 +++--- .../internals/open_gl/locators/prefab.py | 93 ++++++++++++++++++- addon/io_scs_tools/properties/object.py | 24 +++-- addon/io_scs_tools/ui/object.py | 5 +- 7 files changed, 146 insertions(+), 36 deletions(-) diff --git a/addon/io_scs_tools/consts.py b/addon/io_scs_tools/consts.py index cb732e8..cf01780 100644 --- a/addon/io_scs_tools/consts.py +++ b/addon/io_scs_tools/consts.py @@ -447,14 +447,17 @@ class PIF: class PSPCF: """Constants represetning spawn point custom flags. """ + # Depot Types + DEPOT_TYPE_MASK = 0x00000004 + DEPOT_TYPE_UNLOAD = 0x00000000 + DEPOT_TYPE_LOAD = 0x00000004 + # Difficulties - RAIL_MASK = 0x0000000F - RAIL_NONE = 0x00000000 - RAIL_EASY = 0x00000001 - RAIL_MEDIUM = 0x00000002 - RAIL_HARD = 0x00000003 - RAIL_RIGID = 0x00000004 # ?? idk - RAIL_LOAD = 0x00000005 + DIFFICULTY_MASK = 0x00000003 + DIFFICULTY_NONE = 0x00000000 + DIFFICULTY_EASY = 0x00000001 + DIFFICULTY_MEDIUM = 0x00000002 + DIFFICULTY_HARD = 0x00000003 # Lenght LENGHT_MASK = 0x000000F0 diff --git a/addon/io_scs_tools/exp/pip/spawn_point.py b/addon/io_scs_tools/exp/pip/spawn_point.py index b30cd81..b1f4dbf 100644 --- a/addon/io_scs_tools/exp/pip/spawn_point.py +++ b/addon/io_scs_tools/exp/pip/spawn_point.py @@ -85,6 +85,9 @@ def set_flags(self, sp_flags): :type sp_flags: int """ + # depot type + self.__flags |= int(sp_flags.locator_prefab_custom_depot_type) + # parking difficulty self.__flags |= int(sp_flags.locator_prefab_custom_parking_difficulty) diff --git a/addon/io_scs_tools/imp/pip.py b/addon/io_scs_tools/imp/pip.py index 890eec4..92c17f8 100644 --- a/addon/io_scs_tools/imp/pip.py +++ b/addon/io_scs_tools/imp/pip.py @@ -460,10 +460,14 @@ def _create_spawn_locator( locator.scs_props.locator_prefab_type = 'Spawn Point' locator.scs_props.locator_prefab_spawn_type = str(spawn_type) - # flags - locator.scs_props.locator_prefab_custom_parking_difficulty = str(spawn_flags & _PL_consts.PSPCF.RAIL_MASK) - locator.scs_props.locator_prefab_custom_lenght = str(spawn_flags & _PL_consts.PSPCF.LENGHT_MASK) - locator.scs_props.locator_prefab_custom_rule = str(spawn_flags & _PL_consts.PSPCF.TRAILER_MASK) + # flags for custom spawn type + + # check if Spawn Type = Custom (9) + if locator.scs_props.locator_prefab_spawn_type == str(_PL_consts.PSP.CUSTOM): + locator.scs_props.locator_prefab_custom_depot_type = str(spawn_flags & _PL_consts.PSPCF.DEPOT_TYPE_MASK) + locator.scs_props.locator_prefab_custom_parking_difficulty = str(spawn_flags & _PL_consts.PSPCF.DIFFICULTY_MASK) + locator.scs_props.locator_prefab_custom_lenght = str(spawn_flags & _PL_consts.PSPCF.LENGHT_MASK) + locator.scs_props.locator_prefab_custom_rule = str(spawn_flags & _PL_consts.PSPCF.TRAILER_MASK) return locator diff --git a/addon/io_scs_tools/internals/open_gl/core.py b/addon/io_scs_tools/internals/open_gl/core.py index 5a46dc5..5d1655a 100644 --- a/addon/io_scs_tools/internals/open_gl/core.py +++ b/addon/io_scs_tools/internals/open_gl/core.py @@ -20,7 +20,7 @@ import bpy import blf -import bgl +import gpu from mathutils import Vector from gpu_extras.presets import draw_texture_2d from io_scs_tools.consts import Operators as _OP_consts @@ -139,15 +139,14 @@ def _draw_3dview_report(window, area, region): # draw BT banner (bindcode, width, height) = _Show3DViewReport.get_scs_banner_img_data(window) - bgl.glEnable(bgl.GL_BLEND) - bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA) + gpu.state.blend_set("ALPHA") draw_texture_2d(bindcode, (pos_x - 5, pos_y), width, height) - bgl.glDisable(bgl.GL_BLEND) + gpu.state.blend_set("NONE") # draw control buttons, if controls are enabled if _Show3DViewReport.has_controls(window): - blf.size(0, 20, 72) + blf.size(0, 20) blf.color(0, .8, .8, .8, 1) # set x and y offsets to report operator, so that area calculations for buttons can be calculated properly @@ -187,7 +186,7 @@ def _draw_3dview_report(window, area, region): # draw scroll controls if _Show3DViewReport.is_scrolled() and _Show3DViewReport.is_shown(): - blf.size(0, 16, 72) + blf.size(0, 16) # draw scroll up button scroll_up_pos = ( @@ -243,7 +242,7 @@ def _draw_3dview_report(window, area, region): # draw version string pos_y -= 12 - blf.size(0, 11, 72) + blf.size(0, 11) blf.color(0, 0.909803921568627, .631372549019608, .0627450980392157, 1) blf.shadow(0, 0, 0, 0, 0, 1) blf.position(0, pos_x, pos_y, 0) @@ -253,7 +252,7 @@ def _draw_3dview_report(window, area, region): # draw actual operator title and message if shown if _Show3DViewReport.is_shown(): - blf.size(0, 12, 72) + blf.size(0, 12) blf.color(0, 1, 1, 1, 1) blf.shadow(0, 0, 0, 0, 0, 1) @@ -322,7 +321,7 @@ def _draw_3dview_immediate_report(region): ) # set size of the immidete text - blf.size(0, 18, 72) + blf.size(0, 18) blf.color(0, .952, .635, .062, 1) # draw on center of the region @@ -457,16 +456,15 @@ def draw_custom_3d_elements(mode): return if mode == "Normal": - bgl.glEnable(bgl.GL_DEPTH_TEST) - bgl.glEnable(bgl.GL_BLEND) - bgl.glBlendFunc(bgl.GL_SRC_ALPHA, bgl.GL_ONE_MINUS_SRC_ALPHA) + gpu.state.depth_test_set("LESS") + gpu.state.blend_set("ALPHA") # draw buffers _primitive.draw_buffers(bpy.context.space_data) if mode == "Normal": - bgl.glDisable(bgl.GL_DEPTH_TEST) - bgl.glDisable(bgl.GL_BLEND) + gpu.state.depth_test_set("NONE") + gpu.state.blend_set("NONE") def draw_custom_2d_elements(): @@ -495,7 +493,7 @@ def draw_custom_2d_elements(): return font_id = 0 # default font - blf.size(font_id, 12, 72) + blf.size(font_id, 12) blf.color(font_id, scs_globals.info_text_color[0], scs_globals.info_text_color[1], scs_globals.info_text_color[2], 1.0) blf.word_wrap(font_id, 999) blf.enable(font_id, blf.WORD_WRAP) diff --git a/addon/io_scs_tools/internals/open_gl/locators/prefab.py b/addon/io_scs_tools/internals/open_gl/locators/prefab.py index 0b60ba7..08a8d4b 100644 --- a/addon/io_scs_tools/internals/open_gl/locators/prefab.py +++ b/addon/io_scs_tools/internals/open_gl/locators/prefab.py @@ -99,6 +99,84 @@ def draw_shape_spawn_point(mat, scs_globals): _primitive.append_line_vertex((mat @ Vector((0.0, 0.1299, 0.525))), color) _primitive.append_line_vertex((mat @ Vector((0.0, -0.1299, 0.675))), color) +def draw_shape_spawn_point_custom(mat, scs_globals, obj): + """ + Draws shape for "Custom" type "Locator" of "Spawn Point" type. + :param mat: + :param scs_globals: + :param obj: + :return: + """ + + color = ( + scs_globals.locator_prefab_wire_color.r, + scs_globals.locator_prefab_wire_color.g, + scs_globals.locator_prefab_wire_color.b, + 1.0 + ) + + # Load + if (int(obj.scs_props.locator_prefab_custom_depot_type) / 4) == 1: + match obj.scs_props.locator_prefab_custom_parking_difficulty: + case "1": # Easy + difficulty_color = (0.0, 1.0, 1.0, 1.0) + case "2": # Medium + difficulty_color = (0.0, 0.471, 1.0, 1.0) + case "3": # Hard + difficulty_color = (0.0, 0.0, 0.784, 1.0) + case _: + difficulty_color = (0.0, 1.0, 1.0, 1.0) + # Unload + else: + match obj.scs_props.locator_prefab_custom_parking_difficulty: + case "1": # Easy + difficulty_color = (1.0, 1.0, 0.0, 1.0) + case "2": # Medium + difficulty_color = (0.706, 0.471, 0.0, 1.0) + case "3": # Hard + difficulty_color = (1.0, 0.0, 0.0, 1.0) + case _: + difficulty_color = (1.0, 1.0, 0.0, 1.0) + + # Matrix without "Locator Size" + mat_orig = obj.matrix_world + + width = 3.4 + height = 0.05 # Height above ground to prevent z-fight + lenght = (int(obj.scs_props.locator_prefab_custom_lenght) / 16) + 14 + + # Set diffrent shape for "Unlimited" lenght (max size of last fixed lenght) + if lenght == 29.0: + lenght = 20.0 + + _primitive.append_line_vertex((mat_orig @ Vector((0.0, lenght + 3.0, height))), difficulty_color) + _primitive.append_line_vertex((mat_orig @ Vector((width/2, lenght + 1.0, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((width/2, lenght + 8.0, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((0.0, lenght + 10.0, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((-width/2, lenght + 8.0, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((-width/2, lenght + 1.0, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((0.0, lenght + 3.0, height))), difficulty_color) + + # Locator + _primitive.append_line_vertex((mat @ Vector((0.0, 0.0, scs_globals.locator_empty_size))), color) # , color + _primitive.append_line_vertex((mat @ Vector((0.0, 0.0, 0.75))), color) + _primitive.append_line_vertex((mat @ Vector((-0.1299, 0.0, 0.525))), color) + _primitive.append_line_vertex((mat @ Vector((0.1299, 0.0, 0.675))), color) + _primitive.append_line_vertex((mat @ Vector((0.1299, 0.0, 0.525))), color) + _primitive.append_line_vertex((mat @ Vector((-0.1299, 0.0, 0.675))), color) + _primitive.append_line_vertex((mat @ Vector((0.0, -0.1299, 0.525))), color) + _primitive.append_line_vertex((mat @ Vector((0.0, 0.1299, 0.675))), color) + _primitive.append_line_vertex((mat @ Vector((0.0, 0.1299, 0.525))), color) + _primitive.append_line_vertex((mat @ Vector((0.0, -0.1299, 0.675))), color) + + # Depot + _primitive.append_line_vertex((mat_orig @ Vector((width/2, 0.0, height))), difficulty_color) + _primitive.append_line_vertex((mat_orig @ Vector((-width/2, 0.0, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((-width/2, lenght, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((0.0, lenght + 2.0, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((width/2, lenght, height))), difficulty_color, is_strip=True) + _primitive.append_line_vertex((mat_orig @ Vector((width/2, 0.0, height))), difficulty_color) + def draw_shape_traffic_light(mat, scs_globals): """ @@ -211,7 +289,10 @@ def draw_prefab_locator(obj, scs_globals): _primitive.draw_shape_y_axis(mat, empty_size) _primitive.draw_shape_z_axis_neg(mat, empty_size) if not obj.scs_props.locator_preview_model_present or not scs_globals.show_preview_models: - draw_shape_spawn_point(mat, scs_globals) + if obj.scs_props.locator_prefab_spawn_type == str(_PL_consts.PSP.CUSTOM): + draw_shape_spawn_point_custom(mat, scs_globals, obj) + else: + draw_shape_spawn_point(mat, scs_globals) elif obj.scs_props.locator_prefab_type == 'Traffic Semaphore': _primitive.draw_shape_x_axis(mat, empty_size) @@ -259,6 +340,16 @@ def get_prefab_locator_comprehensive_info(obj): spawn_type_i = int(obj.scs_props.locator_prefab_spawn_type) textlines.append("Type: %s" % obj.scs_props.enum_spawn_type_items[spawn_type_i][1]) + if obj.scs_props.locator_prefab_spawn_type == str(_PL_consts.PSP.CUSTOM): + depot_type_i = int(obj.scs_props.locator_prefab_custom_depot_type) + difficulty_i = int(obj.scs_props.locator_prefab_custom_parking_difficulty) + lenght_i = int(obj.scs_props.locator_prefab_custom_lenght) + trailer_i = int(obj.scs_props.locator_prefab_custom_rule) + + textlines.append("Difficulty: %s (%s)" % (obj.scs_props.enum_custom_depot_type_items[depot_type_i][1], + obj.scs_props.enum_custom_parking_difficulty_items[difficulty_i][1])) + textlines.append("Lenght: %s" % obj.scs_props.enum_custom_lenght_items[lenght_i][1]) + textlines.append("Trailer: %s" % obj.scs_props.enum_custom_rule_items[trailer_i][1]) elif obj.scs_props.locator_prefab_type == 'Traffic Semaphore': diff --git a/addon/io_scs_tools/properties/object.py b/addon/io_scs_tools/properties/object.py index 68a394c..e87a4a1 100644 --- a/addon/io_scs_tools/properties/object.py +++ b/addon/io_scs_tools/properties/object.py @@ -878,20 +878,28 @@ def locator_prefab_type_update(self, context): items=enum_spawn_type_items.values(), default=str(_PL_consts.PSP.NONE), ) + # LOCATORS - PREFAB - SPAWN POINTS (CUSTOM) + enum_custom_depot_type_items = OrderedDict([ + (_PL_consts.PSPCF.DEPOT_TYPE_UNLOAD, (str(_PL_consts.PSPCF.DEPOT_TYPE_UNLOAD), "Unload", "")), + (_PL_consts.PSPCF.DEPOT_TYPE_LOAD, (str(_PL_consts.PSPCF.DEPOT_TYPE_LOAD), "Load", "")), + ]) + locator_prefab_custom_depot_type: EnumProperty( + name="Depot Type", + description="Depot Type", + items=enum_custom_depot_type_items.values(), + default=str(_PL_consts.PSPCF.DEPOT_TYPE_UNLOAD), + ) enum_custom_parking_difficulty_items = OrderedDict([ - (_PL_consts.PSPCF.RAIL_NONE, (str(_PL_consts.PSPCF.RAIL_NONE), "None", "")), - (_PL_consts.PSPCF.RAIL_EASY, (str(_PL_consts.PSPCF.RAIL_EASY), "Unload (Easy)", "")), - (_PL_consts.PSPCF.RAIL_MEDIUM, (str(_PL_consts.PSPCF.RAIL_MEDIUM), "Unload (Medium)", "")), - (_PL_consts.PSPCF.RAIL_HARD, (str(_PL_consts.PSPCF.RAIL_HARD), "Unload (Hard)", "")), - (_PL_consts.PSPCF.RAIL_RIGID, (str(_PL_consts.PSPCF.RAIL_RIGID), "Unload (Rigid?)", "")), - (_PL_consts.PSPCF.RAIL_LOAD, (str(_PL_consts.PSPCF.RAIL_LOAD), "Load", "")), + (_PL_consts.PSPCF.DIFFICULTY_NONE, (str(_PL_consts.PSPCF.DIFFICULTY_NONE), "None", "")), + (_PL_consts.PSPCF.DIFFICULTY_EASY, (str(_PL_consts.PSPCF.DIFFICULTY_EASY), "Easy", "")), + (_PL_consts.PSPCF.DIFFICULTY_MEDIUM, (str(_PL_consts.PSPCF.DIFFICULTY_MEDIUM), "Medium", "")), + (_PL_consts.PSPCF.DIFFICULTY_HARD, (str(_PL_consts.PSPCF.DIFFICULTY_HARD), "Hard", "")), ]) - # LOCATORS - PREFAB - SPAWN POINTS (CUSTOM) locator_prefab_custom_parking_difficulty: EnumProperty( name="Parking Difficulty", description="Current parking difficulty", items=enum_custom_parking_difficulty_items.values(), - default=str(_PL_consts.PSPCF.RAIL_NONE), + default=str(_PL_consts.PSPCF.DIFFICULTY_EASY), ) enum_custom_lenght_items = OrderedDict([ (_PL_consts.PSPCF.LENGHT_14, (str(_PL_consts.PSPCF.LENGHT_14), "14 m", "")), diff --git a/addon/io_scs_tools/ui/object.py b/addon/io_scs_tools/ui/object.py index 209232a..f4388d2 100644 --- a/addon/io_scs_tools/ui/object.py +++ b/addon/io_scs_tools/ui/object.py @@ -371,6 +371,10 @@ def draw_prefab_spawn_point(layout, obj): # check if Spawn Type = Custom (9) if obj.scs_props.locator_prefab_spawn_type == str(_PL_consts.PSP.CUSTOM): + + # depot type (load/unload) + layout.prop(obj.scs_props, 'locator_prefab_custom_depot_type', expand=True, toggle=True) + # parking difficulty layout.prop(obj.scs_props, 'locator_prefab_custom_parking_difficulty') @@ -380,7 +384,6 @@ def draw_prefab_spawn_point(layout, obj): # rule (trailer type) layout.prop(obj.scs_props, 'locator_prefab_custom_rule') - @staticmethod def draw_prefab_semaphore(layout, obj): layout.use_property_split = True From 3075e459e000ab746ad112c164cb06d722c3d663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Thu, 10 Oct 2024 19:16:22 +0200 Subject: [PATCH 07/15] reflection fix, shaders update * Fixed upside-down reflection in env shaders * Updated .bin file with new shaders (eut2.interior) --- .../eut2/std_node_groups/refl_normal_ng.py | 2 +- addon/io_scs_tools/supported_effects.bin | Bin 190106 -> 190943 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/refl_normal_ng.py b/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/refl_normal_ng.py index 15215bb..5216457 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/refl_normal_ng.py +++ b/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/refl_normal_ng.py @@ -61,7 +61,7 @@ def __create_refl_normal_group__(): view_vector_n = refl_normal_g.nodes.new("ShaderNodeVectorMath") view_vector_n.location = (185, 250) view_vector_n.operation = "MULTIPLY" - view_vector_n.inputs[1].default_value = (-1,) * 3 + view_vector_n.inputs[1].default_value = (-1,1,1) view_vector_norm_n = refl_normal_g.nodes.new("ShaderNodeVectorMath") view_vector_norm_n.location = (185 * 2, 250) diff --git a/addon/io_scs_tools/supported_effects.bin b/addon/io_scs_tools/supported_effects.bin index 50a04993855fe1007ce092ad987226e83de3cd07..f6a56b1c0cf59e5c4de0b3af50086133ce96a066 100644 GIT binary patch literal 190943 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μLgRaCC&`OtbSh3=FPSv5~SU6x%02Lu5 zJ%XUINhCTl(z~B$FqzF=>szTMvG-$qQJiEup%Y0!8Oorym;oQDW#<|{CK(lG_1;ul z-Zb%aO+~7Y4fB*@@{<2}+T*|dzyIIw*#F^&w6CtOU)-MG$xd_p9D+ju{kST5MYM`n(gjJfJ3zM2S|9W$$ZMv|vc76G4`|Rd#3A zG__-W20|+LFfX17P*4>zeAKiZWa)mVa(vKdhSi1ic>~63V9J{z-(D|Onp3U-^Z@yj zkPRb|vc0*zXa`x$T_D8%8x|e%>dRZ{Zd}VazrVQg6=!IRbq=W~l!d|TtA`Q9*7@+VSx-@|x@ zm^K!sb}djB4qjBLk^8$(L4jkatXYBhv^hl+z^C7zo%A_XH*!wyA2Qz<(Tc$`^snrK zI^mD9zTSNzMNr%sw|c1Vz{FR!JeU{yWA7J0RDC=F*H?G4uS+_arh$fB z;c&MTWkg;use~rY)sPc|AgrG2?b30nk>PGKvJG=Zkf)!Z*=N^k;w zEkX?@Q`cDzWJCPI9LUa{tKVyV%*zC?p~l)GHoU^lLTlN2I~n}_g<`>$?p55)($}Z% zo8g+cP`=#Q%gi*?6yqEqCb z1~j#`@82)f(G7jv2O=fyajiDq@#niGGdoRIOf@d zHZ(=wiNPEca&tXK3@Q&=8;g#yX?sv6rloukQXx%mvqi?J3a6;yV<8^If~xRLK43*5 zq&njYTn>CJl;C98y~E|$Ru2*Fbi;_E^;;R|-I?F!cW^UXK)t$oM@SKwDL*&xL4B#@ z1%!4Ger~^vMk2vsB5w{~dbhfe(pWq@V=Gxg4y;i~#A^e8k?<)3EbA@#B@JY77tM)7MZ+v{T5m6(s9k~Z(|K{XVD&hfKT;4vwt}g7$eQ+NW;>4LRu73z?!}uD>B1k7WB>+uH-uOH6{sr-OH1K+;w88clW4 zL-IAt!ASGvoXq<2rerv#%B&zbGMkJbb@d|iDPGP4C z$Tr+qHP#HnVhSfyYHHR+HO*cBoWraZ#gwD|v-B?V&L`hh^um>*-LYx_>R8*7i41B& z68in5z}jY7*?QnIb?LdhpKQWjgsnPGqErZs?vDgOUlZj8J3lW%$+$qfxnU%ig4%R0 zql^*C@Cb~SN#ZPqfKGE|@()5rhgL(oiGS?lbc)6@9iEfhqCTBPO9ze+-QQdv?jJ|J z{rILNdnnEuj@Ycj>Q~oxi3@bL3hNEK+BK3>Ek3fES(=*^pi=4GCznzR(+x@%`|6lT z^VO_=ni*f|1k3JIa!VmHy?#!JEB;7K5`mMLggzprJ?v$YNNy^0(5mF`;bL108hS~~ zgVCy?aZ;j8bMm&BAFE63zDSW4pM+J!+Vn4|qefb&zOhoN7ht!fJz23(v{XYIg39n> zgHR-dFEY3L6yEu#-Haxvg(2A1v`twc){SYrIB=}GRdd^4jxT8_xOj1Wc_XA#Wt9aY z3>2_8@%lD+mXFYwbQTiQRJTsJ)eDhbn7b=wJAu&4BuKrjh3Dz`IrCr$xP0eh`mJ$= z<&I*!qiLxV2E@lX*Jyp2v*?e&eY#`z{K_7ur6iuVTi>ZON0Fmg&{q)Wz5f^o>Bja) zGAxy2(D6i#{OiA`munnBu!PWokf3F^H#vy@<8B+k9mHQr$Mj8Ghc~r_hEXb}H#?g! z%cTg?B2%4N6wY2hZ@;TG`fjU2OS{I zIF)mm09FU~+B$9RZY#uggiVL#@-u_;)__PH-AblBhrnT$>V|N8&RQadQczkgL6L5< zNiM_2TQZwKLHsAfL;UZI4$^AbBi4r>2`-mDYTimSQJ>{h!(7GsOC7U2Ti7Ud7T!9i zba&zsiT!7d!3PUP?(|myFgV$MKh?l1AeEWY7`_kJDr>H!DV+heL>vi?mlt~bP=0Cm z{nc6CB(&7y7-eG)TZxgD#fo;V9605bF}uU0nzH ztMgF%Y05e@rmJ;L+d`KjB&R{-4iXb>2gqk3)tvjMV;?2p=zq^3X-s>T@!dpFon?TbID7)$)S$w`!mV66n9fO+#>N}Td39)m2$mz~9F_zz z)nRM^O6Wu(5nS@OS?O;&$@A4gw5oX$Z9ZLW>YHaI+E_=yzQ5fOkP@| zTOc;@7wMfoM_FCi0`meW(5-0o30n*OdZ>uPo3i55if|U}fq;5ReX2F6SWGh}RdS(@|}jP`u6sKQ=p_On304 z%XB~_OXU#^hpfR_h)!A)4mM*v(GV>iq(}GVj@s4C;bKsr9n?_C4^rVus3>9Z!M-iI zN?s$VV0U}QU97%m9Zh(mBy(i7#rQ=YsM`$lyjC8lZ;9#KG}4v!LCH!fC476CX<`%p zU>>t{6Xvt-{f`g!`xC}>4m2usk|a_;cKg73Hl+VHx)&?Ub*?BHOT^{Vjsv~K$8C)9d%o3fpLM?Kx&h6=UqSu+*krqB?CjO{u7sK)COQOTP} z{O-;bN0BoW>8u`(#LvY6Zf-xfd@i~+)iOz!(Kj-~CccI-a%nNOuMj-?izD^Z76t{^ z0~`sYd!(hOI0uYI$|*XMm;^hFk*Sq7$VT4Tf}MyFTRnu~CS*CN1y3?->NN!Pg&V>A zV5VbXiN(E1pc+s;rdGH%h$YTAP1ddn-Si!s=g~a(3Xj4m7Hv{ z?p&2jXs^p;iH8(9oKZ%k_!TnmKKXSIh_4ha2MEHjW{~&qZ@<2|KY#P~`tnS+uk)9q z?N##bCo|`C+dZ2D?DF zSJKfIRTI}u5hD|%#>Y^hs(t92+8A>{04ODPI3r3^hA}28MF_s?lwact$e~jnUdzJJ zg?7`gdO~67b6I7b`G_L?IiFnf*tQ3IVynU^*)x@DDEh39<&!Q9ofaOA-YDp7=q;D# zlaRGxGFF^Y_mZt_Mi;yFCDiB~;Y+=ls1vn96kllq`scgM{B%~H7ig;cJ6?!Z=3E6n zq$>*C<8(48ov3x!V{p9HGTqBU!CQg0vD_-lZmkr65(=?hT zZiFV?q`{4rO!lpwFD}n7uCHEy@$O!4kbHdj)f8#20z+aoB?fRKG5)j{fIGRu$g;`8Uwd5d}2#k?Ld{afcyS%@> z)*sCv+JmB3FF2@fBd*}RWWS{h*{O{f)l(4KkEt_~ZfYH8u{ER^XBCbb+S^LVb+nXY zSQpG(63a;ziRdm3)o_qze3n?$XzN&(pafHAD15B~Ndk4thh;#uy>W#%Kk2JB@S#*1 zhiEkVKRTi4e$Do%Ux?Pyt18<@vmWy(qjVLf0z*3I)wzSB%WAtQyW<|2Y*w7K`9t+E zSLR&XLt62$+VHbDxL-e6O{_W`%7^bRZ&n~#CU#`uQR6yh_CG3_=Zf%E4HfekbNJ^R zn38F{vC1sy`jag%`bnlw^a(UZ#YwamN~tSm7&2MpbQF(e*O`c{u%BhixH1nF_R*$R zpepEF0lL4Q%^$Ef$3a39t1;pIX}4R2<$Yq7Ng2Uk->w*&&S1c))|`PD3Pl8PAIYEA zh_f~>j;BN9qy5LUqHLlVZE()G5G+Dm12FP;a5^-RwLcg29J5l?Qc;4bP1snx~ z1G~FxB!LqM8_k1d@Pg%UCz(bRfrqWbSQ$?u*8eW5Iv8lUvND%7miF3kBQ}2@%uW-K zEo5lRU(6y)LWGf#wU35<1)f|LV))@!pu5bsEz7(A@;7Jq@6PY!OA0#rmq*Zz9_F=0 z2u+<4h;Vn2BJE63WrAbk%5@VzGO)BIeJP)0!fM|O$pA=VJr@WM7ef~trMe0v!C7Gi z|I|2r^$8hk6r(cY5I3PL1zhHVxJcBzt--z0BpZ(WV$o165ZvTH8MZ(CDMD+Q&%yxKzh?}QIUcOR?J``|Vz6DvRW3P=PeAE}k*K*qI+X~Yc*SEKC z=gG|KOL!%ST{kl_;>3wZW@SBE+`iY>S_yTojc$+tf1wV4 zUBaUmX9ntJgLLRCI3LbPhh!G0y||N#I-`jwdgrIgg_kue)k|ddVw$o%MXVN!x->Tu z5*QM^Q<}85oiM`WTD!9K>8HE94=;MoE=a#z{I~a2vM<1Z2{fL7Ba3|&${606OeAn6 z=hy#e;AT5v$dqgZOpqIwhH=XE0b|Galnh0y?P5IsT3*kLRLUBzl!`k4|0*jazo>OxRkkTLjC;HuU{BP{CNNJNvc&^>WFZ``2Z&~?B-rqy+;E(WfiUJ zatc2XOE6499jgd4GuSWhkvLfE1PU?q)Crz$F6ZdJth(y)UcwmCW4x#V=)A_zVWAf5 zv#Gr_Cf)m@!e=|os7E@N7YItR+~iX7st+Gl>2%b>;B~SSVCZ7u;24q+gX&AY!pSQm z^8b*s3OmSKanrg&w1afDQu(DUZ`-ouZ60}!*k3VS8MXtW4#Jt8!;s)Y+IyY@#OhXW zLs8t53*Et|7Ub^Cb|Pmv;Tw}VVAeV7aAL!&6%Mzj2i~Qt_XxU5ItcQU!}!PSzt=Ba zj~Z3O2@ILrZ@$M7g3**9&bUH_CR4i9?WaPs`7uT(%euHz%Sq?H1eu{0*tA^F$rES* zw9DYVqWVhn@u#Pk5B5sg#}Be|TK#xMTfF#s$ehE|1tQ2c-B@$uOY=k6MD>-;f(gY4 z_>or7qNb)Td@yujh5zkpV1 zzc=rf27ib+78H`kzJGm1NO?~+eU*i}k!0k!*iL<+xrOu3fij0A7MF(AEA`zR#YXI= zV=l2o!cla4Rk#AqvTGc)_@tp-@b1Es7fs}BW^_L#*WMP9qJ0ntRzp9znn`|XonIUr zTaKV4`j^lB#`(>^Hc(cGGrh!VwPX1WK$EAC-f~g<_Y6W~2jgP~>Ne1C0<3g+X{uN= zLVCaj^+ZHLTiYY%ZTJgBpn&ba4M}E*GX9{+8U}6Hr3Ulx=KY6c)lOpqLiu-621$Zp zKK+VKj{c_Ba6#b^ZTh+;q#?Lg>1TBc^uixHp` zmqr=L+?;9@U*v)ysvToYmnv2WvLWThvv_FmFyYT7oED2Hmv4q@GhTvM+`)6u{!BJq zz{q{oh9d(hoH$$U4)n-F;S$*A%3&@Q?z(i1tJ_)rXD^9)L(1=@Aax8Z2a1;7pg$E_ zZp8wU@PmF_*DhS@hqx(5bvwK93a^X*-J%K6z(3E#W#fOX#W5i(3jFgw@HZE(rmg%E zt2Edjn)$&SHD%vUio~U_pVT{SW-T&TEgDMX8kkOS6_VBQn$IaM;dZtQm#-eGM*Q-e zwFBobf428NH=lIzO{(Rq-`BbZZ$?RhW>2*?Ca-vVgHo+YL8+PLeVr|6B0Y(pN!x4R zRi0eaExKn!=u?j_ehcEPQyq;-ysAL(N4yY z6m1N(m5+79XjH3(#PVbWb5i|~Hy-cq>IdA?@0`&AsO@6Xe`<5U*VoaJr$k!#uwx>U z?d6>)N=W@SNF6$wr~5+~Myn-UoxPxDPiTCE>zRI;^+=%(=k88ZTE(oZ$S}Vgfc6of z>acWlIBiPu=Tv8N!=n6Sl8Xt%@WvENRE_m};A=)ujdVke94oRkgkChVJaN{`sqO2h zd0N8tknJDprImYIs?NpyJil-0Oqf2|B~}r@jpau62z*l75f6(?6i|8l?x6XFl_MmnXO4vbjR6wWr>+;-`GgEV|-PP24pG$O^ zGPk`cc|?D^L^uuLeQF`V_V5QS^W}xpP8hSp6zD1)kl*MabJWVN<~)F5FnMI*EcnsnFQ0IDl+C z$Y+!FAH8a-3cW>uDEpm%rphLK!$QGYvPKzwX>klTz~*;9-(f1GO{W-{0af8C%@ti1 z`^35bZb@DDa>p0~=%sC|XXv7XAMJO_{P1&cu+&>l8(m5){hdak;90+>WeMT2>;ZYl z8|*Qz^VEOB8|rnM7PG4rDD#Z5SCu9-qldSxwYI81xGc{R*$CKxQq%$9Fp2kA#!f|+ zRYYi~mC3peVK#o@{IfJAK^T006k zCQGGQ5d=mddmF4Y{*P;;EHq(%_u1BVJ5iu?opqhM8=<`dLtItdo3|`fR-pb zOqUihGW2xV!?g+EX|*M6$1SAQ&I`p1mYX>bpkP?0YA2evEz^bILE)D7ZY#kafIj0S zRty}DW`U6kck@V>1J8kcwqaa&VXAhUzN9Bo^dg7w+4>ub)`NL^`|_n6DV3|kV<*ev z$lJTuZ}in2qM^Yk4G8Wnf@G}=<_4y|npDM?V386(3?pdDOx6)|i-#K=;NO}r{65LV zL8H!Qk@H$RZW0UxF11s7isL%DBi`1l4}fQJSuvY`jD~W#>2ytdPBI7b9VFw7X1Iu* z>A8oZ=Ms>9WOsUe82*KNMCawEsWQ_omR|tBc&@7z*qi2slF2Fwh4G87b9AvNU4RdH zU+?1^`QEhL>KgdBA}F2YO9RNyqSJ?;z4Wzz`S?yu{o&)|UAV!rmKblCBRNn|PdOhy zuZaU3xV|;yo9l@|vzUL%cQS$P~`f2hCCF1OI z7yyy=GooiKTRqeQ`(Zr;M*T;kspl&%L_sy~_ELe_!tgpJVsc+t_I*HdmY-O0eE_o& zq|@_nlIB7d`69~hI_0t{>L;Ir_YwlSwt0o4c?)8tlvGYM*s(bO1 zT>i35$%}UWq3kLQI8ba;E2@?fPEl6p5n_t6Bs7>|E1R}>GEfnHHf{w$x#n!eE7m{= zF)@y04XTIs=Dh4n;zGs8AHV+-UZ1B3(qwfZd(Q{nL+HnIZgD&DzHci};i9*o_C1_w zV{aippz24z3&A>9`Y!w_fc?eez#mngQ$(`YZMhEp2=zhTY9-|glt?tW&6|9|3*Y#| z>4*A_^~YcIwHo8b3bb_IZaYbLAm7cUrr0DSQEA?P-Y$kfE>q#g&KW9OJ0p@qHJo*J z%R-+5gG;We^Y5|BI|>SJdEMc|-QzKzj%flq>39?~e0)4^#N$#$U9r4U5l|sUm=o#x zQTCl|*ocx4(X`$puc_1xo?QtE-$2zj9;fmY^;;}ciPlSb`k&~fbS|w(@-)L0t`iOyi9$4PdpGf!UHsp97t$DZoGg0{{9zyu)|)# zj`lHL`^+~V?Y3~Qv82d-jq_9?oi%*Of=y8lqdqr^O;y|Y@~ZM7adOOIeyu;S24AY! zk^<`S#7`iCXbZNbB5jA+0U<0 zh0mShX=6C|p3=R~s#=ALD!bZk2&i?oRt_0l=HxM2-Mq*~BC#YLPy?UZ11 z_5-+?sYODFP)UuAaq2}zKW-1Y|6pk?i>5+71l%%(>t)GJ6QHcP!{CDj1c%cL2(%&5 z_>ln1Xp16D3ep(4QU}AroQq;>%;n1RXR#_pU4#MR!uVNJE(8D?tD^LxC%XpJcZqSv zQXB9wy&9Psq@AuyT5+Y_bEzb^)&?{x_mYOS$BBYSZaiojpk{wF3nZ&EcJ=z8Ykhw- z0m7S31|8#q7+&sp_ba4a)zSv_MS2c(c%{za(OjO$e(UXm*#h4ZAGYzd|3o%Q|3)KS z?qjykOb|i2d<%SoN$f7JrLu~KK2hVKbjzw>MR47rb^(Hyw##;r2tQ!+pI=HMC>Ja} z-o1SL;_aKq#|KFZsgYrWgvnYPM(m0My89R=JoEm|e?6=%y*f>H zqj>j%38-HBo|S=6IM44QW^M)}9Wuj_O!g`{tSA{#?9t{M9BQf2W5g7+_E;?^0+GjyPl+iZ^%Vs%8A7Y(}(Cj!mD@~IKKc)hX5uDFjEn8 z{Mc$Fs<{VsYH34x!=OWAYoUAlHb^gQ>hR=p!h{^BtVY91sduYCtVhkpdMp$~xCDf3 zS2x<&*^SQrIe|DeIR~kyG6OCcdHuJ%>^>Y}gjoU%Ce>Jg9SG0yy>6Iqd%B~nlfAnC zSog1CAfU6lSu8uA(h&s)SAC19aI-eMXvR6}$5J2&%@A&~N51@ZLB$NRX#hhxs;gb< z7GaOl@|fP`wfTOVO%6{K?K>*g45{9;!b*+n2`d0}Y z&3%@A1^q3TE|zhq@7Z=M_N;3*cb`+^X(|bo2U1qbOI`WR)3bqa#rsTyenmifg6Q7h zOIn}n3?V)3IMglf{;h5qJAXFK^P(d2fi6j?5QA8j$#G;#&=*3s647DEifC>xefH-1 zc|<|MHwbDuW+4qg4<5_g0pZPQ)9TXZmV{rL7!j~|O!N{gmf2Da=q=PlA=b})QyQ%r zX1T8>)F1iJyhhCX{DW(%hh{c$Ti69H)HiYYJWx`PHYRp};n~ix`H`&TlgtXJX3vFs zd7rztw7*2^D|lqAvQV2@r@FtmQcjE0-xpcu=&S+3bYgtEVES>#T3nfif0JtzmbyPw zm+N*L;20j}y#?lLMk=WuBGSUXqXPTV__R(pEgndk&UK1LkKM+RXlNj^)>+$hD&J5o zN{qMbPt|i0Ar)dH2&eCa(#ABxOXAsoYs;zRM2{pzT4Mc^wv(!NklQEeC|w$Pd9D|R z(Y358+*TklNuyc{)tF<{Hg?*w=lgLEKEFQN&*{h}q~JMQiMQ}}MEE6WZp9aUI+SI- zw>W&5S@i?`MQ*pM+~&&`04onwG`9B? zWA~2_Q#LIjtPrU{zDQE3B|bSM?2u&OS=5d9dfM*R*O6hue`LtsFS5D>-z|2z+P<^k z2|u!92{ZrF=wV~Q!4_AvztQ5HIbt;eze(yCkOF`u>^i({khze$h+LT3%ip4*6pZz! zGkPnRo(!2hW9_ku4K^TW27sKxCp>ta6)(1ARDxM#;G=+O@HQv5;aZ_NRnm3*3_7x$Fm`z zzA%$dHOHz+m)QQ8Su1s|2WZn*uFN;|Ad?>YD`7hsv+>ZOE`cjVOGej6+@tH$f2JU} zJuMWlmqTK^j`2A7`k!(!CIy>m^$npU_ICljYiHSgBZHQpnH}rc9Y+12oBvvUEkI~a zsFr`WK>`m)P~N74i~B!EPi7DFjEPfvV`e1L_7h^wQ1Fgr?0Is^0aziCQbi5}Iq5zZ?8C7Iz6~ z7swO`c<#1gF!W+^lBLMCtK(lSz2*$7$^G0O+wavWDF>H>jItbxyE72D*Xgne5rLqR zH>45nF-;Ji(K_*TJp0?Ebk8towjA3n3S#XVsvfY#zR6ML^R!iv;|7cqca0M)Eju_6 zFF&J7LB~*nP*Y8I6B4sG&c;*cEhGG$$|m+rPxiWU$P|-o%a<*;pl4G7)*nAr z=F4Rz-nZBM&GJcWvq|3T*8c7S-p_6y6Y~TxsYor~7A(_Ip{b7;Agwbw!OjKuaxreZ zL{g(SUXlu9zzx|hv2_?zWX{YTp@h=u7#X%f|H+w<^1ED&;yS=iaec3b>;&O_>f_!0 ztB>E`Nl(QtSABSreQ`Jy#UtQPBwX4E!~_r?>qDlpV^1s~YgIZ&?L+DydgGFGNIru= zaIm2A3ebA)gqp^58Pu9{iEN$A9WVIfjFkPjXDbMGe6J{$Hq|DK7LZMGk%eT;n?I4U zJ=#*58_*eUvM<`=(TQKvGNsz_v1Ws5av@T-=|dG??*oABWZlh2w7#E^50 zG)?(+w@j5zZeR~*Tkej0!O5{7By0>1L{if?JX_aH<-t^Rl+vV_Y3HZBEY?aSau2LT z=>+uMZ=&s5$bE_IZ)J{*Jgf&5swxI^jaDZiZ>}zMviN!MhafFIPSQrGI_ZoN>?;#zTI4o%$ zJ?EA~9yLMH)JrGbLS5=onw8Gir}Q6H43~lSE+!2GSLKM|XOz^OtQ9hv804Egwip)_ zs4Bh%R}#SJF^D<(W@fN|x6~=w-;wP9;eW;;)+JL_d1Tl-a(4!|-EEncnI;&Y5|&hU z)1JFqzUO05FdC=QB(!Q{cN~(%Rwf#2Q5Y;?CdRIO9ut_3FL9Jhau@TtB3xdSD zThhxOnl^bA5}GrZR7-ZV|G7g(EWMn4384j;LpN>F)L{w*;qhhy6O#BehIiUUf`ub{ zoe{bXzy16YVA0|*e8f8N8eL}dyi>bxAZTxTH@$G)^@t<9FYF(R^c<<_6Qo-A{VHu% zjr7Oq=vOA^wDZ7DBTEZHB_DT{hR`r%7_wBP?viF zWZf7?1axoAW4wOz2jwCIF~*DWyQMM<6-=$U_w=q%C6F~1lE>N}U5?$`2Hl>BW8&tU zgyyk|mU>O!7S^d?O06pxlJ=P3B+mUr2NQlwecR$IQRA-R>#;_{?O&f*&KXmXu;`(2 z&-SsJ&d3Q?owa9)&P)-!#(Bykv$Qq}RCdv{!?V!+zkQB-7ruc%qj*+?9+wR4xbT*+ z{zlzZvZSETW47(s)|}-Flg?tBf1l?Bl*1Sy@H`-expo_a|PXw02js)f31lq|W)Db)HJ#irNhFP+Mxmn@X(^VmHP zrmFeIAuOsyCUJxwRQWy}u`_0iIHS)+Ta7ve#5B?JK44&k7vu8oSIbVuL2K@ubPa0+jeoJ`8;K zM57pYb%HQ@Q0+eALLb-CWv)4hy*6$ zLJVI#lE}Ii#cYd1be5mZE^pmtnO$Ba7W)KTjM}}Xdda@J9E1=&@ZQgx_56;NGG2&g ziv)ji9-fy5`UXU?p&_AJ$hof2RW$4jV?|b)(U;iQUtz?4J6752#tA}q^4b_1*Kxpp z)W-}PJ00eR1ksiY5KjjpK>L&h#zQ06i+#Z+Xe?cHLVfJuEg4O6*j-CwoMEEx4-hS= zZ`kWFR)w0&rS>&dgz6JxX>m+!(15o~6;J&kX_#)~1Yn_X}*;^#;76 z%GUkAKgxULcC!%aeru=}m|!qUoq~FYyB5dB2G2>CteG&gJBAvY%G5o32@QgYkQ=+& z{I-PO8E@x%E&DqZ_Nzx2)9vLNGZ=TB@J{G3=Pf$Yhymxx z4fgePqJCjM?=AY_wcPI@2O&-1-mA8e4^_q9-Wv$GobK%>_ZFDKC)h(VRH-?adpvdz2mk@ac;5Hd z5OOHHIV?2Djs%a9%Nbnyc%IbAn(1V{G?B-{k(&jEqal~EDnx+*9?>`}8tFt&)>O~R z$*_?nyM*6R9*39?ny=G!t=nU6z(wK6nITVXe@#yG6?-afhrk+w$ZV^00}v#{PP5T3 z;>;?K_S`?ce)Fi;TiUYrhMh(b=qsGs<*lk>`#FV?jsq7Qza%5X_!c_V^z()?tGN!n zB8F($5fV}OwV2_0idk973!R+A^2i_ISIQ|^Qr9R)9xD9!gtD^58|K)>4&FndLV8#j z=?4XKixl=*lXlWoHeGOU=Z}vse^IF=&Muemh|rJXJ5@(op3BN{(^KI!?*O>^~`VVOvS@HxqZ*HXyxTzuo$(_GAP68nD}**UxYlL{M`}z z`b?-OxeV{sK2zxBub?7bLAD;1K!fXSKy-MWJjV z5YA-deM4SYooli*jIr@U1t#37s3|LxlPyhWW7kKJPW`d<@ zxxu(G6NTgUWP;;xP}s4ql^CLioov$s#$HE#lgiC}J`QZQt*zy5uROY_Qf7P-C%96S z(+MI;&O4$3DvHI|x8Bt-s8XOLAlG6;4|g%U-(7~EXD+R~N;xgH!%S&^$X5h~Kbs5fy0ISO?CkXN4>#Gks_c;qE7D1#`|$d!+Ouc;C}F_n24a|YulbM z)Btjv`w4^_Lq|L1@H&)@xp|Mm;|fB)~(j~@Tm z%MTB)&MvOrp54E{d~0?hp5I)(dwTr! zi@TqlJzRcs_V)Jkvxlpj2YvPC_UBKJ|0AEYA-}%7`uvNB9Qon?=H2=G&;G`T{j>S7 z&b3N&|Hb*m?bm1LPme#Gk7Ka2htL1=?EL=x?WH~Q=ku9Z5}y6=l}!EqT;$D_{o#B* zo|C^{T)sIM4P0D2J^tl<==RO^2U^mHug+Xf6X)siALc9jrNwL_mA`GmJw4JYe5EeA zueA&KD>+-N&gA|y%yjc6tn~EwqkMK49do39WEoG7zhRHQJ^%7Dj37pS^WpmX>G8Au zC|5TZilDYI2xPW8#Oq4{yHo1sHP6%x|x+-oL#T%`E8HLcU%!O%Rf8 zU68fb^Vf4df#h;df1x8sb@qdNPkj~c@$^Wp=0f@q?mi9iBw$SL&#QT!9{)He8bBHl z`0Q_<9)D*(hcN_bHr;8-!~=zv9O<`TUEV!CexjKE>do!7amcI2Mepx!|Lrf0k<{Dd zFXTmY5n_>qrs3`Bku+{r*;+H;WCJ`s{%^U!>ksb$qhS=Igk&h#=iSvefBBd0Cu+5` z9K)2UYc(poeScoW41uACf20?7oJ720Sa|sSGoA0R=IhV$6DIwBz9rZxp{G0vO){Tp z>^H}tYExlVACZQV z?2o!q@N!7-q686kKX>r{WDe{~Y`Qc!4TxGawEW>DQUv-Iag>@V*O67K0&Z{4C50nu z_Nk^(0(F@$8~9Ak?~DKeCbIRATEv<8#lwSyapJz1)k$mt9Q^+2k?8w4L>IZZ*N{sm z98Jwh{9^GxnT83;rsXAy9@RQIR$s)^T;G1Ucy)dD#n*4%y+8ZAf4i44ZohtWe*fnDLMjI;Z`xE)>a*I^ z)po@L2nTsDBUsW;C5C-)yzChBNjLZP9F;XpB} zrYgy>H70i>pyGOcb$$K%_WVx5pZM&1NvnJ;ODKrLHmuObc9?Peh{uBSQJ#171|x#$u~bc82n-``2s*_h0_( z?DhGZFV95dS2vgE5|Rq0#-Cc@2cEI^gQ7TwH~5f=27CfM#*U1OQSkYY%EbWtp|4%v zUw?RWsSPcCn6l_2BE#^WBoI$diNlpZES8|DucOqydDFWtT>I+q*H);DC4YEClVHXl z|J(f%Au~;6(r}Nco?it%RHaMI3`q162`eHiG#`%Pq1fN=k@VvB?U^h&RW+Lg=JjMgc?@yKrOv|dESWS(hjij%^ze&MiLP%h%En?3W z<+JS5UKdBGPVHC-jWSi%M(|+K)`#wRdGv$i(cG$F z6M|{@)x9Pw$Q3-sfn9$)=WZM>=^_4FlG$Hlu|SGC{E{ogBQAa+QXZvF!CVB!e0oHk zx+@xd$ZYFJ6@gCUl9ma+EF+^eOb{TuCY|jB3l7u}o`{PWTi!tYbO(zXrEq3=wRfrKT>Irk5R#d3psCq0i zTK46tRVB!t2%&MxVTSkY1WKc(x5O5UBnBlSz!<8?3X5}IfW<59M#n+A4apL1xtW1f zt1A=CRCyG?0#f3z>4?TpuvBnB+VxoMBr59e?>xBLO)2=^TcHz6*LEyMoro>yYObaT zDPJ_Uw5ClIHfN%@>)X#4717wm8oYmEE5aUs+ilZ-RcNKN3iH#(s&qmOp2+b(A2fv_4bxS{j73y7Vp*l&9SOL#*b9o~bpf9=#ZkqU z)#UX(y0Gxmlaah^qQS8Am7c&5S~7^8A6Q~vy>`!T)|PCv>20xT7N4?|j_`0;p!QY} zmi!`jN@k60fdZE;j3AscnlYXpe?P;Et`R$vK|9zqp^DzPO_{;E`##FvkA3Q-5&z%N z&eP+sjj0u4KYuIv<QUdZ_f z?ENflu+TANwixCdVrL&H+-#nXU`_#-2u#-4eK<_rHWXuMf6TH@GH5)~WW}lvq^t<- z2wH0I19LzFUW3r!8{YvtKRwb`*BpEbKM-U@MGZ&i9juQs)1h0^tjhBANSmH9_W*Iv zez9Ohvzl}9-h=l&Cyc{$zn=Mx^0uSM&a(WL0{i~{{8r-R`NP%u^-tyW)a}*%fN(fCm{m<5W$A_{tt;7c7lV5tYy)U*p{1Xr1Bu9IN=7%zP-E?*}~M7uPeq3zh0s{ ztv_mnL!6f5$B?~zp>BK3?wATRpDOM|Lj@O#tuY*CjuyZOlN6zqC*jygTRQ9#Y1-c7M>K{z@WpkklSR~< zp5-9|ooJZm-1a-ZlZ>TJ`emzvp*+Tk9PoD%3znT1Jpd|{sRiPQ6eHj&2Z)iL-TtZ= zAWtJ2RoCGx8%C0D<_ZTVTOt4fi8Fl727n|0|3^1A5#D4MU4ff}2rov~nxEE7dGv%> zs4VC~9a=YUqF27jqjdo3D-bQXmwVD;s`kF{pPfwRY{R^^%R}MS0S2T%1ynl?2#Mr< zRXYQ5)cHiw(wAVHol7nm%$`P3lu)z!tN972lCi~WvY){ism|A@Vo zbYn3o;bmucZ|2bi8_mhM&Cae3YGj;zjg&%uG?)N>L|zfnS9o*pp>1%^LwscLdCjVP z?i-h0{bN=bn97U3OFT+lyi;2b#tBUVh0fC8b_hoh9n%xz#-azic{s=16wilyXcWV` z$uqXY!Z$QqA>WhuW8f8)e+o>LoGE55=(ZgXa=h+e)cqt!gZHaW#F$LAov489W zT~%*oaCaaCd_!y$Qx<8VUJ(9E0yVj*k*qbNKb?-GZvfA8;WF>n~CZ%;-^iR3bV`C!!^lVAf z*{`mowXqMcZYKB-jIoc2VH39=9;HlRD0JJP4!3K%@&V7U?q1)0xc{Q3LwkFXB&LZ< z=}l9jL=_NS++X<{;lBGyk_cHlNWwh5O}y||qrUV(XBG-9C^35ttJWi&X3 z0~OU-CGb_FP|!L}2Rjwnn%?J^8w%c@T^+b}X&z&$^iPl9vP9W+bK`45ZeOMWs*l+$D7@ll*e6Mi)-Z8EOuZU8LTcYxRBtU$CA_RlhBo1Q zgmfDvOQ4X#Qe;BWv=4*#Jiqr*Gz+^mfXS;U(oqbO698c$2<{&{NfuNn%?e(Fx;% zWl7n-tQdAOlYtezU~li^kid<8g(_xHKt`reUbUVWl3mr@P-C9=RgGN>%fZsI@tXH60ZFArI)i)Y2 zzVXhXYSf#@)c2mA5u!Hwh=iNCYCh>W2LKNgHn zpE8Mx3T&CoRe-g%A=^2)QD2|-6XIZ`V0FYFJ)3} zRkjenlsa1ivU1bdhYv7}Gw0!Si^L!)A+Bm_<8patZ%EwFnht034eiBXQxBL}rVZ+u8G6=_ z`j+Iw2Tco%VqPIOs@=!jX7kR^ngUhAB%>4U845x(8QsNl5`!Xip_27|8MhAdsZ%r& zgLx=g*5#J-Wrb?KI}$kk6oJ@xs&+ywrgZz$n`1(;22*TvZYp(RmcdZ-eKE;4V^yoS zD(=KnP5_A2FQdp>giQYunS(QuSHEistGY-;ZEDuU(pBwCS`xOy0ul0RV_zGtk%8cE zOjPwnS}4;}*FW8*1^GpZJlgiV{!0WDY$rK41>rrN9CD~XK9VkIsq2FRVZ0=dVZ_D&zN<&uYxm+TZD2gfv7X8M(e<{NCg{CCe^6r zhQ!N%zk_L>Uz*>Den#802ikFmf|en~jF8pMF(s3;PB@`gbS>ZdE}wn6HT-*-C{N6K zhfW^+q@iJLayH9TP#6)W7|St69KD4};&PN1MKtb(%3`L0{>@+eTZO@=$G=bBTjTk* zNg6CJxTId}$fJT0-J=2FRs!Mg=A}+5d05~mKmx*8hs1BnT6}#N*CclksF`+0ZrsRJ z;*#E7(OqMw*$0!3*9@R`U{dkLNe;5&MKj6>OVc?z_5bJAXwAZ>ZRu&Jx4HuK>e5~} z*iL}aa$GsIsGIZ@;SH`z%~>X@sgR%(QH-5JM!yDo#?6^Bj(GZoK>E*96C~9NGMGoF zgo)xii+9)O=g{BNBaNv`sy)D%;l$AWq7PM~EtiV(7=~h&$3c?~s@xJY1IH>PtITn}Z5XMY*ugDspaj(ael#<9jQzM#^o5nK@mw3b#+` zGDeA62e6=VBI0TOlzh#Z<0Mu)+lr^pyaPrJztGu$Kqf+_YO>&lV9S1{%HGVgZ-uQ( z;&}McE=(I!^iwJJsWO?ZMXtzC%aOz!ew6dWm0UA(BN?9C6Gu7gOC4hx-~C#;HJinm zL2Duplu``qMLc>CP7~m>^Via#{w3pq8@UQ(IeBFRZ;{k+TAvFjy%-NwN})*~#K`Zx zDQ%e`3Cjx2JU!+eg_^Mh$5CS@UKmgi(_&IEmAW3ehr_FvRdCTi-&tA{vTUr*+F@>> zjKY?p9qF-JrtS~QtO5uMs)I*-RrX{$KD`hM@fCJGcuM+-8Qf16sctAqCPCA0y*EI~ z!*;%?#1EczV|Cg5Bc<)_i+=H89MhAH{eHne zJv7ksY4=&3jaZPx1C+o>KQP4Fg`|2{lSf3mzez3>5;eVjIJ>&JlFmw1Gg)gV>%O4X ztk8@|yfi!mMYWM;;qR@SzN!pQRNueZv?s=09iplueywOKmm-b!%&(`*=CZs1!B;&h ztNuj|pX(*^-TOHRNZ)e@C%)ReB_3dJ2@ImOX<4;ia7=TOO&dfTVd#xo{RpiNhSVKd zI!iPg7v9criLBR9wTH0eh)4C|nNFh4_X-qhTOdZP|5jE>*)(c{5 ztsjz`i1K{Dj2C_aZ>M}hpqYDp)H6_#n(M{px(P>x#=)Zw8_HNiH4U%OrN@8Dr1n0t z78=7$5mXl*+>8cfMf{M|{O(e8a&z|j_QQ>SrGaE~UYeUITu<65_N}TmgQ4TM#JPT0 zjcSjLguw|?9hqf`+o4F|G`p<4a49;XY$Q}qalhivc=_ZW4{-MM_vp6!}S3HzZaJSzIJfC zctkq5gn1mSN)^SFWSiBj$WtKje#chitvy=}BvO@qadBs`yw=-cDUj@h<#|QmYPFlG z9d?y~WhW1NaoslPq&>IR(6h?(vb`dCBe(-EZCxY%r;7woaDQf89!R+eGmNO@Ah&eY zlsCa<2U@5Y5y+Hf0VzwPJ64O8U>}b7wG9%s84(`~uRPr`8KtV?V-1!4X34BnPba3v z5H4>^Oeu5(>{$uw_)F6(mgeih@<$rsdeQg?4_T-;b(>AxWtz!AwuI#wQY}RJ@seW1 zJrvZ&5%aeFL5g^xl3Xpa^(Duk+&BWXHhm&>RF1Ut(Hgj3&`!pV*#_@;3s%)g)n*Dc zEjti)U}B4k$^pJ9))P?j!~SVYGbtf`*lDSQB-LVbycbQ%amDz-1!R4Jlw>FKb00gj zgJnnEnvcexhw=nr2Hv6%t1EhV_RYzeJ-DHi$UJeT9iZ)OJttLj2Uw_=Kc5FY77GZa>q zU&0LyMzC&aKs9beqDmZhhhe=-NEw&U1WlSR2g4qs@kp2O0Oc)8seV9QdfstpHmH`I$mtmimgRs?isqOrZjx?#El!C!cM(xlX?K zH{cEt;m{D_xOli9Ktb0)cj^#fo*v1u4ptGtFw|o*6F|ybdWhk(j}TRoxx8$k!#sSrlk4H(3d?7@gZ5x;5aV<7f7BawX`M&apJ?gRCnIlg zt77RqcYcQlSIUAZKZwP`ZMXSkFb}K`>qzBF>Fli4Lh*~mw;*vx;}6IBcY-D-IeSPp zyfE4&szvGo#q--FxFkMEfg7WTui>;1wWz!}t+wa+gbLCWM3nL1&~;1iLnYMejMt`+x;l<;o;{36wOy$Q zIk+X1){mbU^~E1_HcDI?btcK0&Wk8|B`ETb^iem-G1!J?qO}0xAx|+(N@+C^$ACANgX5> zrJ|;0;Dj>u_t3MDtNX@*8O&94<%|($v0A9EQ^`dvNeS*Pdl4Wp_g-y^w1@ z{5WgBH|7tz=aBXU)sRK5;#c{?1Il9;bTQrnr_Nh^{O`<#`2F zHE5M{JqqcRSBGpPhZ691&tFcEssh&LXk@vb5)!tCLv?kk7PduTj%SKGdAGAYQQ!QI z3uQ=&;UT%krEd~X#QY$v9;_(bO)vty(k7rGeyy*@@fQ3L2Ii4QBo&IE_ zS^rUih#*4trcgJ`pkZWP-AfSC3v<`wtuz6G2a{?xisH-x-V?W$mT@$ zV+#G8^4zr?4Ki^xOF%&b{fttBR-&ekGn$b@D_UP1Y={jmb{6ss0Lma|J3_hV4$>}L zvcyeX@`*fOp*TiUROrqc`^Y}FXdGUUpTk_XeF=7BnZL6eGY)|F(mFjYq#@GVvymem z{6$e>LyNR^HplFq_>5~+nxllE3qHE&YU)PbYkASBi0M&;1PbH_b6FGL7>QEcc%e||ri1WRXZR9Lgud}FwD?Dir7teeFYNgB zeI8AS#$cV&IXFp=?|29@kSVpL!KGYZ5$cHnvUoZpIMEaf?x>0`n2t-e%6KenMTZGC z4qre_TnNy70NL}WsZc#Iv1=7>!4O(Q9Q4Y=<$=a4pGgzb3bppFW zTT;o4)CA$Zxg3?YPe2T`uhLq$kQ|s1dasq5Ia-u!^RsjBqF98tT9Rs|y~9TvVBcs9 zKs>)-#CxD)I`vo5>lN<$pH@ zqwctW1P^#V^YidaJ$?S}^_Be`>#g)H_DYRah%B)VNV5;J@p#l=9*YF*|2+BE4cy#k zWEe*D*1B-J$Otbx{#v+n*A@UOH4vx=z@n0f{ua3TS%t*o$RMBjPH*`=Z5$t1dRc18 zBWbsnuiG*g^No6&bt3AZG%S24f!CGiMRCQ*yqpJ$qTBgTn>PI{_kur7WMrg?_Vu9) z`l9>6533^mCpZ5Ka$)5LIZq?08rdU8%O>KN@nFX=bSlcH>}K*tpbBnAxze-~`Y43# z5iMQYm{}vB5&ZW}<8}e+*}JQ|JG~nXAq@&IRYHht08)MahfMog#oJwLEiWOY4ecC+ zaXR+=?26RC$q1pS3I;(<;tcY~s45o!3+7rv@JlxEk|irWJ{8znQUOJCbEd8msz(=B zUza)|MEHouN2Qj6n`%gmra3eVAnd7?5u+X)G|N4YYCN>$T)^QTgKXTRIr5#wZu0c` z^@IKlE}bZi^=^^i6YO__9jY-vs3CVF4%&L^&VC%19DR-ys{FQY3MC1kl5U7d zXFgf+V7b3$jy#oDfOXrU?^yctaigT5U_OTqp~E6e62HtHqwDYXNfZ43-TC?1&82M6 z$v0qkXRog>Z!XT>U0z&$5DU~ck!QV@@K$|gcRR#@%1pI6=r5SG_7*K;%2jNNR)pWv zYFq4Wq}VmsXOgPeZ64X7l$C}EumD2Yq0Tt@!YTp@SDQvO$f#8Qh37(RBT!%$D|(f7 z4x`i>BkAtjo|LAZWQkxf>S66cAy1Dri2Qtu>yN+rF>Z0qi-GEkGR(9@O7-CUtiW9P zDCuKxf($Y20UQRkhx8)%wg-|4k@r`h-#CCte<{TpH~j@_kPIJF&qw~e@E-<_Kl|F$TBkwVli#WY@%6m* zuj~%#_>I}+2pnb=vEp4n1@MVd?(6H@+joA=0Oc#ZDz&Cyhn||ac3enqzKgY%l~A{S zN#n<~!o|py5N&^N`J|pwX)31!rtU?s3kHPRPsY^1fmV{avzQZ_=WRP!UietLp9izz zhwhf0)R3`ebAWgwT>ieqhInU#ecvmpYS7{$9FvGTMj0HF@U`i;T8j60_Vu&O&8@jI zKK$|NKYk<;jJCd|Tv&onOgD_^SyZ2w~M{&Y18Ua~opUcp* zNVge5b7&_D3Kg*wH`0MUSg$gkGs>QR7Uab22PF%SUnbdyHklvzIbdMS-%$(Ltob&z zGyUEN$EyGEjnB30{9rdO`k)8<0|O&USlC=4T5yU9Yq0(n-ZmTaQ>Ztpo0DA^gdd8V zZHQF2YfQzoe!{P^HwX^(Cz7b44na1fEFsb+JzQ+m?zvqvm^UDYKn#Q0XOo&Hs>tPT z8Qali;e@#5!O;`WDRtaBMiK^DqfGo|M4Rr5nM#jfuX5(iF@K*8GK)j|sl&>V?&%03 z4k3Tz^koluoYLnxRZih?;_qG}*Rm`_46)gqCv=ASfXa$Vo|kzyfSSUm2C9W-np2;@ z&1?^pONU8f`7(|VFmpXn&B>LKGVCY`NTdo^`_b$wB*ct8Hc)FURK=0dCjyE5%S-GO zs|);KiRt3&4$t^d{gp&NYT^v1Y>_}jUSR2#9%{v^p;Ut90W&xOQ`3dyC=>|XiC!mq zTqswi!FK73*gluv28W+qySF8%F5*`E|NL|5y-EB7YI=pPMitwEP?%xQU3CUx+b$Fct#^LTA|Tq9B3?Fh2Ed$J#_P#}3|Df_{n>Q^PCey_RwiJ5KP& ziIl;0813ni(r2I6|C9O~ z()7lsC5{Bzy#|92tx6R|(o3eukP**@I>Wefb_tQ_m_GME&2?-uo(F`}gO1uP8|u z=G<|7NJoAhx|{3~SqI^Qz-CH9IWkR9(oqt3^#; zBFXr{gG|pcb#;T*4oEj%m()UBAdUKx?^m`MT;_}X-P zjL|iiScI;FcG;12Xn0;68?)`Fr+g^MQ>)U}PmfIkay`SX!qHA0cd%$MBXN0Q<8g74 z<(^)D!T-ak_t(|CY^_9wq55(PTL2~NKKA-BMwhR*c3~>dIKYAI2T5M^J=Al-j8von z0ETKHsLb1(5KNngPw>g1MXR)}eq!&N($^o}$l2(Hyc#PGeE76>H06^IS7$%_@YSok z&tC%zm4zm_!Y6vp(d&+~*&zW8R0xPDl?qEWiN_m7wggpvF}cWg6sQ;&b|@=EM5PoV zy?f{mVP)QJsnU6bbQ2L>j)^NcFFQ4{nnJhDy=-TX@p{juvcTw+rhmoQSk}~25z0X? zY)$aT!KoN~*i5W!J?Q)U^IQ48;{4(2{Q9RCmp8Xp_m@AFKhm)P)m-gT^@Y&h&4z-v zJgHoT410Ww;xa~9`E_Oj|Ii@Xm#IJ3`R-i%(wyIj7_|nR?1h`g+UgkBNu)Fgz{;)^ zXC`-tVdTFHAO?sGl;!8A@LSLc1M7*x%ZtzDw=6Cnr1fzomb???Bi(GBH>kcJ&U4rD zB4b}P#~R8h+=Lcf4vO+15*HR(2mQo@yR0PcNYW@-iXnt3TufEs_H^7hZX;R7UVX8U zKww11eF1!Mw6Qvg!oBSmgMT`}} zl|eKu29Hq(Fa(~W`1p{-+}zF?<%XHAU2eJ@cVMbF>u3hn|I#r8n{IIz045?#QDmKb zR_o#9nIG_^40#(31cAi^v?*{3xdtG-dGc3Qah8wjtT}MHLh9LiRpt-XlW?tMDyn+^ z`Q^U@P$vb?@qMA1CV3}~P;l%j?bQtDd#6;FUV?UtfF-*1jCdq?P0xp!qVA)lV`?r? zOT+5|MFv{jsaJbsp`2j8hM6QED1|KdB!yI`eF$Q4>InZ)qI*1rhU6D0uGD6=Ic54WJazKrpChx|ggwRE@y#>)x@7wTG;m%{1APFbObizb)6*k@YF4IAe_Z=o9;6a3}s==pQEyBgu9U& zs!l$RRZQb#qYWh{Y}||N=DcM5JP~Y0LAH=QP{@m1t{pV}8Vf&p8wMR-J> zBT^AC)sF~Q zVK*}n`O$d4C(u6KPj>3bj+_-(^3#R~nyOqZ!EC6Eg7Fdc_YvXSwH6E(dqQ3*xqadz+sxa_e_a-(eDc~ zz?QNaaav#ZUo-gSK2&vo7R9*u5Ub^p%XKpwr|KUm210cire@;Cm>66!cSU3Qsud6H z1g=xo)vtZQwN+5$tZdDHjM=VVx9)Y7xd7o{w^wF z3|0*i>1kkOPgVS!?zj77u$HNrh*BpqYmaM9{DTcj6{b?>&?CXjbbwsa#qc16+whir zE;Vzof#rPR4!HEvc8B;Pd8W2fSOj9BIuC>765=7j+;W}}DzMg|>2{$kJLs#_8Q*bG z^xo>{2=SSC;elC)d%e5&6VF>TXjLF>+Xl7*dnjt|)+$T|*ukgx-QGRMp%9_Zpht*G zZKxQrQnFN}vx{UymAy391r6rMY04d;l_kFTYcaG6)wX(~A#GfKBgb1R@lbX#bJiu{ zN>=_woBlv9D$)hHGDXP0lq1oR!*O3d#vp=Q`deQl`*Q4G>%z>o{2*P~-KDllsB{F= zkS1P>UGf^cRXe(Bt5+69ZpRkLgu{?mk>1_eDX)fAGC4j5=qOLjDz$+>5e#h5JR!T! zXCecW6m9}08W#KQtVlOADOD|DBI41p>cSf4qGv;>VJv+|9h9mVTR(&=czNrFx~$t_ zjrs}z;#kxZ847kaEiqnRqf*${8*`Q`V=j4tva@(H*WwR);MjvGUUF`tA&1T_S#l4D z)=#J4sN#Mlb02kul)Vmh_G=a}Y`tRGh;Ay`n3w6t0bpZFR(u_+*6pRI$4}y9sG?7= zE1S}G&t?2)ukpI~UNa5ZoOlFK+agMUnki6+R_jWE5Ch5%zzEy30wf`?6-YP}SP z%mMsa3t`ng5&4X6c~}W{CY8mC*=fOou@KlNq3|K1=MiRiqi^O%^sCX|eRkX%bNWcmEInv%hBA?wM4J$i*rW3#eJPi8-?} zH6vH5N4x;~RZm;H~h`+#$#P?R9= zR#N)(=ufL}3{a1TIFc|@<*_vZlAlVjR_9t`&vqOUz`b8HnorC_^5%}sW}#pd?m$6w zONU}P(Pc1Tqm^)x{-gJ`7PHb|mO6lk-*(d9Ay~FOHtX}XDfrzK|FuwQtN4~FN3x7N zIjZ{)nT?pV69xgGTxN4Z>*G`(-O>c5Cs0XcEKq{|g4@CGtS5FBr{($6$Q}Vz+NZ~F zDe1nwx_-Ene(`tYMBCe2`6*=k?5FPtbe|E|r0?{m-Ipl&j9votYrP&z2m&D=jz5Qn zmt;Kt5a>p_fQ8qG11JQ$K-JzSt|b-8y2*KAIT z_E7d4Gi5T;wMhf>WNxN37?G?L(qp+v{*gAEG{k&29A%+(U%me)y)BfYO~~Su{*>Rz z@VTV)baLOHS_I(S;_309rqU*o`2D27sHJr0yZ058Yhe;Ai2qATtb4&>*U)jKx3YKZ zQ{I^N@)CiX8R0ZFCY!$?hJ`nQQTqD%uT7*F%!O|XdM<9lq+UHqOG&c z1H#}5U7c@+QtPT^BE8IpPQ8RFunqr>HNNPiQGh+lBHN6jUc}faB>aq8ErVOZIX5C_8OrMd}J=v)1C~7^;`p*4cfaFOHIF3 z18VvMdJZLP3S%cX%vy2`OA_jaCnWmJq`4^qAnEf*mcdy1!N#kI+m;+sQ_27U|3-Vh z{$6QS_y6y?lX7hs(>e`Kgfr=I#zN@py{S0{6UayG!)pQ&$^_Sf)Rf*dw#Kn`%&RPIEY+& z+9a4*)=Bs!T8S;}Jp4d8)f_fVofZpXroz3&hgh^{kg*e*UxQ?@^X-`PpB;TO9h1k1 zSYy1eU3Trx-+p~_fBx?M_2rq~hAmEhef#;+iw=9T6Ax256sT=J^e1{4Qo#8Rc8q;8 ze?h~DNo=3cJzUD6zq|T|?w|!8^`Cv+$-d<^IL7xDTBo);gQ-!=47)2RLe050(?dp* zlZkC%+?BWN)Wqm+#M4I+M`lKNClgjCGY_m(fXcQl@kO%E*og zW5@oBX|95O?U$i$#$U4OGu{`@l*AlLfu!IS5!=IR>GkDAgqVLaiGZ zc)CTB%Qm}?XX6ZAu4anrYg}^U%DZuYkaZXS6-f?-%t2ZGcy4)ig!sdZtWQdeNRoyf z!mJ9Z%6<-tr4@-S|K&)(tVY3g78gfm0%GAa83}r zNz`!Mf;pP&DMb6mM9+chOTsnB=lHwTcfSU4`OW)f11bbR2!4vOs5&_r-JZLzy-srP zZ~~ZbamDzv$1Nw0>56n>bD+YKZqO5zr{l5YgUA$6!qF>x^8^4e3q_y+dQIRZK-CzQ zefDHXbnm;B=K30)u$_*5wS#aeGe9lU!WoSc)ad|$W2IcJrM@Ym;9R_skK?!B-}Bp6 z_6%ZE__>=_cKK}{-$^dg=N8nuQ80#ES;!XQF*!fLnJnvx3@kv&$FMVwYjvvF9w4{R z4!*ek`pxLrE+&8d63hZzPY1ZSXd~9JT1}z z3eUnD?U)Xv zrY?-)2`U5sp$TtGpDKrD{QHdKMt+cU{PkAF!fa6Ll6*fiPS73De@MD?1Y*(bp5of@ zBbZ^{=k5633Yhj{{#=@1` zeR~seDRju-wRXU9cJO_%#xWLWe#5#W`V%3NOWb~aCU-*p^zQuTbBTa?8d$(DvMvQs zOJGF790``D@my{g#Injt5EBi>8yo}_C%z1mYI{42B{}U*uNPoc?*1|rWCnmDYL*YO z^PlNVOQa5WRwg8XF<|I`a2GHj(NXnR^L9C=h#`?Crqh^_^M9HDPcUd!QOqR;#g-wB zp&iWL?(u|n`AX26`AAwL4X873_;-pM1m9)-Cijc-Dg}mfBBkVm=WIRtthm{?%$T3w zo!?7Snuv6&FVO2gNQu#W7Hdd%cDdx2KX*hqzjuwVT?vZRxE||?GU~gw7WusT@|%Yb zcb5VfkVuA`T!QveNkj3sP`^~Gz!dGA#d8za?E9+PJiDa6T6}|f>w8GP|297RIu)rZ zQxkFY@VPX2`}e!~FZ=V$uD$KN2;cUkaCLFd&oF7o703w zdfzI-{G{0Sfn2oGDBf-~RV1~XR-l>Fbg8ENzKk$8F&-#E(;u&bZ+Q??t;qbQB1J%S>vC1SNc=JKWC=x28_r8pE@_?i)<7A0m2Eo2Ce+Rwz zy&b{&;o{2kHrIa>n%*U*6P}0zy`iEBJF*zWAS&xzz5buXtpD%wSRz9Lh&QYjSwvOT z3l1wWJ!GB=5YS5FEq9@wOcXaL@H|El%v!qUMqGZ2dXink5U*+7!5!VYM4g5{G!7{@ ziM6C(EWEUnMWLjzrGl6F8Sk!S6|pu^Ts1g4#BI#v=x6$w^8~iWH(5^j0}r|#D^Sc2 zLxR4iFLwiIYp*I!I5K6SKx+S%**q88#TzHRH4Wzdi@8EImK6)ORal~Ux)&>7f_icV z(ndcV*-IN6%YM`qh^OXOpu`bBP>8%Z=4PJ_?2f3`cjrt$@sun-yTB0SpEB6mgCWT3 zu=45<%MnU&cP8l!|C2exQA}F~w_JcC)vWB;dVfGJ96Kc$U3<9TMqDg8^P2uJ1K~TO%!| z`n=^nh4{=pWI1-OqqN}UqKk^B>u9F}sAPaxVW}$m7F6kQw6Mhm+gIWuw=?x`1d|V-3-}#n<)PfjAP{0juP!}Md)A|jZJ@KPCl{pcUk`#v?+Muxr(qo9LGsi@irYiM zzx>X)?h1vulm$-7uTG1n=@;!A#@JkqkBH;R357^rydY`31wSTQO-=cuKJ+%_ z5SDk6vV>w@exWZ`625-+qnhvx@u1Z@>@BuKl=Ck3?hLS;fqHlT4eu`Hr*Jl-??vZ_ za-KIj0gwjw1kf~NK>BT^qVRUDJznc|0IKWqcZ$j4wx~m@U@>HvJ5y_k0-adVebTET z-@4f{2Sh#WPga~+oNk@fkl;*|TLI2EuD;?n3y(fV2tm6sTV$gX8lOlc69<$BBqo|g zyu~qtDne60t7>}L8>00_?8mcIrEH~1av3nCH)+iknH^I>$+8scR~S4NeT28NYfH4{ zoWTjCOb!56sWdVgm&d)I!br?YKvW9-^XJ2I9U+hmvW~T8G!)tCql~%sn4Q<`vLepx z+i>yFsBUvg32K-_v#1g+aCHF89q^3QFNG77>GYvGT_xD#BBD z`%oc?A1#2EbC`kKnFge(Ef1h@z;5A6rmo(UC#Jy~Mdv094O|KsCLyFPL&3QeX`t%m zq?ov&FDSn5?svM-w$qe5<;4I?!aCI!qGb$Jp(xtNGv((whbt0s75Uyw>q9}yzS|T! zsv~Oh#LR;*#T3xr(t_48m+EFjKOhT!vrWsfitu;2a?6NQ`TF^>qW=jf{ zR-{nTJ!X|h1ur`eHg?a8x0j=v?B~IG!#RJ^_brZsXV|NQeAyI_huEl4@ACLWdmkCJ zLPi@}tq7qiblu_*i{BW5eI~0<_BuCXM!SSzmW>rL8DU}gPD<^G+rhyF5jV&L_*!pe z>tTW_wqZff3F(l{*w6Pb5(;~=h}wl4$pGYc?ogVm)}h3~N~)xZK2NO=0w9c`OT7my$?U4XDpcLEGXN!dQGv00C}6T_=zk!@lMBc*81XAJPg zkp2v43f8*j$7K(8T7YDM)FsTDHJ7xp877ofD0NmPGO}03Lm@+YQ;IvNCWA3$m|=yf zWCyLc1c-vk2Sl~;xD2-GX2rKLZv-{ZlprBZ!y(2-QbM%5dAg(G>G9-6I|+>b4q{(k zPQld(32-VHS>8oRVu4+8;%ZALVGQlr)~Cjd!^sw^jwxCe07tH!U4y+eG@;Xd^B|Qo zOuKDXb*u|vpz!RQElMLNH+jmh6tYVYA9yp8G=))&g2am-1%st~?1}+x4<6+CrN<7F zg=0hQUKaSXn$j-IiAP=FC>&0f=JZY%MYT%~I(<3c6&x5SX{C?@{h`^L=H8fwkJf|#J8}=n@68DD>9yy!*5fCqY^b7~O%t=1wQ>1HAqr|rrgpJ#2RP-Z zTZ?$)GLxIn|HqFw?cBcyg4k#55GS&U@KPX(^b>;@J>zA~^ES1DW_TEfBKW}jh-5bX zl2pdL?r9Mnu`24vq(qZ;R6OjhEx={iR);O_xgjzp#~OQC(Bon2jJP7fau~1tg0vr$K!?9# z9KsRCF#t_#qkxUOlKTF08e5KpY`NKm@@PVZKmbwy3YuROv&t0Jv@s5Gw5u`3#VUMm zO0`CAT2d}hqam9-0V0BPOitKrWD}X>;yR}KEVaU2i0}5Mp$Iha)G480K<|2r zO<0LlHhq*5tLCoA8 zS}P1fHT~Pr+de(wi(ap8m!|wwFIlGpiP^ZJqHE|P6dfIyQ)ce)G+#|%?n!d4SQg|C z{*tGIwxfHN0GPSTupvdn0TqL&V{>UlK_eaQ6eeONBM^fK-Rn>-tCYG(-A|VUh&sRW zk05mzkLF0oSjHT75v`@vRMw95nQeN=;4={8%wDXgF@Y6p*09Y(73~~Sc=Cn`7hiL^ zXpXRyq>~kZj1>A;BKd^~QQe{r(ejd)?t$%VjQM3h6?rjr8LcawKUZK^{&h)v83SPg z&4ju|(#Q~&R0mI%fgMSdt!@_8UJ)g?R<%N}nn;J~MH5jm{IUw!VW?B!rLtlJY@`|b zm^c72Pe7sxP~%aC5YM{H4QC@qh~X+3>uxr`HHzF^8rL++UeS>|WRuRFBJbI!aI5)R zT{RGkfIMa_N=gJh@WJ|mhq z$I?p(4Nag8dC1DN2uK#}ML{S=ANsdv;ed;QH(ryyG!uVzg4O*{($tYTt>{z{+RX2_ ziYqk;dTpV`&d=?L|DAq?ioz=wm=8rh7D>JDfz0F1V zk5vq~g=`KKE(Zs}He%h@+PO2jY|pqUS$|N1N*rA@`m$lXXQq!3K>?B0wvDtK%cR7i zwxtBJm)wheujZq=)ozL%zC&h=Uck<7GVS}%=f!YX@pQF zJx9*s3kfJOo&clWrn%p0W-0FV+kY2?9CZuSp-)dkvv_EpS&Le;=#DY02n=)Tog|1z zt(_?rCe8asY+gxq@BjU7X-hMwtLsacV^)r@B=YVe!BV@Gket8ysI5>e+;1pqzbU&E z8O`@%eM_$^EH~pzf?M*ik6>tFoW{_*i%ViU(F*~&3EOeHqzQPA4c9R8X@(&MzJJ?E zDd?$eDLh+5w42}(hq^S)IxrXV45Ge4>8(+qua*hOBlatb(2jZjXyh~5FoG!Awr2W! zcY9ISFNT7fAQiEFwk53zdpUz5b#o4&wQn3dRGEx($gWkbK+IMniXG}Go^_()h#CBw zxH7dV@4=ON^SWYU1Z8R-j#WTz(ZSMT3uOup-L9|`9|5wTM;zTabK>+buXQLhnDBIs zSW!eRf`PZ$Wu>-97_!u(t9l9HyOtGznqT`lUi-oMZ7Dc3nA4dDEY3WoY77pbZ7!^R zFMoNkWHv~cXl4$%)aLQ$1#t3*r67!l-CTmGA0)ZB>ZN>LsLWx5AOshM645TQiWjXa zW6O7=k!1m9va#!K9x!a!qzD&Mk5o8ZF%(NJi-zYRJ>;f`xA64WmcnH#jkqD6hu6>v z<{^RErOuZ+0VL&76lu{iLxiYr>8g`dn9+38A_)~g6yBQ;3oz4*1nz3{c1DE+=+ z0pTQsdMvo1PpAoPs8<+EQO)VFRmnW++2}w8=g& zDIH-8eY4x8k)re|7s<7maa_akRULj`7v*Kkx)Vivd08F+qxrrTizCtazAc4 zUNs2U0(^vZG>rboF4;4eesg{M;i5iu(gwqNtDSs5JD;;g1R1AcJiHp~vIy}>GL+NC z-{wD<9ASwqJ2XEKOcVZh2Yy_D1rsz2FhL!nq00)S4V4t_Hj%|bhKNcj)zOo_J}LZt zOQj+jrcGX zS6&!PbKmiro(N-S#-SN?M3WVRae*02Cc zfPjv2X#Y*5#O8ww&8nMc+}wBDoNMN;pT}zGi7K!VZvdpS^GH(&EE~UeUkRPiG}HDm zY3d~2B5&VJBmCq@2y9w$KevQb3qO}1EWhr7#}T11$hEYMpBV|EuJ!BfR8HKipd->X z!LV+{(82iPO7uN;=)>^*^!Sf6Qaq!((t}d~seaJ=MtPPVA5dT_1D=Lu?JBjw7kG@y z(q~rT9{G|WnL+`a`%c&pD02hYbWas{qcscsEvzOJ#;m(+1LOHRa|NtqZq#%&oMZl6 z+=>!k62yuUsQtpS9Ui5fvOpHO_bQYG!IPD$px&Yefoob7686g4z`1PeZ^@Zu5(S{7 zJm?!NUNp4m&5Af%C}F9Bh3phlp-*Z`ms;9%V~&k8wF5h2zJo|ZX33^JA#~4!DW%5# z=!{U)xPNgAAk)xpibjscRY4l)b?23CN}NNL`pKc)X#a3`C0E&BU;gxsPIIo8+Sjp% zEFl)^?w#*N**kO@s+t1!p-wa{1JywdAAWNrARj1Tf-oRY*n z$nhKL<=8KZMrW`^y}%KuA)?r(O6lDMyD_W%P-&q1On#q0ZtSNNel9&G^w37`FrQ6u z58^Ua!NIPTsjQ!SegFFQ!_6DvO#&dsi1v0@AQ49hHiAm}#lo%|U>D;-L^6>6oGTPW zeX`9^ooA>s+^{1edjnwX?nsEy#Tcv6RK$*D+y+7g0Ns!nm4H(|8S3o{7Go zDI`B*;=h+12VRaF@eF{d*AHw6S9daWuT))8`Zcs+sjJVU{#OeGqL4?OP|4DyZwudK>M83jCQHV4?l&&Yi97()%}?oHxiWW0j6(+oK6;eftb>Q*u{QCcw4cBL0v2Y zOn610j-IAWd??h`Y@UF5mplX6i?@`2RlOzpqIuic(gg`Q#4)400KTo$E-r*>3OFzs zz}R(xW?kza)K^7tg*E#nFEpwfCw3vOA3li1o@tnh*4oxM_;DF8xu#PsA$Ia(7$=t* zZc(}8NJlLvigXM?Ej*t(k8_^3-keH8#nL2xe~UdWn-t%hAFS1|5e=~TTm&#V_A~vq zfj$fDywFo-lVInonAq3eZ{@`s*kEu{t*&YT!YKDomX-UBk=FH&U&c{-qhdc488$%j zv_#DPV_vEMqE0RXt;_Y@k;?aToPap2v2U0O{N7)Ec`L@amIHUoR?~3pzGVPhQ#0cz0@5vF!08IP7Ksp+q|yS0 znj|4`slwTyCW>027qvjYw?2H6G8&b#PE_L!NKU=x9xgglZbBcYyyEGJpWrQ9CSC;3H4=;LWN^z`_XtR-x& zi6wdigR64AHA)u%FWiMBiyX8YaEbg6`mgRj$B=w z34`>2jn>NrN_8M^xvaA@#p?|QlN6d_shn(yqfB6+BCiV7J6<~nBa$!Kg(1&P#DSO7 zeh(z05=yaymF9VM5D<99G)$)eM4x!=;re$ndoDzTTK=R6Sp55SXJkNF>bk!N?Een*QB z^xjPAH*(?ME02Z_<18oory5ahVXerjOtySE;7C{?|RXpUO18iCE-{54=1 zw1A@d@u7s9vEDyDnbYNo2P<01rsRwb1M<_P$+xNik?*f|^Vm{G@<>0ccsg7;b&lpA zZAT=I12Lv&Vk-(Rl}JXZ1x41-v~OoV;tAMffBj2#zRix*ZZ$j6{Jt!cc-i!s;Ld}e zC7bCqOw(HdOB)~_8hqDt3xv*>uw>AdWe$pD>XZ+bih@7e-iCC`Dy@Y#ekoEa3|-Me z1g5w_WJ~DHbGEur>k5(GLjh`D&Meh(9{!158tr8dqSIN`)9S>!a?kB{KdjT7KT5p$ zbF2=lgA}BoI`B=7YPt%syMaYzF{@mts6S8>Py|!{z`Pi_Zp6^IDiQzt_U8I$qT4qg zbl051dB?G*3B+PeFje-FM2CS=cC`vn`B4BvHlZ|>-0!?xhLisOsh!}sw&UIE~VzuI3i_OX@Z{!*S6sK3z}m(zsmcsG}#bu^cgr96-rb4@#RABexlO2qpTYZV@#@U42eq14(+(IJRo*_+y0MrS_kz z5|ct1OX-<_9B|S(m*5;jh8_%gi+kDU!rB6R|9zQI1DwE85Xu!MBBIPe zn?Bvx9`fa&zN8}q1_=rPZDb?}OSlO|L7PMir!a0QgD`D=0;q|y;oyjU$u`oo+hwFZ z8I{w!f{E6^uF|W0wp5!BD7VXM~i)a`Czp zK+)k1sHJucg;kExFb2b^d}0K0I{8N#)Az0`6pn^uKf$3x5WU6RBQ?!Z+_PGP+(Amm zLJy`}@(f~|-qoUA$Pf$)l|EJ+;w(N7!a)i})(A%RfU3cl2zrMLi#N7hO2#)ZNFwu9 zh;qTyH+$N?Te6RNXQ(tbw#@B_4|NDnIN zThu?;0edtE<9uYsJsT^=S<}YsC}!dqn|hQHF4}V;w_9#1rq_%wvING0t08S@CtYBK zg=VHe9RsSj;{sA3?xK6xqo92_u8}rmJa~nH855~MGwDNRpJ%V=YX|38Xc7P8Re;dY z`l5YI>v$pR9=FHkd&*0hM>v)aorM}GfTi|4gh3w^BZe2?35xzfV+-FLZr3UMD30~h(tbq@00G`e zSXkpzGn_1^@BmbbIJUU7vQYdO!{XHcJQ;P;Ntis8xGqp&vX7qg)dY#BS6k!fL!B)5 zjsSsn@LJ`~~dGM>_Fjx%$jZQ8LC&#q#vh_nQfnW0{hHu)x&OQhfMO zuI1gQs3C3*$mh;{3qc>W5}q`}UKL=MRu`pxAycPY zzTWx$T&Gr!lz7>9+sm&7#A{{4!}Gf8bCv4U3!3{^S!JnQ)0zI2g2fzYk>E3Zg-q$Q zh3=(fu{2}RS`1d;gxz&_pQMOKwu@K2$juJ7`UUr!!znP)$XkagCC>JKFTm}^%)h(x67`>m;8ogIKpb%E|x3H3B zLn@wPUzczPc^u#Scpd8vHBO@u=JBxjsv~O60-jT*LAxO*?@R}5(a zE~UY+l%pO-s4t+bdyIY_V$lKBrhTFrT9;gKOcxKsP_(7l!oDaY?WEf#8q?>lsydu0 zya)SiFuEptk1;wy6sa_PS_&1lCYpAn;0^6=(_(V`@fy}l>0!WI|5(|P{OgkTjA%O8CB^xNrV0Qqhojk5Z)}dGnftyX3-up!sH<`pM76?00ux zi(QulY&$C99c@oOso7|lx>h!3B01&Da{!g6uIE3NpFtP`u47S1oQi}DTPOx%$k&^{ zAe-54m)h>n*16&Llx@UZ6P@9iVm2a!R2?3va5tMbS~4}VEUg+-L~`KSA?a!Sbp#Ik zu+92}7#seE{vSJi)J?mq5vgN1%t#A#W}@cq-jvRHw4Bf|2F~0==#GeDJ1Ca8bGI0; zqDolJ_G_>Kc&HVCfkefS;XH1?-ERoRnh2pDPJ5Y>d|kqI%2w8=pu1Cp3~c!k=*qr~ z)7vZUvv$fR=IbG-JEwy-dcBznZxGPBr8YICKr!$pxAd$Mg$&vpU6r)l5us(B9oczS zK!+rk%3by?iFLPK=SYX)TJmzpR{y|Iv#=Kq0YZMQjC#O-xZd=u*8|RD@=|;0=jusI@%z1 z+!ald^`Qdq2W5T&r>CL9-?OtZ6MjG&ZoTFV-onDbl%vLC%5r@yl+5WV4%aO$tpm9k z()Xiu&f$h%y5o>|!$B$~^M@(ChX|o8!JbcnkV)HRd$PdG^{Py@_{}=%3%^cvA0jBLNTG1Gz|!rbbm@e!SWnpGTWY~r^v-a z4p}5bfDZw`q?P6*;Uem4g-i=F_yod&%hCnLY(Z$%VscF?93>DzgN98TY)O6;^&^Ep zlTTXpO-icBKz(*Sz!5!=^nzh_3p_y>J&CHbSjJajekaK_kd9FmOrH6x?x^K)%FcQA zg&LcCWehy2YADGWLWM}MIz`xK^|i%dS|m~)L$@!UPc@(Q`_|`>+4VM0)hMf4zKtsE z*b|nfT^JA0D5@#-Mc;$;H(!kIh5T!{V}dG&4*3I1me7&zV%T;5k6_GhCb9hXM2ZCK z>_CwW2L{)XG;rU)J3l{reSLXz5eJyf#@DxBFHt2{0~M%P?GTwVv;t0=X?d_rkD3|* zEgzAc@(f!qH0B8oL1`dTLRT=NnTy~)Ckn}(?<@l)|BFRZl9Yt%B7GW%mwIAZiCE_6 zi0IU>p#><31d0@KAAyY#Z{jMB#OgdOgc!E8{8nLH_tDY75=c!uy@oIf1uyX6!RRAQ zX<&*a7T}*F9yMzHUu@I*_Db|aahn*^%SGzXq~#4H$C1#$rwb7O82A44K)Smy;qsgJ z@6Nxm+nMO#6+ZMnSgFnDRN}5;zxEQ{LvtzQ;&je$S|DIM^ylj!_nD81|L9}Ei}dUO z2ji4n&4^|W-Vq@RCAGV(BY~5rDC%#96+s%tem80C=29+qkxO0foY20I|M`qN1ukSr zm!pmR5suj3m&z+`h%z$IRXpD!Noq15TFUs)?*u(u6bYD|uf4mJ_<18KmHr4$Y*e@t zx=Tr1+m&rqvgPM%b`fu0GvpPI*TnS2me74}tcajXJ`}=-(nIAH9>x4wfvX{8IK#OW zqhyYO&6b!n4Z^YHc9dXi7vF{}hL}f^O>%0jML2R7wa+eby7KM$m!fTC$v8Xs*SUpZ z+MIsMOK)hSTASmxiA5e{&kX;uke0-i8z3(C{GKsC^76mtuDfapkUHo_>^wIZq-rz` zg6K-w1U6)y`btQpke2i9vX{V3Siw|5G%?T+88GHm3oN~<7_-WAEXqg@Z1kPnKL{c~JgAzN*+MF;4$sZ}>C0`GvO5Cb)QHQJCjg>n8*j9E{_3H@@LQF*-#JBCUpFP<6hM z(mIB*So1tedk^0UY62SnA<;Q{3QZq2Q?=caF*NUd5e~XVG#gs3iJa<9bdP#&7*}xjx13l-rZ|L_bKGVCqwxG8-O>QUd zimwEzxrHg|Os-o^|Mu$a-TD2O`a!IWfE*PgXuTK?2o9nSR{}Wg=<#$p+>%d*qi4xL zyDWRqV)oo)^Nbtbj=%lWWXC;G5jJ|kSB>VAE8fFW{&lg_SV*K9r;g*q(4MeRRX2t! zjyF#*T`mGJ(8ETynUQDlbpTc8IH_VVSL+W&TPjU%z0-4PS$y=@G)-wPb^iKZPL@dO zygjK38BLveGp>|tMjn=X;8OkliA2##yE)FAU-oK#6;elVs*afUCbfrAfZyPsP^GaD z`NVvq`Drw3$UF1Yc(~fKQj2<(iN$%=)(22*jnCnocY9Y9u9d*>h77 zp;kBGa*{lr&ctCsR6OCXgn>{eDSc8L*oYu&ge5*fY8SVf$M!`oGiMTRLuN$L!Qtxv z$@d24Tk~hp<7B7 zQYev39^<6_{5GHxe(81$bqV>p_xGq=s5h4wZz%4Hk2im}d<5Tn6K6^&@I>k;U4b4b zC!1!A6(b|*X?%LE3b(gGvEtgwb5rvoL%#=LY)JNMQ31-k2 zW%rCSWg1S(y)=`f)IJw2--CnF7HL zwCF6^fY#c@au&v+v{(t`qcAXaL&i%NU%vhkA^lnT;9JXv`!Am!fB9!0zIr8>;Uff4 zt6)wPYKcWV)lt^o2)rf~KYC$DVdRaAW!m7HO4${#-VVa}%c4!s$De1CiDHSPq)UDQ z9)inTSdZ7BnI%w6H9BnF+{AIaM;lbk2MB|fK5Bp%Wh*Q#qAWeQarN|D?cMwR2ncV) zW0m`Lrz+AkBEmL6m_tf5+Oi1!47Ikr(-J&{!RI&E((nip6i7UbMfRrpTq?bJ6C&)P z9vnOWq=Ly6e>i#3YZJ<|C{u9HC)u_^?vynF_=S0iS0YJ|I(|li@o*yBSsJxDpkvpx zolD~Y7qtO&$2;21nu~y8{vr;$^w0T&5})Y-^VQ(5K$_Kwp#IE|;%|b&75jcQAbJ>n z`?ziNksI!<;P!L5YhLw%9wdnBT;+2q&8eLUwoR0@&;;SHOru6ai_-ge2S9tK2n^k( z7o1L%tgB>hUU26ZNlVBQa^JM7DNdu39Btzv}|Dw0U~d5D}pqr z9qp57)U-o;JsX7aar+1n*eN)Jb8UZK1w6I+R4f5SM| z6E4O*w2{i+7`*hHi(Ohnnw;U!lFp(Go4mz@)E~l3orACkn-02t4s(Q|iVQdFVm4W< zINtrg-|Z^b%+4Spg%60B%P<~uVzM?GV6W(qGL@D`7IbG8H=ZA`srkW=)*$(og>U=t zXd#LiafMMtXw&1etsL)-aH;b~)ndEXx}a#&e8j=JRE}YR&=NCaf%3mzn*Yawx|Haa zWbP3j>&YykFu>&w(*)R>IDOaIfkLd$m2hw%Z1b`W_v*Uq=!`})Qw8;mLsTj}NWQ+9hWq`%(BD6@)rg)y zG$HUbCgxqmT~v@-5M%BWj^JwdJ+p@$n_O-P)QwH$t8PN?p+A=?gaXA!-2F|>1!UKn zV%oL4WW_r=Rj(NNb7nd|jb~||4KBA6gzJo(JVeOYETC&DJ3H&V_4!J?Kwt#KuJpsuGXz@WQtxtqG&9;V2Ng(zutw_?e4Z1wSBoqI@n{fDVeA; zbk&}qBq|m@_(2{A%&FNiwc~t6{kWZoYTqqB9Rv$LA-7w2QUv;y`unYNa?O9awc10R zEQrI(+$ADo8Upw^CsK_$N$3X>rEO)qPYa2e#v&f50wi!#Yx7{7O1)IhEX^{3kk_J} zv@cEsta2%e|1elpDW-=Yf=l7?9vqgYWe`bT)f87mqOY_(FKWn^Zaiu`GwthkOFSs# zhY|+Z#6<3A&0n_hR8b7}Q60aGfGld@@sBu)7ZNEa?s}lHkV=|56(is%|6)a_qy?_p z&YJZm1qjDSpwa!9>BnwMLtY_K?vQ`N3fSRvbFi8Y%15#T^1dRoC0Rex+R?ymtKHPqK{Fm8lo3qF8kix*t z&Z9(fvMIECVf@CY-qHIShwSMX@d^qd_Ux#%>P6)=U7oIAVi|oqE?6tw$DL5uMauR^ z$AZ8Rvemv*c8|Ct&QhZ91BbQ~{(veuv7BnYBYJ+65-y9$X zV(OPRl!iP8kCZ*QQ`AVO(NS=MFO0S+ix`7~d1%^Lm$;q--?K!|gn|Fled>ivZKV9k zU4a9FyJTq5kLx*o_l4C1La~D=D)Pt+2SCMg%o11x=}rQKpHuK}b?7%ohR1}OBD|Ds zEXYt%K{A^Ro^w%hF*yRWlqo!yqx*JJ@TEdCk!g?&gr0uM8Dd$))s67}^0|6n@-s(X z!~#vhVg*t`AFBTrlWaQIp=g5zhH*|N-cPkxg0?tlt~a8U_jM`pC!6qFWl;ETl-E?D zMp%&1Vh@lRWh6TEOBWX1Tt5Dc%Tjb>UP=Z_v|vbTM>MmWFS#z~XAg>XLmQ@8bKuNe zjYzO>gw<10Aa=kJW5YKV)ktoo%u zNH6!%GuL6DTq##%L$wy{B!$hCj%h#9ZUtKD2&gHJQL%X@|`Vz$t6_f{`=}QK9 zr|h)DtUAfT7Zr zU0v3^`d#2D+KvQXmlpcxrOP_tlQ^Os4E)YaaA#>z3;=#VWWM(^$ zSbYPNXm^f7vr=@n+W8y@mKQT?+8>(3(NJf+pPi7q1gwCMf(+rjR zHaogsEXCd%E%u`1qjF>DmJ>pgm69!gA#52EEKQV&v-x=X{7-gH8vRz3TlvxTa#I#X zg|QM#?-4@Kt$xX=BSCqm89#jc3>e275v~c0vHD7z!NoN6R2eioB@zJR^To^8A7n>d zKk~WP^v*s>pv{OuHJM?0bU=r%z9*etK#b^;I9EiqVBq+jBx1g3z-~*aWXSHgw8_1L zPdE$}VXhr1Y}-u52GA%;J~f(zsYJlq8qMT*(mP7@?36WC3(l)59M^j0B~`k32zd&) zi@gt;-z$e=Y)YqxQy^9J>jd&sfSzc<*9#VYd%9@(BtRO}QX8HTQM(t4b;sP)-cz*@ zSRXs3GMRFQ0;*jn2m)ZSB1iRed#1w&EEyn8;{lNcivt)aj-Qr9K=~``PW|VX(AlB1 zauY7ZLWNlw2u-=3%$rzo%79~3g7p0BFRmUg#~KRI7FdJ-{TX9{+@Dj7OSal8zU<<= zjWn^O<2Tt_dnGN&Q=0AcLz%_+Vt_-)LAj@6XNJtk$#k3qOCMx5L!@X;eSVkRMRsVjEYYD1 zoQDOh!P&1G;1e?BxPwMJ3M1g7jEj@`9e|&}o>$k`uW!%qgvuzG4BN0~PL;-B7)r5s z*a%Y(f~d1~*$KY=`O=Ig6b$h+S&v_4Pokk4qPnpt;D;w}r1N%31$=^qVm1^{$HPeA zoW$|;40MAM6x@{dDxPbzIaRs*4(C#XFa-{c0>sd`w7OISL#K4Q~Am1gY z)aMXa3j#xAC`;x?83ykmt8MWGZFs;Z!gbHl_g?vJdj6?45&a^CYYcj#&B-Z7yh=K@ z6X4WY3qS;4E(Ll#fZE)VSYNWC{Vo$eUjl;xN$_Enn5#_gY^?d|57qPsEsl4W7gu_V zJr#$W!80q6CIM9&p|vVXAdkPIDvmp4w9vS_y_FfMjGA`v_sI+%Ux-nUW*1#x=I?iI zmm%MZG<7Sx$5%7NGhbc64y39<=twh>4&dqi-j%O!CYvt{&aRW){XvGr9)(cyrN369_KUEvI%PtPP zO77Y9jkV*cihcS?6VDAuWW!t7YRNqh)sThc$=r9!82J|wu+L!#pbr(bDpI3UTGfo` zlDkzTR;v2GkZ&e$u zgLK~NQ1@fa?iR#QJ92FD;Os z28&_sN$gBj!y@)T^CVb2jT2$kz#xYiMw?Pnh*UDH5-UdbXh7y1N;9es{?i4Pw-_}} zeFBBJEa3CI+YdJv7k9Vs@12WrRAFrGICm`kzX_KT1wiSP6%KLD#zA{&WU4pE8@53A zwyKIj`+S7k=%T)Fv~CEg2W+K%v!=R^P(~9QV1I#Vrt)pi;=_wi1MVMLTN;TEz z3$CH!ZfR_1m~VeH%D2v4KiRJzw8>4tw|9QDpXxM!fBQvemo7T3>74G3;)6g~_0j>* zwXvYTW}Oyss49rP7caL9Uf?uUn8K%k7|)bs^BsYw3vWsh6KwD0#&q)=GW!xbZLCxXL6ZRPY`uLDxv;hjDf^&8-%=( zw^%n^eyO>JyJl$8{DC6t)DWAe-ZWK#$J+5+*JvK-UWShWhr8COFa`QMJxX*)qw^7; z4=1pv;1HxUnbQ+_vg@TF5K5OXXBLag3ESNJJ@|Q0*z!behzvl54G+o{G=zvoLL@02 zPWHG$qpmtT(P%pueVfJ#A@wcoQc%;oO>6oR%PKBrEuQyITZ&lWdvLsou;d*Frbx!z z!e7fpf5PF9ZE~D!NRq?FD|^j6fx5*g8tAys>d}#Sv7p_@ZPMZ>FXyPuGTbVR zG;@3)>V!MQV%6LG&Wtj(19k zJ^@wA18&AL7?YCwojn4Y;ohwYLJO?(ym(e5Y}#z+ z0eD7(P*Oa(B>$n>@}gRw97KpS^5eGE}8V-b>$@2ypaew`ZhbZaBzBOs;$U-g(_>^K+OY^G49m>@hbFfXpP)IIt z=On8is0%v;)SLmflz-u95T2YO02sOsp9Ede36SY(NFTOmpkxzC2k@UPnZ<@ug#6tp z^yHRqSOY?adwB_icFW!6^_vf`FZEZF{p9g-D?*Gir7xmDW57>G#Yq|YSoPt|4H6GV6QlZ}<1-w`V`UyS(`D<}!ZL0i+V#j+TJ(o6y3N9PG^p zUXyjdWRqSns}dUr5J)$?QOit(znJC}ic3`$)*0bOo>ZC89w!%Q?&hF%@on%OiDg+o zn@aWr0kkvU25$*#>gSofy5~gov8w~Vf{lFhU)Pu6Oh>XjYC_6&B$|3kK(#sL0o27! za6~`?LB9B6pR%U?_xJa;Y>WZXiAaZ^ONa$GR?)y`BQQN*f|6G@s4`=heL2B3)f8%gctL>S zdD5bwZyOE1P}UN0_9MGy+mOg?s&hO^@XRaHgA%C1ncH9yBbMa;j>o+8C>QA~Q}z02 zuKH@6)ZbLAeme)@BW4U63r=FWhH5N0tH}-NDfTH*nA%*1Myw?l*nJh0pp6+em3Th0 z-lg%v+hU}DF5qdm#eA9-gR4Sg3xO$58fhG%QipZw8g)C$U;8=#tZm)bw=`9YbX#|l zgvaQlR#*@XPhrx$CI#ge@o3=`rrXR;#)~(%&mZO-E6NAPGkF>@!USKFCd*%J{Sa+~ zl=iRBYRUz*9O~{NQDZU^-ZO{DWqDZ_NSWbWREE z&Rruc#@abzwbNYVlLL4yO%R432}(A2Dv%3C-HK+vgHaMbquWwpJ!45KdC8b^2;y!b zGglFTep)=%lfz&ptljq5EL)WbW$Qo_;^;~tyD$i^F87++eUP1W=%i5yvhl@^ow~13 z)oV!n`R8|+=MR^1y92f8_bYWhNrYHlaLk1$&`FS)?Y87^XTxzVb+6W4QJX0XiNhh> zps17KDdw(*I4uz(O48oFV(g+Egl1ox#z|mrIf}g>df%wsYkKHUf+ksfzJ!N2%$vVn zH2kciVWpS3QlL*xj9>cwzWsJo^@I=t33=9$-Q)+)>_Wa+mzzh=^ay0lnw11*kqSRu#J z>D1MT%mHkvS*U$Bh2|P3ngEo4(t<05xS~Ww)YhKP@XVzBFi%EguP$)1rW6(6h4Vcd zDC_r@X-QM0P5u*~su2eStezhKrw><$NOGqbII@69))+=>IPw>rnW%~D*6{x%0Q`Sr z6s3oDH5E2!ya{N(-<3TwodeGI&xXky@01BweOW{6psfIr2G(MOH)osn5LyT?pVF!W zLE5}v2W!)R^adzC7U*{KsfE_F1W>0lZ+zp?JbOa*6;abL910l)rH?pE?EQy@!lo9R zi46`Pq4J79>D(GqsGOc^l<)&(QK*WiCQKCxq4k%>1|R>U4n74CyqqD&+$k*Hu$A}9 zIoSd_5q(f0Fq|TTO`Q3l&eQP59Id%~juYcN!XxQL`}8|5ZA(|2)6C{Ven9H=3VHm{ppT=l zGIpTN##ohuQ2ysqFHA|i$?yIOU!=1T6Fe~khH2KfxoDHRU$&>iNZXh;+HG+d%ZwH% zqC8|*;)^4K(xXOBWs`|3v?ANZDk=ZiXt|-NatS~Kr(Pg;08poI>{el%{C>ik!kHu& zl;SnzI7nf$zLvFc)ty31i0$AfpW;yXs3ENtQ^6owx=1zI1aO42k(-MBJ+CHp22A{E zNIohVSmA&~%Ve?qnCGvKwnt9x^HR&ap-xs{+E@;~50>-fliG_|mA_7f$br|uZE0%>*&)F5-`1s$JYWUrB9q;72?OEEn(V6_o2XP!#93C#}?Cx0u*pdRds;Edj*@(n_HeR7K_60s~MxDfix5oWnJN{6v^hWferVcLWS|x zWXWjc!^+htQ2;q&S_rEGg$5mnu4S2BDKL#kO;wniGOHup>!Lgt+cscGKj!BKslcjIq80Y&n{jO7GzR<`fE97JbRj>=_;xdXvk%{bB0v!mE;<#Rat z)y}jRMG4mB?o^VQl(~%k1=%_ zk-@beo#P#N1GPP?*foM9fS4f(X=A<97ZpZ-yvsN@=Wv!Ezo}2;gzdLKq9F;lnbTll zyF^P1MgJ~k6Sb`&Wpmynja0lJ!BoxK@PyuByw>=3@-RKk&W@TlD}?Oq5GD@6yt-`o zO`p*&q{4}^x0erZzUcd|MuNQyY)RD8YQhJOa3lMj)vs^wt}pK2pX>3o?XQ;l6;^b< zV9U`GPrX@bejy(zj^>xB$0J0gCOjXGFy>a-EPu6fy|7%L9c!DE3rjIsRBG#kmo-e?v((I+ubfDQNlnKPyx;qDDLdCg_7|gb{+e0(iElgVO}2^kIB*&o2IxfCvKR{sWjRcjba2joU_)=e&Usul1I>>lTBv^)o01&vBJS^9ZC$Vfo z(pa`d9y~@&P&-bAD?C*Gxo~?`Wl=G2bMMnm8G8Xh76z2;u{0aS+~5z*CAcEn7p)q3pIDD z1YM+#Rc*rDgJ2w>NNFuqwwa!r95N6XE1F@4< zbAu1SuFgZER0hsxO!v1-P+SXrS4Ac>?qc(h%80k_NKDrAhhzx*4Q0iOZ{A3G@Dkn- z^QcOrP$pqXuejmN?qy#xG^i!pthE0Ut4^regdkJzkA1khzR;hrjz=vm$WXvY^HX0j zUeTrR#QY=5906@dnwv5sivMqnV)dEhi=2cY5VJ;P7xjbBh>ZUK%C2q4uB^JgLel{v zNC+qoiI5_sB&Ebc5sCy6LVQQ7>^ki(Q7)S*+uiUD{lJ4iIP*5>`nN6t{jZ%tBG4|?< z#MhL1+DGzrMzRy5s-dmb5Ntt(4-B(|85kl`Vr7Efnyn@&6vr{q)L;z{bRec}4!jGV z#gbfF@zpE-YT+6*b{jYykQ^UQ4SY&Oz}(rM#;E zFzxBkPZO?6>Vhin4x2o)b`CBbmyk$!yg5+!YJ2V!AQG2u2w?Pcw-k z)Uz}e!_h%{8FFzrOjEAvw&d_hsf=rXV|Wp2(Xuq}7~f9Ni!8_ij%`yqLjS(QVQmW- z1oeIK`n6^va|HDgSrDm0I9RW6*1H=}EgXIpBf-1vLmAX4f?S9CD#4&Cj45`wtE*1w#Tq=es|M6_S$rW@6EiFccqqNJc$t@@? zDdL?77ue=lR)s^LO z6vm*b9N9>55$!Gp7CcJ(I_P9#sPrmN?;>nv&mk9%-15GM45jZwGJQ;YO_;P&;VEuh zK*D5TD&j-~f8t_~(>ZI@5j5}cP3ngnxJHvw3@(AM_G^(V{|3@=aAU1i_$Z5Tsdv5; zA?zv)3bIa5*kg#tK#PFWAelTY7_hmQX2=w1W83w9fQjX_L6|>H-A~A2dAdYOAULVP z`!PpEOxlCDkW9+Q?{G>@WRNbL&fdj_^k)ga!?e<+Fn*=2@tlU$FnV8ACW(>eoc0=4 z9ffEHd-afqHn$N+in3dC*1F}zx<+|E+&Z%}Y2)p4WNlE;fXyc8{ zdSFy6_0wf1Eb^fz6dlt19eZF^>%oi;Z$wn*J&OwH#^pxg_RKgXR+Le5ZnEi%Y6i9( z$2I2#L>Pc>`$f67f@NW~D*hsnn-^_&oE*5%QdLhDSgsr1M`;gq6&7Gt_vvrH`u2Yg zjcQ6rHGl?KXZ&u&y+iq^H3nLKi0SDPBCZC*!H3vx{ z#9@QPo3@-2*#~7vCZ14&ir;#K|2Jdp+04DniT71^^}UoHVNB#hsK}iF+o0oL_WDx3l@<8bKW@}i=QN3IsOh#b zmx|M1q!lWMT^N7XDXVfamu1_j$}F4IRxHcNt$1oHk%IUSsbpnEf6dbyb92(=;};Lt z_pjxk5GfJ%=%P%VwXsARe{U1SRvWV;EQz<>P>38c){jwo%MQmq_r;8+w-nbKO)c^jH>QUP&Q( z)dX-uqD|%b@tCnPx~9HnZa1MEeD(dS+t+fSaGuywFc7MYAj(PMD^3R5gXSRAGBBmW zt~03=vVWhzVcd~fYh^t1V`3osiMCWnB(tKwLKgqWt%C6#S&_vso$7-YO$v9D@;#{mR(fecFUK@ ze$WTZv(2R{Q}>Xk=r^#;nn?r;kW_fySg}a2^&e%Rut>!5KJM06jha~v{x_X=tqV)V zbdn+JnSjcnPoc;3=vtiS7DA6(4@kq?(ZE}jDY@B3Q!<}{>OqWBc@>N$1tms*SW;{Z zaohEh!4QN0(VTjTL(zdzi&I1V>*deEL*>AxhXEEk>|td%#N6EGV67p{4FU;MG6t7q z7!QRdg=lNnnDsamEWmXAWK2NDN>J^*MH*Y zt)&Oiu1_=g!^3qZvT;n7aBFJNg{p?Cso_5>dfwDsz_M0+dw;opxO#Z~Qglt+4+Jy| zZuuOQ5OY>A3zY&FoQ60FqedeT<74J(4AGGE!`A(Ak7#5HgWlSvW3BGYq>J*a+!|IIJ=BeGBt9*Y70H$ta@0?8A~< z4^U!XQjj}eS%o1q2bXtTc^i9K+oAi`un%i$f$_SoDgUJDODBbsW@MWB`#`aMKb1#* zfC1I({h6+kJRE|=d8X7}FS?kY#(qNuK|>WX1sNyR2O{~y47ON^__()7NGGB*83G1g zYyhDA%U$|N{h(g2m^1F8fNRnpw9*x-8htW@O6eQh0y&C zTY=Mrt&YICom;b`T7&95(*aw~GmB8kVs!hCNA}*9E_4&=R^Zp6-5Gsmu|H`%jCMe5 z=jtA4-_LGQSa0N)0Q|*E8E)Be!63VsHUxOyTnh2K9Ml_@YtZ)^2bO4hH=SI0N1QRf zw;M{cG}~`S`Q?J~*zQHn@>9GD~U-=TDNMbjP6ooz;BEHU7ye zZHPN^2-&3dPYZ6u#~jbVf~;=aC~Jllv5nHXp*TW6f>p&NbMtZIa=Dsit#wtmVcXzW z&N%<&!^an5i%S=J5w0WZp5|#viF0N^B!v;Wn-f*+GcqxK%-SBTEy0nWIWiNR1)ECP zi|C)d2rROqmD)?=X#*Afxr?BaQsj)WQV!Pu1y%U^mnUHMCtmCoCy zG7-Moc2e5YlJa#XL;%>sO!=$$xkh?l6-$fs=V!PU??;btJnu=Bj6q^F^O@m*e0bPQ zI$VZ5lg!Moyj~G9)CL`dem5iij7AVQ#F3Vx77|BSM^A5n-JT4GAbZ+8JsRAmJ_}g6hsmZ@T%*3>mduhs z+UT+bKu!tx*C{9qB9*w+EO|RTXl=Uu@EPRBKZ&aG|E|Zs zvvFjziu_T(-$pGo;%3zH!*0mh^1ZtA39^T)>rTs`ITx3gA6|dFeY`ULx%HA5%mzYe zNxqot=WAQ?^VB4{kd0rXHnpvvldf>i?QK_WzKB})^++r!b*JmsyW z9fUWa_hvS^5K;i$%fu;-f5GxhHDFRC%7IkwwV;^4WR7KvmIEN}<(_3)AWX9zWndYc z#xBiPYH?fBC3|=h>+60WZ*MMguWaZ|1hEKbKVgc>YG~uC>BQ3PSll9O@)t!Nq5Y^_ zEeD_k4Qla6+yqD(c%&>P2^&F)5D>5B!`=WQYh9j-2zNlHPv|32?`bc?RGI{MO+5=}d&+{4rLnQG|1sdQrVNgT*gSdr z^le^}XaPkwu_C}U@tJ_E6-9|LbP1%*#EdqE@pH||<}FIm6mzqt;%+BPar+Sb47@!|6L_U@zfF?X3- zO0d6nwgxKf4GWfdU2WU8j)2tNAGYiNuSJlrKHS}1_3r>sX@R1WF!DU*78)x4^|XAh z2wALZ8y3PSdW9EKj>g`YCt4jy4?F6UP|0~p{Fb)q%9E(BXTx7zu5T3pVl;@7zrzzZiNtr=JjT`z+h+5M6r{V_E`m;6# zO(LG^xXEhCusD?B5~4*xaI!_m{!ID?3@V$8DO7o?YdgYvOVxieG z-VQUBON_T+fv)q+ zc1tQPNK`13DaK;tXUIdfL2=N)#B{K`vL;`{>q~Wq;M!8)kkxOq6tkD~uO~ZsR!AfO zop(6JVSbolLke!p7#VxQIXKX@`xXeD)Y*=y+`-VP2UyY zCIVpV6~3Hbw3OWd4;%z)cT_kmcW6ZAxx>(A5yYY0doSc~aA|)eTcpjNJw5f`iEy{e z*^N@qK3G*V?U;Ma;z&C!DmeRzii9*5pQ{yEq(w+R@X}4n!&ck&Y1Sr9S!~Hn;25@+ zC6vpS>|RAtO-loPwF!$- z==mVbHf&r)ERI1%ZsV$Zeh`vP(8^wP`-5>vEyJ+>FgjNdHC#ZD_z^MzI*znspdhK> z)&x%KAC}T~(m^64jEp)(lA(1F?$$pCH@?p}|tn0%x#geu2m z*YcA3sSRy*@}D{cXmg%`=6NRBZM;$#3Nd)wSrT?=(QdG_iVIxzMcho#MojNJzolGz zI#+&i*YmLGUPS&x0@;{B`B!)f@ddsaDC<3w$kJX-BSVGoDfT`mwqs|lZ;RXZRLa&1>d~O zIM4cAzIoSeLc1j>C>EF9fv!Y2Bh?YSd0*~5!W9;j8?u7Xe`(UE1c5Z%#lGyn8yWky zBo@Luj8cggbA>j7HcCSr+R1OoqKHdR!fJWaG(TNUSBN~8wEG4W#C&moF^YjEnfHWI zj8K)U413E9i*XV;D9nrr%>-N3m^BG8W0?dE78H9pdUO5wr`mi=%QX-tBMLw>xTJ0Z z?4)nrFdL<&8%9U`bsVK4~6s5S(tdzNTTcyq>qgpy-Dgc1mBdX zPWJ?N-N=dLsVh6(<%XtP+@;N()w+*i3fnhBFj@Gdpc`d$Lw1fBln=O6DpnYerots0 z3#Ri~_LpdTtc2;8GnH8r6mFYC@BKIhIiz5~VGm&lz-+~w8qKu1(E9jH^k zzINp~a`u0ev&dhbm7Eq+>fbzp(pSN5l)~X1Y$WUCI zZc+#Bnh<9U403T&$R@eGY!&+9G@;CKgH8&A92^o_Y`v zVI0UU;3_w5H7z*AE32|k^g!c2jK~Q+LGplLPb-RA6^TE(v?8y?mH-sG-oT^8e~R7d z^N2ndj_QcKx4-9h6zj3*x7&Vf;AbTrX!+x;oaTfqyB#Kmy%b7~q%%x#c(iyk71fw0 zo}P9=1qMBv`iLoH@Sk%J$}h>Z?IsktLopb0O$Ozc!}Yb{Ug?f%PiCw_$q!Sw0V7my ztn)fMipo@!ohv4yet>#E558&Z9Hr1^_;eIiQ!}`Bp<4Tl2Xxs`7Mj>JJja5jSiX9` zTdbQV(8Fe>O4$-7Qg`2RSZ$0Tzy|po3#H0k52p6G57(A70NG9z$edNQzXlpE!QV~Ha#^^_GZ{D(>fX(BZ=n+$xz(by?_k@>xfRdq805ldVl%~BVL?Hm*-}l=x9o4+Mv-8%KgQ;_HAiypK1WzU zWI>D2hG9t(7*+@zbkijk_?b=R_93t;Sgsdp4yNe%t@XIZ(V_-51sk5XYGZb}4} zM+R%=aie- z@7`ZTemit3NQkINC8fcgx{6(g5Z2&XOI;39IOdYuZNW>OzLE^M-w0)XYW*evb9$za z*09d>5zVbMZ2e=kYFq`B;;^d1gFNU(9(-UmBVXk5nF}ao6Q^hE*keNR2M9iQp@HdECRv{D`7J z=P($>Xpaxg8Js!kzic~CqwPcsgdV5PQZ_OHv~#fR=BU5h-iak73Y7>TfvuG1gLj{m zJEbm)eO8ul3Nuy=j!Cd;ec>Q~+e(jz0~RAJxA zoKImcnm9`tXR>8$rXH8p-jc-vH>S^9Fcxe74t?peTcs#+TjD?`s*V?kivSZj9{C1w z8~H<2Jxinb00PpvO;}5pbEI1c96{BRA|FiQN~P>9p6!T67CR+E%!VKj0W2Sn3Bu+Y zfW5i9z6KGuZ{FR>(KxESjQ8MG(Sd@~q|csf6|NFkHtiNfStgV`0CL(2{IV#cgQ4zu zUW`%`zHi+RaNRFtfex2hE>cMeu%6qnu$-T57lUY*!jO4l*cr-Faa6}{4J{tlJbO=i zsyWnT&d&ENM5AmeC4%4nD*ElD>YN5XrslBELm)(?BO--vIbm@Ml0I+BgQBO8linE< zSAx2P+i8x2H=RR7IQN5$_MzL?EHq?pgjp(bf(f6)3y46d%8whP=);_@rB`_HVI@K- zM@tF`tK#PaoBC3T*(#ooU~lTEP@R1_1p2Mf&%;W2^N`(Zu(g!o#3Fc$9IEps75Ch& zz``O!rk<2!ScQ1{*}gVx0V)EG^|5cxYts3{qM-&Z-W#kEEVhdyql)Fn z$~Uu2O22--Z6TSOJ$D% zOCg|Yteesd(v!c+e12rQeYkviCtEUZ^-Oxb*fl)QZOb|eA#M)s8CBm<~eG80}$ba5qXzz4^oHt)!`Pv zQ%=`hJb@z&O(UvV^4HhW(Y|_o|8TjMD)#o_;jI)l)VfY0<7MZ|1Vn|vncC1nrDP~6 z3uz(uaE;N!5Cc=>e)A8ByEuswC0YKxTsx=rQ0A6FNod>G*bmT~I;mfn!x0y)K0g2e z7)dV>&r5%vOSaD&gEIqC(>UFdIAsZ=Zh?hZ4Bh(d{c+@#K%yhy5}@u(o&$`F#k|)w z^sgQC3{#>)@iFZP6s;G5!x^l}h^5g-nwgA3KW>k|o2C?x#y^?nj1ery46zz0(X^~nT zXn2S(q!7q&-fAs&T-pB8)Z>ox?E5(g|m4#5--ol3C3W-?njm9QtqsCNbZ3>6Sd?pI)wztiA6)pD80r_t0o0{ z9h_7Ic5ilC$U@hL1B*;eOE)E)aDB_CkiP@4(r>4jlQ$C}IxKlRIt=3~63D7h1DHzp z&&*YzC?kz(GfSw-LbN_QN{f#;cA?tcG1%g`Y Date: Fri, 11 Oct 2024 04:06:43 +0200 Subject: [PATCH 08/15] First "eut2.interior" shader implementation * Small fix of comments in amod shader * First implementation of "eut2.interior.lit" and "eut2.interior.curtain.lit" shaders (there is also "eut2.interior.spatial.lit", but SCS not use it anywhere now). It's without "interrior mapping" effect, but allow to create new models with that shaders. Because ConverterPIX not support new attributes from mat, after import from .scs, you MUST open .pit file, and replace all: interior_unit_room_dimensions --> aux[0] interior_atlas_dimensions --> aux[1] interior_glass_color --> aux[2] --- .../internals/shaders/eut2/__init__.py | 12 ++ .../eut2/dif_spec_amod_dif_spec/__init__.py | 28 +-- .../shaders/eut2/interior/__init__.py | 166 +++++++++++++++++ .../shaders/eut2/interior/curtain.py | 124 +++++++++++++ addon/io_scs_tools/shader_presets.txt | 173 ++++++++++++++++++ 5 files changed, 489 insertions(+), 14 deletions(-) create mode 100644 addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py create mode 100644 addon/io_scs_tools/internals/shaders/eut2/interior/curtain.py diff --git a/addon/io_scs_tools/internals/shaders/eut2/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/__init__.py index d883946..4717ebb 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/__init__.py @@ -40,6 +40,18 @@ def get_shader(effect): from io_scs_tools.internals.shaders.eut2.window.lit import WindowLit as Shader + elif effect == "interior.lit": + + from io_scs_tools.internals.shaders.eut2.interior import InteriorLit as Shader + + elif effect == "interior.curtain.lit": + + from io_scs_tools.internals.shaders.eut2.interior.curtain import InteriorCurtain as Shader + + # elif effect == "interior.spatial.lit": + # + # from io_scs_tools.internals.shaders.eut2.interior.spatial import InteriorSpatial as Shader + elif effect == "reflective": from io_scs_tools.internals.shaders.eut2.reflective import Reflective as Shader diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py index 0fe1d09..68a642a 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py @@ -60,14 +60,14 @@ def init(node_tree): vcol_group_n = node_tree.nodes[DifSpec.VCOL_GROUP_NODE] # node creation - # - column 0 - + # - column -1 - sec_uvmap_n = node_tree.nodes.new("ShaderNodeUVMap") sec_uvmap_n.name = DifSpecAmodDifSpec.SEC_UVMAP_NODE sec_uvmap_n.label = DifSpecAmodDifSpec.SEC_UVMAP_NODE sec_uvmap_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1000) sec_uvmap_n.uv_map = _MESH_consts.none_uv - # - column 2 - + # - column 1 - vcol_scale_n = node_tree.nodes.new("ShaderNodeVectorMath") vcol_scale_n.name = DifSpecAmodDifSpec.VCOLOR_SCALE_NODE vcol_scale_n.label = DifSpecAmodDifSpec.VCOLOR_SCALE_NODE @@ -87,7 +87,7 @@ def init(node_tree): over_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 700) over_tex_n.width = 140 - # - column 3 - + # - column 2 - vcol_subtract_n = node_tree.nodes.new("ShaderNodeVectorMath") vcol_subtract_n.name = DifSpecAmodDifSpec.VCOLOR_SUBTRACT_NODE vcol_subtract_n.label = DifSpecAmodDifSpec.VCOLOR_SUBTRACT_NODE @@ -101,21 +101,21 @@ def init(node_tree): mask_invert_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1000) mask_invert_n.inputs[0].default_value = 1 - # - column 4 - + # - column 3 - vcol_abs_n = node_tree.nodes.new("ShaderNodeVectorMath") vcol_abs_n.name = DifSpecAmodDifSpec.VCOLOR_ABS_NODE vcol_abs_n.label = DifSpecAmodDifSpec.VCOLOR_ABS_NODE vcol_abs_n.location = (start_pos_x + pos_x_shift * 3, start_pos_y + 1100) vcol_abs_n.operation = "ABSOLUTE" - # - column 5 - + # - column 4 - vcol_invert_n = node_tree.nodes.new("ShaderNodeInvert") vcol_invert_n.name = DifSpecAmodDifSpec.VCOLOR_INVERT_NODE vcol_invert_n.label = DifSpecAmodDifSpec.VCOLOR_INVERT_NODE vcol_invert_n.location = (start_pos_x + pos_x_shift * 4, start_pos_y + 1100) vcol_invert_n.inputs[0].default_value = 1 - # - column 6 - + # - column 5 - mask_vcol_mix_n = node_tree.nodes.new("ShaderNodeMixRGB") mask_vcol_mix_n.name = DifSpecAmodDifSpec.MASK_VCOLOR_MIX_NODE mask_vcol_mix_n.label = DifSpecAmodDifSpec.MASK_VCOLOR_MIX_NODE @@ -123,7 +123,7 @@ def init(node_tree): mask_vcol_mix_n.blend_type = "MIX" mask_vcol_mix_n.inputs['Color2'].default_value = (1,) * 4 - # - column 7 - + # - column 6 - mask_color_mix_n = node_tree.nodes.new("ShaderNodeMixRGB") mask_color_mix_n.name = DifSpecAmodDifSpec.MASK_COLOR_MIX_NODE mask_color_mix_n.label = DifSpecAmodDifSpec.MASK_COLOR_MIX_NODE @@ -133,31 +133,31 @@ def init(node_tree): # links creation - # - Column 0 - + # - Column -1 - node_tree.links.new(vcol_group_n.outputs[1], vcol_scale_n.inputs[0]) node_tree.links.new(sec_uvmap_n.outputs['UV'], mask_tex_n.inputs['Vector']) node_tree.links.new(sec_uvmap_n.outputs['UV'], over_tex_n.inputs['Vector']) - # - Column 2 - + # - Column 1 - node_tree.links.new(base_tex_n.outputs['Color'], mask_color_mix_n.inputs['Color2']) node_tree.links.new(vcol_scale_n.outputs['Vector'], vcol_subtract_n.inputs[0]) node_tree.links.new(mask_tex_n.outputs['Color'], mask_invert_n.inputs['Color']) node_tree.links.new(over_tex_n.outputs['Color'], mask_color_mix_n.inputs['Color1']) - # - Column 3 - + # - Column 2 - node_tree.links.new(vcol_subtract_n.outputs['Vector'], vcol_abs_n.inputs[0]) node_tree.links.new(mask_invert_n.outputs['Color'], mask_vcol_mix_n.inputs['Color1']) - # - Column 4 - + # - Column 3 - node_tree.links.new(vcol_abs_n.outputs['Vector'], vcol_invert_n.inputs['Color']) - # - Column 5 - + # - Column 4 - node_tree.links.new(vcol_invert_n.outputs['Color'], mask_vcol_mix_n.inputs['Fac']) - # - Column 6 - + # - Column 5 - node_tree.links.new(mask_vcol_mix_n.outputs['Color'], mask_color_mix_n.inputs['Fac']) - # - Column 7 - + # - Column 6 - node_tree.links.new(mask_color_mix_n.outputs['Color'], vcol_multi_n.inputs[1]) diff --git a/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py new file mode 100644 index 0000000..74e6274 --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py @@ -0,0 +1,166 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2015-2024: SCS Software + +from io_scs_tools.internals.shaders.eut2.parameters import get_fresnel_window +from io_scs_tools.internals.shaders.eut2.dif_spec_add_env import DifSpecAddEnv + +class InteriorLit(DifSpecAddEnv): + VGCOLOR_MULT_NODE = "VertexGlassColorMultiplier" + GLASS_COL_NODE = "GlassColor" + GLASS_COL_MIX_NODE = "GlassColorMix" + GLASS_COL_FAC_NODE = "GlassColorFactor" + + + @staticmethod + def get_name(): + """Get name of this shader file with full modules path.""" + return __name__ + + @staticmethod + def init(node_tree): + """Initialize node tree with links for this shader. + + :param node_tree: node tree on which this shader should be created + :type node_tree: bpy.types.NodeTree + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + # init parent + DifSpecAddEnv.init(node_tree) + + base_tex_n = node_tree.nodes[DifSpecAddEnv.BASE_TEX_NODE] + vcol_mult_n = node_tree.nodes[DifSpecAddEnv.VCOLOR_MULT_NODE] + diff_mult_n = node_tree.nodes[DifSpecAddEnv.DIFF_MULT_NODE] + + # set fresnel type to schlick + node_tree.nodes[DifSpecAddEnv.ADD_ENV_GROUP_NODE].inputs['Fresnel Type'].default_value = 1.0 + + # delete existing + node_tree.nodes.remove(node_tree.nodes[DifSpecAddEnv.OPACITY_NODE]) + + # move existing + diff_mult_n.location.x += pos_x_shift + vcol_mult_n.location.x += pos_x_shift + + # node creation + # - column 1 - + glass_col_n = node_tree.nodes.new("ShaderNodeRGB") + glass_col_n.name = glass_col_n.label = InteriorLit.GLASS_COL_NODE + glass_col_n.location = (start_pos_x + pos_x_shift, start_pos_y + 900) + + # - column 2 - + glass_col_fac_n = node_tree.nodes.new("ShaderNodeValue") + glass_col_fac_n.name = glass_col_fac_n.label = InteriorLit.GLASS_COL_FAC_NODE + glass_col_fac_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 800) + + # - column 3 - + vgcol_mult_n = node_tree.nodes.new("ShaderNodeVectorMath") + vgcol_mult_n.name = vgcol_mult_n.label = InteriorLit.VGCOLOR_MULT_NODE + vgcol_mult_n.location = (start_pos_x + pos_x_shift * 3, start_pos_y + 1200) + vgcol_mult_n.operation = "MULTIPLY" + + # - column 4 - + glass_col_mix_n = node_tree.nodes.new("ShaderNodeMixRGB") + glass_col_mix_n.name = glass_col_mix_n.label = InteriorLit.GLASS_COL_MIX_NODE + glass_col_mix_n.location = (start_pos_x + pos_x_shift * 4, start_pos_y + 1200) + + + # links creation + # - column 1 - + node_tree.links.new(base_tex_n.outputs['Color'], vgcol_mult_n.inputs[0]) + + node_tree.links.new(glass_col_n.outputs['Color'], vgcol_mult_n.inputs[1]) + node_tree.links.new(glass_col_n.outputs['Color'], glass_col_mix_n.inputs['Color2']) + + # - column 2 - + node_tree.links.new(glass_col_fac_n.outputs['Value'], glass_col_mix_n.inputs['Fac']) + + # - column 3 - + node_tree.links.new(vgcol_mult_n.outputs['Vector'], glass_col_mix_n.inputs['Color1']) + + # - column 4 - + node_tree.links.new(glass_col_mix_n.outputs['Color'], vcol_mult_n.inputs[1]) + + @staticmethod + def set_fresnel(node_tree, bias_scale): + """Set fresnel bias and scale value to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param bias_scale: bias and scale factors as tuple: (bias, scale) + :type bias_scale: (float, float) + """ + + bias_scale_window = get_fresnel_window(bias_scale[0], bias_scale[1]) + + DifSpecAddEnv.set_fresnel(node_tree, bias_scale_window) + + @staticmethod + def set_aux0(node_tree, aux_property): + """Set unit room dimension for the shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param aux_property: TBA + :type aux_property: bpy.types.IDPropertyGroup + """ + pass # NOTE: TBA? + + @staticmethod + def set_aux1(node_tree, aux_property): + """Set atlas dimension for the shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param aux_property: TBA + :type aux_property: bpy.types.IDPropertyGroup + """ + pass # NOTE: TBA? + + @staticmethod + def set_aux2(node_tree, aux_property): + """Set glass color for the shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param aux_property: glass color + :type aux_property: bpy.types.IDPropertyGroup + """ + + color = (aux_property[0]["value"], aux_property[1]["value"], aux_property[2]["value"], 1.0) + node_tree.nodes[InteriorLit.GLASS_COL_NODE].outputs["Color"].default_value = color + + factor = aux_property[3]["value"] + node_tree.nodes[InteriorLit.GLASS_COL_FAC_NODE].outputs["Value"].default_value = factor + + @staticmethod + def set_aux5(node_tree, aux_property): + """Set luminance boost factor for the shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param aux_property: luminosity factor represented with property group + :type aux_property: bpy.types.IDPropertyGroup + """ + pass # NOTE: as this variant doesn't use luminance effect we just ignore this factor diff --git a/addon/io_scs_tools/internals/shaders/eut2/interior/curtain.py b/addon/io_scs_tools/internals/shaders/eut2/interior/curtain.py new file mode 100644 index 0000000..6a58289 --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/interior/curtain.py @@ -0,0 +1,124 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2015-2024: SCS Software + +from io_scs_tools.consts import Mesh as _MESH_consts +from io_scs_tools.internals.shaders.eut2.interior import InteriorLit +from io_scs_tools.utils import material as _material_utils + +class InteriorCurtain(InteriorLit): + SEC_UVMAP_NODE = "SecondUVMap" + OVER_TEX_NODE = "OverTex" + BASE_OVER_MIX_NODE = "BaseOverColorMix" + + + @staticmethod + def get_name(): + """Get name of this shader file with full modules path.""" + return __name__ + + @staticmethod + def init(node_tree): + """Initialize node tree with links for this shader. + + :param node_tree: node tree on which this shader should be created + :type node_tree: bpy.types.NodeTree + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + # init parent + InteriorLit.init(node_tree) + + base_tex_n = node_tree.nodes[InteriorLit.BASE_TEX_NODE] + vgcol_mult_n = node_tree.nodes[InteriorLit.VGCOLOR_MULT_NODE] + + # node creation + # - column -1 - + sec_uv_n = node_tree.nodes.new("ShaderNodeUVMap") + sec_uv_n.name = sec_uv_n.label = InteriorCurtain.SEC_UVMAP_NODE + sec_uv_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1100) + sec_uv_n.uv_map = _MESH_consts.none_uv + + # - column 1 - + over_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + over_tex_n.name = over_tex_n.label = InteriorCurtain.OVER_TEX_NODE + over_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 1200) + over_tex_n.width = 140 + + # - column 2 - + base_over_mix_n = node_tree.nodes.new("ShaderNodeMixRGB") + base_over_mix_n.name = base_over_mix_n.label = InteriorCurtain.BASE_OVER_MIX_NODE + base_over_mix_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1200) + + + # links creation + # - column -1 - + node_tree.links.new(sec_uv_n.outputs['UV'], over_tex_n.inputs['Vector']) + + # - column 1 - + node_tree.links.new(base_tex_n.outputs['Color'], base_over_mix_n.inputs['Color1']) + node_tree.links.new(over_tex_n.outputs['Color'], base_over_mix_n.inputs['Color2']) + node_tree.links.new(over_tex_n.outputs['Alpha'], base_over_mix_n.inputs['Fac']) + + # - column 2 - + node_tree.links.new(base_over_mix_n.outputs['Color'], vgcol_mult_n.inputs[0]) + + + + @staticmethod + def set_over_texture(node_tree, image): + """Set overlying texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assigned to over texture node + :type image: bpy.types.Texture + """ + + node_tree.nodes[InteriorCurtain.OVER_TEX_NODE].image = image + + @staticmethod + def set_over_texture_settings(node_tree, settings): + """Set overlying texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + _material_utils.set_texture_settings_to_node(node_tree.nodes[InteriorCurtain.OVER_TEX_NODE], settings) + + @staticmethod + def set_over_uv(node_tree, uv_layer): + """Set UV layer to overlying texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for over texture + :type uv_layer: str + """ + + if uv_layer is None or uv_layer == "": + uv_layer = _MESH_consts.none_uv + + node_tree.nodes[InteriorCurtain.SEC_UVMAP_NODE].uv_map = uv_layer diff --git a/addon/io_scs_tools/shader_presets.txt b/addon/io_scs_tools/shader_presets.txt index 00ad8fc..835f63f 100644 --- a/addon/io_scs_tools/shader_presets.txt +++ b/addon/io_scs_tools/shader_presets.txt @@ -1828,6 +1828,179 @@ Shader { TexCoord: ( 1 ) } } +Shader { + PresetName: "interior.lit" + Effect: "eut2.interior.lit" + Flags: 0 + Attribute { + Format: FLOAT3 + Tag: "diffuse" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT3 + Tag: "specular" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT + Tag: "shininess" + Value: ( 65.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "fresnel" + Value: ( 0.200000003 0.8999999762 ) + } + Attribute { + Format: FLOAT3 + Tag: "env_factor" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "aux[5]" + FriendlyTag: "Luminance Output (Day, Night) (nit)" + Value: ( 1700.0 17.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "aux[1]" + FriendlyTag: "Atlas Dimensions (X,Z)" + Value: ( 8.0 4.0 ) + } + Attribute { + Format: FLOAT4 + Tag: "aux[2]" + FriendlyTag: "Glass Color (R,G,B,Factor)" + Value: ( 1.0 1.0 1.0 0.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "aux[0]" + FriendlyTag: "Room Dimensions (X,Z)" + Value: ( 3.5 3.5 ) + } + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_layer0" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_layer1" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_mask" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_nmap_detail" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_reflection" + Value: "/material/environment/building_reflection/building_ref" + TexCoord: ( -1 ) + } +} +Shader { + PresetName: "interior.curtain.lit" + Effect: "eut2.interior.curtain.lit" + Flags: 0 + Attribute { + Format: FLOAT3 + Tag: "diffuse" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT3 + Tag: "specular" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT + Tag: "shininess" + Value: ( 65.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "fresnel" + Value: ( 0.200000003 0.8999999762 ) + } + Attribute { + Format: FLOAT3 + Tag: "env_factor" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "aux[5]" + FriendlyTag: "Luminance Output (Day, Night) (nit)" + Value: ( 1700.0 17.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "aux[1]" + FriendlyTag: "Atlas Dimensions (X,Z)" + Value: ( 8.0 4.0 ) + } + Attribute { + Format: FLOAT4 + Tag: "aux[2]" + FriendlyTag: "Glass Color (R,G,B,Factor)" + Value: ( 1.0 1.0 1.0 0.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "aux[0]" + FriendlyTag: "Room Dimensions (X,Z)" + Value: ( 3.5 3.5 ) + } + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_over" + Value: "" + TexCoord: ( 2 ) + } + Texture { + Tag: "texture[X]:texture_layer0" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_layer1" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_mask" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_nmap_detail" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_reflection" + Value: "/material/environment/building_reflection/building_ref" + TexCoord: ( -1 ) + } +} Flavor { Type: "AIRBRUSH" Name: "airbrush" From 8ebe28e8972062ee70a5d2020cdb0ccfbf480919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Wed, 30 Oct 2024 02:53:39 +0100 Subject: [PATCH 09/15] amod update, interior tweaks * Fixed "amod" shader - changed "decal_blending_factors" attribute to "aux" (and removed old properties) * Added support for "Decal blending factors" attributes in material tab * Updated "amod" nodes to better reflect that shader in blender * Corrected TexGen description in shader_presets.txt --- .../eut2/dif_spec_amod_dif_spec/__init__.py | 138 ++++++++-------- .../decal_blend_factor_ng.py | 155 ++++++++++++++++++ .../shaders/eut2/interior/__init__.py | 97 ++++++++++- .../shaders/eut2/shadowonly/__init__.py | 94 ++++++++++- addon/io_scs_tools/properties/material.py | 15 -- addon/io_scs_tools/shader_presets.txt | 19 ++- 6 files changed, 422 insertions(+), 96 deletions(-) create mode 100644 addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/decal_blend_factor_ng.py diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py index 68a642a..fde4cb8 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/__init__.py @@ -20,19 +20,19 @@ from io_scs_tools.consts import Mesh as _MESH_consts from io_scs_tools.internals.shaders.eut2.dif_spec import DifSpec +from io_scs_tools.internals.shaders.eut2.dif_spec_amod_dif_spec import decal_blend_factor_ng from io_scs_tools.utils import material as _material_utils class DifSpecAmodDifSpec(DifSpec): SEC_UVMAP_NODE = "SecondUVMap" - VCOLOR_SCALE_NODE = "VertexColorScale" - VCOLOR_SUBTRACT_NODE = "VertexColorSubtract" - VCOLOR_ABS_NODE = "VertexColorAbsolute" - VCOLOR_INVERT_NODE = "VertexColorInvert" MASK_TEX_NODE = "MaskTex" OVER_TEX_NODE = "OverTex" - MASK_COLOR_INVERT_NODE = "MaskColorInvert" + BLENDING_FACTOR_1 = "BlendingFactor1" + BLENDING_FACTOR_2 = "BlendingFactor2" + DECAL_BLEND_FACTOR_NODE = "DecalBlendFactorGNode" MASK_VCOLOR_MIX_NODE = "MaskVertexColorMix" MASK_COLOR_MIX_NODE = "MaskColorMix" + @staticmethod def get_name(): @@ -58,22 +58,34 @@ def init(node_tree): base_tex_n = node_tree.nodes[DifSpec.BASE_TEX_NODE] vcol_multi_n = node_tree.nodes[DifSpec.VCOLOR_MULT_NODE] vcol_group_n = node_tree.nodes[DifSpec.VCOL_GROUP_NODE] + + # delete existing + node_tree.nodes.remove(node_tree.nodes[DifSpec.OPACITY_NODE]) # node creation # - column -1 - + blending_factor_1_n = node_tree.nodes.new("ShaderNodeValue") + blending_factor_1_n.name = DifSpecAmodDifSpec.BLENDING_FACTOR_1 + blending_factor_1_n.label = DifSpecAmodDifSpec.BLENDING_FACTOR_1 + blending_factor_1_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1100) + + blending_factor_2_n = node_tree.nodes.new("ShaderNodeValue") + blending_factor_2_n.name = DifSpecAmodDifSpec.BLENDING_FACTOR_2 + blending_factor_2_n.label = DifSpecAmodDifSpec.BLENDING_FACTOR_2 + blending_factor_2_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1000) + sec_uvmap_n = node_tree.nodes.new("ShaderNodeUVMap") sec_uvmap_n.name = DifSpecAmodDifSpec.SEC_UVMAP_NODE sec_uvmap_n.label = DifSpecAmodDifSpec.SEC_UVMAP_NODE - sec_uvmap_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1000) + sec_uvmap_n.location = (start_pos_x - pos_x_shift, start_pos_y + 900) sec_uvmap_n.uv_map = _MESH_consts.none_uv # - column 1 - - vcol_scale_n = node_tree.nodes.new("ShaderNodeVectorMath") - vcol_scale_n.name = DifSpecAmodDifSpec.VCOLOR_SCALE_NODE - vcol_scale_n.label = DifSpecAmodDifSpec.VCOLOR_SCALE_NODE - vcol_scale_n.location = (start_pos_x + pos_x_shift, start_pos_y + 1200) - vcol_scale_n.operation = "MULTIPLY" - vcol_scale_n.inputs[1].default_value = (2,) * 3 + deacl_blend_fac_gn = node_tree.nodes.new("ShaderNodeGroup") + deacl_blend_fac_gn.name = DifSpecAmodDifSpec.DECAL_BLEND_FACTOR_NODE + deacl_blend_fac_gn.label = DifSpecAmodDifSpec.DECAL_BLEND_FACTOR_NODE + deacl_blend_fac_gn.location = (start_pos_x + pos_x_shift, start_pos_y + 1200) + deacl_blend_fac_gn.node_tree = decal_blend_factor_ng.get_node_group() mask_tex_n = node_tree.nodes.new("ShaderNodeTexImage") mask_tex_n.name = DifSpecAmodDifSpec.MASK_TEX_NODE @@ -88,94 +100,56 @@ def init(node_tree): over_tex_n.width = 140 # - column 2 - - vcol_subtract_n = node_tree.nodes.new("ShaderNodeVectorMath") - vcol_subtract_n.name = DifSpecAmodDifSpec.VCOLOR_SUBTRACT_NODE - vcol_subtract_n.label = DifSpecAmodDifSpec.VCOLOR_SUBTRACT_NODE - vcol_subtract_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1200) - vcol_subtract_n.operation = "SUBTRACT" - vcol_subtract_n.inputs[1].default_value = (1,) * 3 - - mask_invert_n = node_tree.nodes.new("ShaderNodeInvert") - mask_invert_n.name = DifSpecAmodDifSpec.MASK_COLOR_INVERT_NODE - mask_invert_n.label = DifSpecAmodDifSpec.MASK_COLOR_INVERT_NODE - mask_invert_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1000) - mask_invert_n.inputs[0].default_value = 1 - - # - column 3 - - vcol_abs_n = node_tree.nodes.new("ShaderNodeVectorMath") - vcol_abs_n.name = DifSpecAmodDifSpec.VCOLOR_ABS_NODE - vcol_abs_n.label = DifSpecAmodDifSpec.VCOLOR_ABS_NODE - vcol_abs_n.location = (start_pos_x + pos_x_shift * 3, start_pos_y + 1100) - vcol_abs_n.operation = "ABSOLUTE" - - # - column 4 - - vcol_invert_n = node_tree.nodes.new("ShaderNodeInvert") - vcol_invert_n.name = DifSpecAmodDifSpec.VCOLOR_INVERT_NODE - vcol_invert_n.label = DifSpecAmodDifSpec.VCOLOR_INVERT_NODE - vcol_invert_n.location = (start_pos_x + pos_x_shift * 4, start_pos_y + 1100) - vcol_invert_n.inputs[0].default_value = 1 - - # - column 5 - mask_vcol_mix_n = node_tree.nodes.new("ShaderNodeMixRGB") mask_vcol_mix_n.name = DifSpecAmodDifSpec.MASK_VCOLOR_MIX_NODE mask_vcol_mix_n.label = DifSpecAmodDifSpec.MASK_VCOLOR_MIX_NODE - mask_vcol_mix_n.location = (start_pos_x + pos_x_shift * 5, start_pos_y + 1100) + mask_vcol_mix_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1200) mask_vcol_mix_n.blend_type = "MIX" - mask_vcol_mix_n.inputs['Color2'].default_value = (1,) * 4 + mask_vcol_mix_n.inputs['Color1'].default_value = (0,) * 3 + (1,) - # - column 6 - + # - column 3 - mask_color_mix_n = node_tree.nodes.new("ShaderNodeMixRGB") mask_color_mix_n.name = DifSpecAmodDifSpec.MASK_COLOR_MIX_NODE mask_color_mix_n.label = DifSpecAmodDifSpec.MASK_COLOR_MIX_NODE - mask_color_mix_n.location = (start_pos_x + pos_x_shift * 6, start_pos_y + 1050) + mask_color_mix_n.location = (start_pos_x + pos_x_shift * 3, start_pos_y + 1200) mask_color_mix_n.blend_type = "MIX" # links creation # - Column -1 - - node_tree.links.new(vcol_group_n.outputs[1], vcol_scale_n.inputs[0]) + node_tree.links.new(vcol_group_n.outputs['Vertex Color Alpha'], deacl_blend_fac_gn.inputs['Vertex Alpha']) + node_tree.links.new(blending_factor_1_n.outputs['Value'], deacl_blend_fac_gn.inputs['Factor1']) + node_tree.links.new(blending_factor_2_n.outputs['Value'], deacl_blend_fac_gn.inputs['Factor2']) node_tree.links.new(sec_uvmap_n.outputs['UV'], mask_tex_n.inputs['Vector']) node_tree.links.new(sec_uvmap_n.outputs['UV'], over_tex_n.inputs['Vector']) # - Column 1 - - node_tree.links.new(base_tex_n.outputs['Color'], mask_color_mix_n.inputs['Color2']) - node_tree.links.new(vcol_scale_n.outputs['Vector'], vcol_subtract_n.inputs[0]) - node_tree.links.new(mask_tex_n.outputs['Color'], mask_invert_n.inputs['Color']) - node_tree.links.new(over_tex_n.outputs['Color'], mask_color_mix_n.inputs['Color1']) + node_tree.links.new(base_tex_n.outputs['Color'], mask_color_mix_n.inputs['Color1']) + node_tree.links.new(mask_tex_n.outputs['Color'], mask_vcol_mix_n.inputs['Color2']) + node_tree.links.new(over_tex_n.outputs['Color'], mask_color_mix_n.inputs['Color2']) + node_tree.links.new(deacl_blend_fac_gn.outputs['Factor'], mask_vcol_mix_n.inputs['Fac']) # - Column 2 - - node_tree.links.new(vcol_subtract_n.outputs['Vector'], vcol_abs_n.inputs[0]) - node_tree.links.new(mask_invert_n.outputs['Color'], mask_vcol_mix_n.inputs['Color1']) - - # - Column 3 - - node_tree.links.new(vcol_abs_n.outputs['Vector'], vcol_invert_n.inputs['Color']) - - # - Column 4 - - node_tree.links.new(vcol_invert_n.outputs['Color'], mask_vcol_mix_n.inputs['Fac']) - - # - Column 5 - node_tree.links.new(mask_vcol_mix_n.outputs['Color'], mask_color_mix_n.inputs['Fac']) - # - Column 6 - + # - Column 3 - node_tree.links.new(mask_color_mix_n.outputs['Color'], vcol_multi_n.inputs[1]) @staticmethod - def set_over_uv(node_tree, uv_layer): - """Set UV layer to overlying texture in shader. + def set_aux0(node_tree, aux_property): + """Set decal blending factors to shader. :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree - :param uv_layer: uv layer string used for over texture - :type uv_layer: str + :param aux_property: decal blending factors represented with property group + :type aux_property: bpy.types.IDPropertyGroup """ - if uv_layer is None or uv_layer == "": - uv_layer = _MESH_consts.none_uv - - node_tree.nodes[DifSpecAmodDifSpec.SEC_UVMAP_NODE].uv_map = uv_layer - + node_tree.nodes[DifSpecAmodDifSpec.BLENDING_FACTOR_1].outputs["Value"].default_value = aux_property[0]['value'] + node_tree.nodes[DifSpecAmodDifSpec.BLENDING_FACTOR_2].outputs["Value"].default_value = aux_property[1]['value'] + @staticmethod def set_mask_texture(node_tree, image): """Set mask texture to shader. @@ -197,9 +171,29 @@ def set_mask_texture_settings(node_tree, settings): :param settings: binary string of TOBJ settings gotten from tobj import :type settings: str """ - # Commented because of texture linear colorspace problems in render - # _material_utils.set_texture_settings_to_node(node_tree.nodes[DifSpecAmodDifSpec.MASK_TEX_NODE], settings) - + _material_utils.set_texture_settings_to_node(node_tree.nodes[DifSpecAmodDifSpec.MASK_TEX_NODE], settings) + + # due the fact uvs get clamped in vertex shader, we have to manually switch repeat on, for effect to work correctly + node_tree.nodes[DifSpecAmodDifSpec.MASK_TEX_NODE].extension = "REPEAT" + + # due the fact uvs colorspace linear, we have to manually switch to sRGB, for effect to work correctly + node_tree.nodes[DifSpecAmodDifSpec.MASK_TEX_NODE].image.colorspace_settings.name = 'sRGB' + + @staticmethod + def set_over_uv(node_tree, uv_layer): + """Set UV layer to overlying texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for over texture + :type uv_layer: str + """ + + if uv_layer is None or uv_layer == "": + uv_layer = _MESH_consts.none_uv + + node_tree.nodes[DifSpecAmodDifSpec.SEC_UVMAP_NODE].uv_map = uv_layer + @staticmethod def set_over_texture(node_tree, image): """Set over texture to shader. diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/decal_blend_factor_ng.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/decal_blend_factor_ng.py new file mode 100644 index 0000000..a124be2 --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_amod_dif_spec/decal_blend_factor_ng.py @@ -0,0 +1,155 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2015: SCS Software + +from multiprocessing.spawn import import_main_path +import bpy +from io_scs_tools.consts import Material as _MAT_consts + +DECAL_BLEND_FACTOR_G = _MAT_consts.node_group_prefix + "DecalBlendFactor" + +_MAP_VCOLA_SHIFT_NODE = "MapVColAlphaShift" +_INVERT_NEG_NODE = "InvertNegatives" +_ALPHA_1_SCALE_NODE = "AlphaScale_1" +_ALPHA_2_SCALE_NODE = "AlphaScale_2" +_BLEND_1_ABS_NODE = "BlendingAbsolute_1" +_BLEND_2_ABS_NODE = "BlendingAbsolute_2" +_MULT_1_SCALE_NODE = "MultScale_1" +_MULT_2_SCALE_NODE = "MultScale_2" +_MULT_FINAL_NODE = "MultFinal" + +def get_node_group(): + """Gets node group for combining of Decal blending factors with mask texture. + + :return: node group which calculates change factor + :rtype: bpy.types.NodeGroup + """ + + if DECAL_BLEND_FACTOR_G not in bpy.data.node_groups: + __create_node_group__() + + return bpy.data.node_groups[DECAL_BLEND_FACTOR_G] + +def __create_node_group__(): + """Creates decal blending factor group. + + Inputs: Decal blending factor (1 & 2) and Vertex Color Alpha + Outputs: Factor + """ + + pos_x_shift = 185 + + dec_blend_fac_g = bpy.data.node_groups.new(type="ShaderNodeTree", name=DECAL_BLEND_FACTOR_G) + + # inputs defining + dec_blend_fac_g.inputs.new("NodeSocketFloat", "Vertex Alpha") + dec_blend_fac_g.inputs.new("NodeSocketFloat", "Factor1") + dec_blend_fac_g.inputs.new("NodeSocketFloat", "Factor2") + + input_n = dec_blend_fac_g.nodes.new("NodeGroupInput") + input_n.location = (0, 0) + + # outputs defining + dec_blend_fac_g.outputs.new("NodeSocketColor", "Factor") + output_n = dec_blend_fac_g.nodes.new("NodeGroupOutput") + output_n.location = (pos_x_shift * 6, 0) + + + # nodes creation + # - column 1 - + map_vcol_a_shift_n = dec_blend_fac_g.nodes.new("ShaderNodeMapping") + map_vcol_a_shift_n.name = map_vcol_a_shift_n.label = _MAP_VCOLA_SHIFT_NODE + map_vcol_a_shift_n.location = (pos_x_shift, 100) + map_vcol_a_shift_n.vector_type = "POINT" + map_vcol_a_shift_n.inputs['Location'].default_value = (-0.5,) * 3 + + # - column 2 - + invert_neg_n = dec_blend_fac_g.nodes.new("ShaderNodeVectorMath") + invert_neg_n.name = invert_neg_n.label = _INVERT_NEG_NODE + invert_neg_n.location = (pos_x_shift * 2, 250) + invert_neg_n.operation = "MULTIPLY" + invert_neg_n.inputs[1].default_value = (-1,) * 3 + + # - column 3 - + alpha_1_scale_n = dec_blend_fac_g.nodes.new("ShaderNodeVectorMath") + alpha_1_scale_n.name = alpha_1_scale_n.label = _ALPHA_1_SCALE_NODE + alpha_1_scale_n.location = (pos_x_shift * 3, 250) + alpha_1_scale_n.operation = "MULTIPLY" + alpha_1_scale_n.inputs[1].default_value = (2,) * 3 + + blending_1_abs_n = dec_blend_fac_g.nodes.new("ShaderNodeVectorMath") + blending_1_abs_n.name = blending_1_abs_n.label = _BLEND_1_ABS_NODE + blending_1_abs_n.location = (pos_x_shift * 3, 50) + blending_1_abs_n.operation = "ABSOLUTE" + + alpha_2_scale_n = dec_blend_fac_g.nodes.new("ShaderNodeVectorMath") + alpha_2_scale_n.name = alpha_2_scale_n.label = _ALPHA_2_SCALE_NODE + alpha_2_scale_n.location = (pos_x_shift * 3, -100) + alpha_2_scale_n.operation = "MULTIPLY" + alpha_2_scale_n.inputs[1].default_value = (2,) * 3 + + blending_2_abs_n = dec_blend_fac_g.nodes.new("ShaderNodeVectorMath") + blending_2_abs_n.name = blending_2_abs_n.label = _BLEND_2_ABS_NODE + blending_2_abs_n.location = (pos_x_shift * 3, -300) + blending_2_abs_n.operation = "ABSOLUTE" + + # - column 4 - + mult_1_scale_n = dec_blend_fac_g.nodes.new("ShaderNodeVectorMath") + mult_1_scale_n.name = mult_1_scale_n.label = _MULT_1_SCALE_NODE + mult_1_scale_n.location = (pos_x_shift * 4, 100) + mult_1_scale_n.operation = "MULTIPLY" + + mult_2_scale_n = dec_blend_fac_g.nodes.new("ShaderNodeVectorMath") + mult_2_scale_n.name = mult_2_scale_n.label = _MULT_2_SCALE_NODE + mult_2_scale_n.location = (pos_x_shift * 4, -200) + mult_2_scale_n.operation = "MULTIPLY" + + # - column 5 - + mult_final_n = dec_blend_fac_g.nodes.new("ShaderNodeVectorMath") + mult_final_n.name = mult_final_n.label = _MULT_FINAL_NODE + mult_final_n.location = (pos_x_shift * 5, 0) + mult_final_n.operation = "MAXIMUM" + + + # links creation + # - column 0 - + dec_blend_fac_g.links.new(input_n.outputs["Vertex Alpha"], map_vcol_a_shift_n.inputs["Vector"]) + dec_blend_fac_g.links.new(input_n.outputs["Factor1"], blending_1_abs_n.inputs["Vector"]) + dec_blend_fac_g.links.new(input_n.outputs["Factor2"], blending_2_abs_n.inputs["Vector"]) + + # - column 1 - + dec_blend_fac_g.links.new(map_vcol_a_shift_n.outputs["Vector"], invert_neg_n.inputs[0]) + dec_blend_fac_g.links.new(map_vcol_a_shift_n.outputs["Vector"], alpha_2_scale_n.inputs[0]) + + # - column 2 - + dec_blend_fac_g.links.new(invert_neg_n.outputs["Vector"], alpha_1_scale_n.inputs[0]) + + # - column 3 - + dec_blend_fac_g.links.new(alpha_1_scale_n.outputs["Vector"], mult_1_scale_n.inputs[0]) + dec_blend_fac_g.links.new(blending_1_abs_n.outputs["Vector"], mult_1_scale_n.inputs[1]) + + dec_blend_fac_g.links.new(alpha_2_scale_n.outputs["Vector"], mult_2_scale_n.inputs[0]) + dec_blend_fac_g.links.new(blending_2_abs_n.outputs["Vector"], mult_2_scale_n.inputs[1]) + + # - column 4 - + dec_blend_fac_g.links.new(mult_1_scale_n.outputs["Vector"], mult_final_n.inputs[0]) + dec_blend_fac_g.links.new(mult_2_scale_n.outputs["Vector"], mult_final_n.inputs[1]) + + # - column 5 - + dec_blend_fac_g.links.new(mult_final_n.outputs["Vector"], output_n.inputs["Factor"]) diff --git a/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py index 74e6274..b6316bd 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py @@ -20,12 +20,19 @@ from io_scs_tools.internals.shaders.eut2.parameters import get_fresnel_window from io_scs_tools.internals.shaders.eut2.dif_spec_add_env import DifSpecAddEnv +from io_scs_tools.utils import material as _material_utils class InteriorLit(DifSpecAddEnv): VGCOLOR_MULT_NODE = "VertexGlassColorMultiplier" GLASS_COL_NODE = "GlassColor" GLASS_COL_MIX_NODE = "GlassColorMix" GLASS_COL_FAC_NODE = "GlassColorFactor" + LAYER0_TEX_NODE = "Layer0Tex" + LAYER1_TEX_NODE = "Layer1Tex" + MASK_TEX_NODE = "MaskTex" + NMAP_TEX_NODE = "NmapTex" + ENV_SEP_XYZ_NODE = "EnvSepXYZ" + ENV_CHECK_XYZ_NODE = "EnvCheckXYZ" @staticmethod @@ -50,11 +57,16 @@ def init(node_tree): DifSpecAddEnv.init(node_tree) base_tex_n = node_tree.nodes[DifSpecAddEnv.BASE_TEX_NODE] + uvmap_n = node_tree.nodes[DifSpecAddEnv.UVMAP_NODE] vcol_mult_n = node_tree.nodes[DifSpecAddEnv.VCOLOR_MULT_NODE] diff_mult_n = node_tree.nodes[DifSpecAddEnv.DIFF_MULT_NODE] + add_env_group_n = node_tree.nodes[DifSpecAddEnv.ADD_ENV_GROUP_NODE] # set fresnel type to schlick - node_tree.nodes[DifSpecAddEnv.ADD_ENV_GROUP_NODE].inputs['Fresnel Type'].default_value = 1.0 + add_env_group_n.inputs['Fresnel Type'].default_value = 1.0 + + # Doesn't work... + # node_tree.nodes[DifSpecAddEnv.BASE_TEX_NODE].extension = 'REPEAT' # delete existing node_tree.nodes.remove(node_tree.nodes[DifSpecAddEnv.OPACITY_NODE]) @@ -64,11 +76,42 @@ def init(node_tree): vcol_mult_n.location.x += pos_x_shift # node creation + # - column 0 - + env_sep_xyz_n = node_tree.nodes.new("ShaderNodeSeparateXYZ") + env_sep_xyz_n.name = env_sep_xyz_n.label = InteriorLit.ENV_SEP_XYZ_NODE + env_sep_xyz_n.location = (start_pos_x, start_pos_y + 1800) + + env_check_xyz_n = node_tree.nodes.new("ShaderNodeMath") + env_check_xyz_n.name = env_check_xyz_n.label = InteriorLit.ENV_CHECK_XYZ_NODE + env_check_xyz_n.location = (start_pos_x, start_pos_y + 2000) + env_check_xyz_n.operation = "LESS_THAN" + env_check_xyz_n.inputs[1].default_value = 1.0 + # - column 1 - glass_col_n = node_tree.nodes.new("ShaderNodeRGB") glass_col_n.name = glass_col_n.label = InteriorLit.GLASS_COL_NODE glass_col_n.location = (start_pos_x + pos_x_shift, start_pos_y + 900) + layer0_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + layer0_tex_n.name = layer0_tex_n.label = InteriorLit.LAYER0_TEX_NODE + layer0_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 700) + layer0_tex_n.width = 140 + + layer1_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + layer1_tex_n.name = layer1_tex_n.label = InteriorLit.LAYER1_TEX_NODE + layer1_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 450) + layer1_tex_n.width = 140 + + mask_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + mask_tex_n.name = mask_tex_n.label = InteriorLit.MASK_TEX_NODE + mask_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 200) + mask_tex_n.width = 140 + + nmap_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + nmap_tex_n.name = nmap_tex_n.label = InteriorLit.NMAP_TEX_NODE + nmap_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y - 50) + nmap_tex_n.width = 140 + # - column 2 - glass_col_fac_n = node_tree.nodes.new("ShaderNodeValue") glass_col_fac_n.name = glass_col_fac_n.label = InteriorLit.GLASS_COL_FAC_NODE @@ -87,6 +130,13 @@ def init(node_tree): # links creation + # - column -1 - + node_tree.links.new(uvmap_n.outputs['UV'], env_sep_xyz_n.inputs['Vector']) + + # - column 0 - + node_tree.links.new(env_sep_xyz_n.outputs['Y'], env_check_xyz_n.inputs[0]) + node_tree.links.new(env_check_xyz_n.outputs['Value'], add_env_group_n.inputs['Weighted Color']) + # - column 1 - node_tree.links.new(base_tex_n.outputs['Color'], vgcol_mult_n.inputs[0]) @@ -102,6 +152,31 @@ def init(node_tree): # - column 4 - node_tree.links.new(glass_col_mix_n.outputs['Color'], vcol_mult_n.inputs[1]) + ### TEXTURES ### + @staticmethod + def set_nmap_texture(node_tree, image): + """Set nmap texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assigned to nmap texture node + :type image: bpy.types.Texture + """ + + node_tree.nodes[InteriorLit.NMAP_TEX_NODE].image = image + + @staticmethod + def set_nmap_texture_settings(node_tree, settings): + """Set nmap texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + _material_utils.set_texture_settings_to_node(node_tree.nodes[InteriorLit.NMAP_TEX_NODE], settings) + + ### ATTRIBUTES ### @staticmethod def set_fresnel(node_tree, bias_scale): """Set fresnel bias and scale value to shader. @@ -125,7 +200,8 @@ def set_aux0(node_tree, aux_property): :param aux_property: TBA :type aux_property: bpy.types.IDPropertyGroup """ - pass # NOTE: TBA? + # NOTE: TBA? + pass # NOTE: aux doesn't change anything in rendered material, so pass it @staticmethod def set_aux1(node_tree, aux_property): @@ -136,7 +212,8 @@ def set_aux1(node_tree, aux_property): :param aux_property: TBA :type aux_property: bpy.types.IDPropertyGroup """ - pass # NOTE: TBA? + # NOTE: TBA? + pass # NOTE: aux doesn't change anything in rendered material, so pass it @staticmethod def set_aux2(node_tree, aux_property): @@ -164,3 +241,17 @@ def set_aux5(node_tree, aux_property): :type aux_property: bpy.types.IDPropertyGroup """ pass # NOTE: as this variant doesn't use luminance effect we just ignore this factor + + + # def made to override base texture settings, because overwriting "extension" in init doesn't work + @staticmethod + def set_base_texture_settings(node_tree, settings): + """Set base texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + + node_tree.nodes[DifSpecAddEnv.BASE_TEX_NODE].extension = 'REPEAT' diff --git a/addon/io_scs_tools/internals/shaders/eut2/shadowonly/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/shadowonly/__init__.py index 3a1799a..ace9ea2 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/shadowonly/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/shadowonly/__init__.py @@ -18,12 +18,19 @@ # Copyright (C) 2015-2019: SCS Software +from io_scs_tools.consts import Mesh as _MESH_consts from io_scs_tools.internals.shaders.base import BaseShader +from io_scs_tools.internals.shaders.flavors import alpha_test +from io_scs_tools.internals.shaders.std_node_groups import output_shader_ng +from io_scs_tools.utils import material as _material_utils class Shadowonly(BaseShader): COL_NODE = "Color" OUTPUT_NODE = "Output" + UVMAP_NODE = "FirstUVs" + BASE_TEX_NODE = "BaseTex" + OUT_MAT_NODE = "OutMaterial" @staticmethod def get_name(): @@ -44,18 +51,37 @@ def init(node_tree): pos_x_shift = 185 # node creation + uvmap_n = node_tree.nodes.new("ShaderNodeUVMap") + uvmap_n.name = uvmap_n.label = Shadowonly.UVMAP_NODE + uvmap_n.location = (start_pos_x - pos_x_shift, start_pos_y - 100) + uvmap_n.uv_map = _MESH_consts.none_uv + col_n = node_tree.nodes.new("ShaderNodeRGB") col_n.name = col_n.label = Shadowonly.COL_NODE col_n.location = (start_pos_x, start_pos_y) col_n.outputs['Color'].default_value = (0.01, 0, 0.01, 1.0) + base_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + base_tex_n.name = base_tex_n.label = Shadowonly.BASE_TEX_NODE + base_tex_n.location = (start_pos_x, start_pos_y - 200) + base_tex_n.width = 140 + + out_mat_node = node_tree.nodes.new("ShaderNodeGroup") + out_mat_node.name = out_mat_node.label = Shadowonly.OUT_MAT_NODE + out_mat_node.location = (start_pos_x + pos_x_shift, start_pos_y) + out_mat_node.node_tree = output_shader_ng.get_node_group() + output_n = node_tree.nodes.new("ShaderNodeOutputMaterial") output_n.name = output_n.label = Shadowonly.OUTPUT_NODE - output_n.location = (start_pos_x + pos_x_shift, start_pos_y) + output_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y) # links creation node_tree.links.new(output_n.inputs['Surface'], col_n.outputs['Color']) + node_tree.links.new(uvmap_n.outputs['UV'], base_tex_n.inputs['Vector']) + node_tree.links.new(col_n.outputs['Color'], out_mat_node.inputs['Color']) + node_tree.links.new(base_tex_n.outputs['Alpha'], out_mat_node.inputs['Alpha']) + @staticmethod def finalize(node_tree, material): """Finalize node tree and material settings. Should be called as last. @@ -69,6 +95,72 @@ def finalize(node_tree, material): material.use_backface_culling = True material.blend_method = "OPAQUE" + # set proper blend method and possible alpha test pass + if alpha_test.is_set(node_tree): + material.blend_method = "CLIP" + material.alpha_threshold = 0.05 + + # init parent + out_mat_node = node_tree.nodes[Shadowonly.OUT_MAT_NODE] + output_n = node_tree.nodes[Shadowonly.OUTPUT_NODE] + + # links creation + node_tree.links.new(out_mat_node.outputs['Shader'], output_n.inputs['Surface']) + + @staticmethod + def set_alpha_test_flavor(node_tree, switch_on): + """Set alpha test flavor to this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param switch_on: flag indication if alpha test should be switched on or off + :type switch_on: bool + """ + + if switch_on: + alpha_test.init(node_tree) + else: + alpha_test.delete(node_tree) + + @staticmethod + def set_base_texture(node_tree, image): + """Set base texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assignet to base texture node + :type image: bpy.types.Image + """ + if alpha_test.is_set(node_tree): + node_tree.nodes[Shadowonly.BASE_TEX_NODE].image = image + + @staticmethod + def set_base_texture_settings(node_tree, settings): + """Set base texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + if alpha_test.is_set(node_tree): + _material_utils.set_texture_settings_to_node(node_tree.nodes[Shadowonly.BASE_TEX_NODE], settings) + + @staticmethod + def set_base_uv(node_tree, uv_layer): + """Set UV layer to base texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for base texture + :type uv_layer: str + """ + if alpha_test.is_set(node_tree): + if uv_layer is None or uv_layer == "": + uv_layer = _MESH_consts.none_uv + + node_tree.nodes[Shadowonly.UVMAP_NODE].uv_map = uv_layer + @staticmethod def set_shadow_bias(node_tree, value): """Set shadow bias attirbute for this shader. diff --git a/addon/io_scs_tools/properties/material.py b/addon/io_scs_tools/properties/material.py index 1a361a3..4fed34c 100644 --- a/addon/io_scs_tools/properties/material.py +++ b/addon/io_scs_tools/properties/material.py @@ -342,9 +342,6 @@ def update_shader_attribute_tint(self, context): def update_shader_attribute_tint_opacity(self, context): __update_shader_attribute__(self, context, "tint_opacity") - - def update_shader_attribute_amod_decal_blending_factors(self, context): - __update_shader_attribute__(self, context, "amod_decal_blending_factors") def update_shader_texture_base(self, context): __update_shader_texture__(self, context, "base") @@ -715,18 +712,6 @@ def update_shader_texture_sky_weather_over_b_settings(self, context): options={'HIDDEN'}, update=update_shader_attribute_tint_opacity ) - - shader_attribute_amod_decal_blending_factors: FloatVectorProperty( - name="Amod Decal Blending Factors", - description="SCS shader 'Amod Blending' value", - default=(1.0, 1.0), - min=0, max=1, - step=1, precision=2, - options={'HIDDEN'}, - subtype='NONE', - size=2, - update=update_shader_attribute_amod_decal_blending_factors, - ) shader_attribute_queue_bias: IntProperty( name="Queue Bias", diff --git a/addon/io_scs_tools/shader_presets.txt b/addon/io_scs_tools/shader_presets.txt index 835f63f..f4950b3 100644 --- a/addon/io_scs_tools/shader_presets.txt +++ b/addon/io_scs_tools/shader_presets.txt @@ -1473,7 +1473,7 @@ Shader { Shader { PresetName: "shadowonly" Effect: "eut2.shadowonly" - Flavors: ( "NOCULL" ) + Flavors: ( "NOCULL" "SHDW_ALPHA" ) Flags: 0 Attribute { Format: FLOAT @@ -1793,9 +1793,9 @@ Shader { } Attribute { Format: FLOAT2 - Tag: "amod_decal_blending_factors" + Tag: "aux[0]" + FriendlyTag: "Decal blending factors" Value: ( 1.0 1.0 ) - Hide: "True" } Attribute { Format: FLOAT @@ -2020,6 +2020,15 @@ Flavor { Type: "ALPHA" Name: "a" } +Flavor { + Type: "SHDW_ALPHA" + Name: "a" + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } +} Flavor { Type: "ALTUV" Name: "altuv" @@ -2329,7 +2338,7 @@ Flavor { Attribute { Format: FLOAT4 Tag: "aux[0]" - FriendlyTag: "TexGen0 Scale (X,Z,ROT_BASE,ROT_NMAP)" + FriendlyTag: "TexGen0 (ScaleX, ScaleZ, Rotation, Unk)" Value: ( 10.0 10.0 0.0 0.0 ) } } @@ -2339,7 +2348,7 @@ Flavor { Attribute { Format: FLOAT4 Tag: "aux[1]" - FriendlyTag: "TexGen1 Scale (X,Z,ROT_BASE,ROT_NMAP)" + FriendlyTag: "TexGen1 (ScaleX, ScaleZ, Rotation, Unk)" Value: ( 8.0 8.0 0.0 0.0 ) } } From 0e17894a4b85a4ae33354a5979df94c37b817c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Tue, 5 Nov 2024 18:58:51 +0100 Subject: [PATCH 10/15] support for old tg0 & tg1 float2 * Added support for old tg0 (aux[0]) and tg1 (aux[1]) float2 values * Changed tool version (added ".1" to version number) to distinguish my edits from official SCS version. Author is also added. --- addon/io_scs_tools/__init__.py | 4 ++-- .../io_scs_tools/internals/shaders/eut2/dif/__init__.py | 9 ++++++--- .../shaders/eut2/dif_spec_mult_dif_spec/__init__.py | 9 ++++++--- .../shaders/eut2/dif_spec_over_dif_opac/__init__.py | 9 ++++++--- .../shaders/eut2/dif_spec_weight_mult2/__init__.py | 9 ++++++--- .../eut2/dif_spec_weight_mult2_weight2/__init__.py | 9 ++++++--- .../dif_spec_weight_weight_dif_spec_weight/__init__.py | 9 ++++++--- .../internals/shaders/eut2/dif_weight_dif/__init__.py | 9 ++++++--- addon/io_scs_tools/internals/shaders/flavors/tg0.py | 7 +++++-- addon/io_scs_tools/internals/shaders/flavors/tg1.py | 7 +++++-- 10 files changed, 54 insertions(+), 27 deletions(-) diff --git a/addon/io_scs_tools/__init__.py b/addon/io_scs_tools/__init__.py index e0df0a6..984e7bf 100644 --- a/addon/io_scs_tools/__init__.py +++ b/addon/io_scs_tools/__init__.py @@ -21,8 +21,8 @@ bl_info = { "name": "SCS Tools", "description": "Setup models, Import-Export SCS data format", - "author": "Simon Lusenc (50keda), Milos Zajic (4museman)", - "version": (2, 4, "aeadde03"), + "author": "Simon Lusenc (50keda), Milos Zajic (4museman), Michal (Michaleczeq)", + "version": (2, 4, "aeadde03", 1), "blender": (3, 2, 0), "location": "File > Import-Export", "doc_url": "http://modding.scssoft.com/wiki/Documentation/Tools/SCS_Blender_Tools", diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif/__init__.py index 1056dcb..d8d7344 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif/__init__.py @@ -501,7 +501,7 @@ def set_tg0_flavor(node_tree, switch_on): @staticmethod def set_aux0(node_tree, aux_property): - """Set zero texture generation scale. + """Set zero texture generation scale and rotation. :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree @@ -510,8 +510,11 @@ def set_aux0(node_tree, aux_property): """ if tg0.is_set(node_tree): - - tg0.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value']) + # Fix for old float2 aux[0] + if (len(aux_property)) == 2: + tg0.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], 0) + else: + tg0.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], aux_property[2]['value']) @staticmethod def set_flat_flavor(node_tree, switch_on): diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_mult_dif_spec/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_mult_dif_spec/__init__.py index 1791006..57e3eff 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_mult_dif_spec/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_mult_dif_spec/__init__.py @@ -167,7 +167,7 @@ def set_tg1_flavor(node_tree, switch_on): @staticmethod def set_aux1(node_tree, aux_property): - """Set second texture generation scale. + """Set second texture generation scale and rotation. :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree @@ -176,5 +176,8 @@ def set_aux1(node_tree, aux_property): """ if tg1.is_set(node_tree): - - tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value']) + # Fix for old float2 aux[1] + if (len(aux_property)) == 2: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], 0) + else: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], aux_property[2]['value']) diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_over_dif_opac/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_over_dif_opac/__init__.py index ef534de..9e66be4 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_over_dif_opac/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_over_dif_opac/__init__.py @@ -87,7 +87,7 @@ def init(node_tree): @staticmethod def set_aux1(node_tree, aux_property): - """Set second texture generation scale. + """Set second texture generation scale and rotation. :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree @@ -96,8 +96,11 @@ def set_aux1(node_tree, aux_property): """ if tg1.is_set(node_tree): - - tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value']) + # Fix for old float2 aux[1] + if (len(aux_property)) == 2: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], 0) + else: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], aux_property[2]['value']) @staticmethod def set_reflection2(node_tree, value): diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_mult2/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_mult2/__init__.py index 3522eef..25642f3 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_mult2/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_mult2/__init__.py @@ -191,7 +191,7 @@ def set_tg0_flavor(node_tree, switch_on): @staticmethod def set_aux0(node_tree, aux_property): - """Set zero texture generation scale. + """Set zero texture generation scale and rotation. :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree @@ -200,5 +200,8 @@ def set_aux0(node_tree, aux_property): """ if tg0.is_set(node_tree): - - tg0.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value']) + # Fix for old float2 aux[0] + if (len(aux_property)) == 2: + tg0.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], 0) + else: + tg0.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], aux_property[2]['value']) diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_mult2_weight2/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_mult2_weight2/__init__.py index d308976..24ca419 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_mult2_weight2/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_mult2_weight2/__init__.py @@ -362,7 +362,7 @@ def set_tg1_flavor(node_tree, switch_on): @staticmethod def set_aux1(node_tree, aux_property): - """Set second texture generation scale. + """Set second texture generation scale and rotation. :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree @@ -371,5 +371,8 @@ def set_aux1(node_tree, aux_property): """ if tg1.is_set(node_tree): - - tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value']) + # Fix for old float2 aux[1] + if (len(aux_property)) == 2: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], 0) + else: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], aux_property[2]['value']) diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_weight_dif_spec_weight/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_weight_dif_spec_weight/__init__.py index 43c8bfa..11caea1 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_weight_dif_spec_weight/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_weight_weight_dif_spec_weight/__init__.py @@ -250,7 +250,7 @@ def set_tg1_flavor(node_tree, switch_on): @staticmethod def set_aux1(node_tree, aux_property): - """Set second texture generation scale. + """Set second texture generation scale and rotation. :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree @@ -259,5 +259,8 @@ def set_aux1(node_tree, aux_property): """ if tg1.is_set(node_tree): - - tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value']) + # Fix for old float2 aux[1] + if (len(aux_property)) == 2: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], 0) + else: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], aux_property[2]['value']) diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_weight_dif/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_weight_dif/__init__.py index 19b84e6..218ce38 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/dif_weight_dif/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_weight_dif/__init__.py @@ -222,7 +222,7 @@ def set_tg1_flavor(node_tree, switch_on): @staticmethod def set_aux1(node_tree, aux_property): - """Set second texture generation scale. + """Set second texture generation scale and rotation. :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree @@ -231,5 +231,8 @@ def set_aux1(node_tree, aux_property): """ if tg1.is_set(node_tree): - - tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value']) + # Fix for old float2 aux[1] + if (len(aux_property)) == 2: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], 0) + else: + tg1.set_scale(node_tree, aux_property[0]['value'], aux_property[1]['value'], aux_property[2]['value']) diff --git a/addon/io_scs_tools/internals/shaders/flavors/tg0.py b/addon/io_scs_tools/internals/shaders/flavors/tg0.py index c0c2f83..d60248b 100644 --- a/addon/io_scs_tools/internals/shaders/flavors/tg0.py +++ b/addon/io_scs_tools/internals/shaders/flavors/tg0.py @@ -101,8 +101,8 @@ def is_set(node_tree): return FLAVOR_ID in node_tree.nodes -def set_scale(node_tree, scale_x, scale_y): - """Set scale of tex generation. +def set_scale(node_tree, scale_x, scale_y, rotation): + """Set scale and rotation of tex generation. :param node_tree: node tree which should be checked for existance of this flavor :type node_tree: bpy.types.NodeTree @@ -110,10 +110,13 @@ def set_scale(node_tree, scale_x, scale_y): :type scale_x: float :param scale_y: y coordinate scaling :type scale_y: float + :param rotation: base texture rotation + :type rotation: float """ vector_mapping_n = get_node(node_tree) if vector_mapping_n: + vector_mapping_n.inputs['Rotation'].default_value[2] = rotation / 57.3 vector_mapping_n.inputs['Scale'].default_value[0] = 1 / scale_x vector_mapping_n.inputs['Scale'].default_value[1] = 1 / scale_y diff --git a/addon/io_scs_tools/internals/shaders/flavors/tg1.py b/addon/io_scs_tools/internals/shaders/flavors/tg1.py index 2adae8d..3306c16 100644 --- a/addon/io_scs_tools/internals/shaders/flavors/tg1.py +++ b/addon/io_scs_tools/internals/shaders/flavors/tg1.py @@ -101,8 +101,8 @@ def is_set(node_tree): return FLAVOR_ID in node_tree.nodes -def set_scale(node_tree, scale_x, scale_y): - """Set scale of tex generation. +def set_scale(node_tree, scale_x, scale_y, rotation): + """Set scale and rotation of tex generation. :param node_tree: node tree which should be checked for existance of this flavor :type node_tree: bpy.types.NodeTree @@ -110,10 +110,13 @@ def set_scale(node_tree, scale_x, scale_y): :type scale_x: float :param scale_y: y coordinate scaling :type scale_y: float + :param rotation: base texture rotation + :type rotation: float """ vector_mapping_n = get_node(node_tree) if vector_mapping_n: + vector_mapping_n.inputs['Rotation'].default_value[2] = rotation / 57.3 vector_mapping_n.inputs['Scale'].default_value[0] = 1 / scale_x vector_mapping_n.inputs['Scale'].default_value[1] = 1 / scale_y From 0295b756ddbb2ee3adf456c2e112979ccadbd1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Fri, 29 Nov 2024 04:23:41 +0100 Subject: [PATCH 11/15] fixes, new shader, new tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Reverted "upside-down" envmap fix (caused problems elsewhere) * Fixed wrong order of “envmap” and “shadow” flavors in lamp shader * Fixed problems with exporting models with "interior" shader (missing UV1 in model data) by adding "Material Mapping" setting below attributes (need more testing) * Added "Interior Window Tool" in sidebar, which allows you to enable/disable glass reflection effect on interior shader (by changing UV tile). It's possible, that other shaders with "glass" reflections also support that. * Added support for "anim" flavor in "lamp" shader * Added support for "dif.spec.mult.dif.iamod.dif.add.env" shader --- addon/io_scs_tools/consts.py | 9 + addon/io_scs_tools/exp/pim/material.py | 20 ++ .../internals/shaders/eut2/__init__.py | 4 + .../__init__.py | 219 +++++++++++++++++ .../shaders/eut2/interior/__init__.py | 28 ++- .../eut2/std_node_groups/refl_normal_ng.py | 2 +- .../io_scs_tools/internals/shaders/shader.py | 36 ++- addon/io_scs_tools/operators/mesh.py | 75 ++++++ addon/io_scs_tools/properties/material.py | 223 +++++++++++++++++- addon/io_scs_tools/shader_presets.txt | 127 +++++++++- addon/io_scs_tools/supported_effects.bin | Bin 190943 -> 192085 bytes addon/io_scs_tools/ui/material.py | 99 +++++++- addon/io_scs_tools/ui/tool_shelf.py | 30 +++ addon/io_scs_tools/utils/material.py | 92 +++++++- 14 files changed, 946 insertions(+), 18 deletions(-) create mode 100644 addon/io_scs_tools/internals/shaders/eut2/dif_spec_mult_dif_iamod_dif_add_env/__init__.py diff --git a/addon/io_scs_tools/consts.py b/addon/io_scs_tools/consts.py index cf01780..acae933 100644 --- a/addon/io_scs_tools/consts.py +++ b/addon/io_scs_tools/consts.py @@ -227,6 +227,15 @@ class TrafficLightTypes(Enum): Yellow = 1 Green = 2 +class InteriorWindowTools: + """Constants related to interior window tools + """ + + class GlassReflection(Enum): + """Defined states of glass reflection. + """ + Enable = 0 + Disable = 1 class VertexColorTools: """Constants related to vertex color tools diff --git a/addon/io_scs_tools/exp/pim/material.py b/addon/io_scs_tools/exp/pim/material.py index 6cb9f68..3a7a1f0 100644 --- a/addon/io_scs_tools/exp/pim/material.py +++ b/addon/io_scs_tools/exp/pim/material.py @@ -101,6 +101,26 @@ def __init__(self, index, alias, effect, blend_mat): self.__used_textures_without_uv_count += 1 + if blend_mat and "scs_shader_attributes" in blend_mat and "mappings" in blend_mat["scs_shader_attributes"]: + for tex_entry in blend_mat["scs_shader_attributes"]["mappings"].values(): + self.__used_textures_count += 1 + if "Tag" in tex_entry: + tex_type = tex_entry["Tag"] + mappings = getattr(blend_mat.scs_props, "shader_mapping_" + tex_type, []) + + for uv_map_i, uv_map in enumerate(mappings): + if uv_map.value != "": # filter out none specified mappings + + tex_coord_map[uv_map.tex_coord] = uv_map.value + + elif uv_map.tex_coord != -1: # if tex coord is -1 texture doesn't use uvs + lprint("W Mapping type '%s' on material '%s' is missing UV mapping value, expect problems in game!", + (tex_type, blend_mat.name)) + + else: # if texture doesn't have mappings it means uv is not required for it + + self.__used_textures_without_uv_count += 1 + # create uv layer map with used tex_coord on it (this tex_coords now represents aliases for given uv layers) # It also uses ordered dictionary because order of keys now defines actually physical order for uvs in PIM file self.__uvs_map_by_name = OrderedDict() diff --git a/addon/io_scs_tools/internals/shaders/eut2/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/__init__.py index 4717ebb..c3e99f2 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/__init__.py @@ -152,6 +152,10 @@ def get_shader(effect): from io_scs_tools.internals.shaders.eut2.dif_spec_mult_dif_spec_iamod_dif_spec import DifSpecMultDifSpecIamodDifSpec as Shader + elif effect.startswith("dif.spec.mult.dif.iamod.dif.add.env"): + + from io_scs_tools.internals.shaders.eut2.dif_spec_mult_dif_iamod_dif_add_env import DifSpecMultDifIamodDifAddEnv as Shader + elif effect.startswith("dif.spec.mult.dif.spec.add.env"): from io_scs_tools.internals.shaders.eut2.dif_spec_mult_dif_spec.add_env import DifSpecMultDifSpecAddEnv as Shader diff --git a/addon/io_scs_tools/internals/shaders/eut2/dif_spec_mult_dif_iamod_dif_add_env/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_mult_dif_iamod_dif_add_env/__init__.py new file mode 100644 index 0000000..277571a --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/dif_spec_mult_dif_iamod_dif_add_env/__init__.py @@ -0,0 +1,219 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2015-2019: SCS Software + +from io_scs_tools.consts import Mesh as _MESH_consts +from io_scs_tools.internals.shaders.eut2.std_node_groups import alpha_remap_ng +from io_scs_tools.internals.shaders.eut2.dif_spec_mult_dif_spec import DifSpecMultDifSpec +from io_scs_tools.internals.shaders.eut2.std_passes.add_env import StdAddEnv +from io_scs_tools.utils import material as _material_utils + +class DifSpecMultDifIamodDifAddEnv(DifSpecMultDifSpec, StdAddEnv): + THIRD_UVMAP_NODE = "ThirdUVMap" + IAMOD_TEX_NODE = "IamodTex" + IAMOD_SCALE_NODE = "IamodScaled" + IAMOD_MULTBASE_COL_MIX_NODE = "IamodMultBaseColorMix" + REMAP_ALPHA_GNODE = "RemapAlphaToWeight" + + @staticmethod + def get_name(): + """Get name of this shader file with full modules path.""" + return __name__ + + @staticmethod + def init(node_tree): + """Initialize node tree with links for this shader. + + :param node_tree: node tree on which this shader should be created + :type node_tree: bpy.types.NodeTree + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + # init parent + DifSpecMultDifSpec.init(node_tree) + + # node creation + remap_alpha_n = node_tree.nodes.new("ShaderNodeGroup") + remap_alpha_n.name = remap_alpha_n.label = DifSpecMultDifSpec.REMAP_ALPHA_GNODE + remap_alpha_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1800) + remap_alpha_n.node_tree = alpha_remap_ng.get_node_group() + remap_alpha_n.inputs['Factor1'].default_value = 1.0 + remap_alpha_n.inputs['Factor2'].default_value = 0.0 + + StdAddEnv.add(node_tree, + DifSpecMultDifSpec.GEOM_NODE, + node_tree.nodes[DifSpecMultDifSpec.SPEC_COL_NODE].outputs['Color'], + node_tree.nodes[DifSpecMultDifSpec.REMAP_ALPHA_GNODE].outputs['Weighted Alpha'], + node_tree.nodes[DifSpecMultDifSpec.LIGHTING_EVAL_NODE].outputs['Normal'], + node_tree.nodes[DifSpecMultDifSpec.COMPOSE_LIGHTING_NODE].inputs['Env Color']) + + base_tex_n = node_tree.nodes[DifSpecMultDifSpec.BASE_TEX_NODE] + mult_tex_n = node_tree.nodes[DifSpecMultDifSpec.MULT_TEX_NODE] + add_env_gn = node_tree.nodes[StdAddEnv.ADD_ENV_GROUP_NODE] + + vcol_group_n = node_tree.nodes[DifSpecMultDifSpec.VCOL_GROUP_NODE] + mult_base_col_mix_n = node_tree.nodes[DifSpecMultDifSpec.MULT_BASE_COL_MIX_NODE] + vcol_scale_n = node_tree.nodes[DifSpecMultDifSpec.VCOLOR_SCALE_NODE] + vcol_mult_n = node_tree.nodes[DifSpecMultDifSpec.VCOLOR_MULT_NODE] + diff_mult_n = node_tree.nodes[DifSpecMultDifSpec.DIFF_MULT_NODE] + spec_mult_n = node_tree.nodes[DifSpecMultDifSpec.SPEC_MULT_NODE] + + # delete existing + node_tree.nodes.remove(node_tree.nodes[DifSpecMultDifIamodDifAddEnv.MULT_BASE_A_MIX_NODE]) + + # move existing + spec_mult_n.location.x += pos_x_shift + spec_mult_n.location.x -= pos_x_shift * 2 + + vcol_scale_n.location.y -= 200 + vcol_mult_n.location.y -= 200 + diff_mult_n.location.y -= 200 + mult_base_col_mix_n.location.y -= 200 + + # node creation + third_uvmap_n = node_tree.nodes.new("ShaderNodeUVMap") + third_uvmap_n.name = DifSpecMultDifIamodDifAddEnv.THIRD_UVMAP_NODE + third_uvmap_n.label = DifSpecMultDifIamodDifAddEnv.THIRD_UVMAP_NODE + third_uvmap_n.location = (start_pos_x - pos_x_shift, start_pos_y + 900) + third_uvmap_n.uv_map = _MESH_consts.none_uv + + iamod_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + iamod_tex_n.name = DifSpecMultDifIamodDifAddEnv.IAMOD_TEX_NODE + iamod_tex_n.label = DifSpecMultDifIamodDifAddEnv.IAMOD_TEX_NODE + iamod_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 900) + iamod_tex_n.width = 140 + + iamod_scale_col_n = node_tree.nodes.new("ShaderNodeMixRGB") + iamod_scale_col_n.name = DifSpecMultDifIamodDifAddEnv.IAMOD_SCALE_NODE + iamod_scale_col_n.label = DifSpecMultDifIamodDifAddEnv.IAMOD_SCALE_NODE + iamod_scale_col_n.location = (start_pos_x + pos_x_shift * 3, start_pos_y + 1000) + iamod_scale_col_n.blend_type = "MIX" + iamod_scale_col_n.inputs['Color2'].default_value = (1,) * 4 + + iamod_multbase_col_mix_n = node_tree.nodes.new("ShaderNodeVectorMath") + iamod_multbase_col_mix_n.name = DifSpecMultDifIamodDifAddEnv.IAMOD_MULTBASE_COL_MIX_NODE + iamod_multbase_col_mix_n.label = DifSpecMultDifIamodDifAddEnv.IAMOD_MULTBASE_COL_MIX_NODE + iamod_multbase_col_mix_n.location = (start_pos_x + pos_x_shift * 4, start_pos_y + 1100) + iamod_multbase_col_mix_n.operation = "MULTIPLY" + + # links creation + node_tree.links.new(add_env_gn.inputs['Strength Multiplier'], mult_tex_n.outputs['Alpha']) + node_tree.links.new(remap_alpha_n.inputs['Alpha'], base_tex_n.outputs['Alpha']) + + node_tree.links.new(iamod_tex_n.inputs['Vector'], third_uvmap_n.outputs['UV']) + + node_tree.links.new(iamod_scale_col_n.inputs['Fac'], vcol_group_n.outputs['Vertex Color Alpha']) + node_tree.links.new(iamod_scale_col_n.inputs['Color1'], iamod_tex_n.outputs['Color']) + + node_tree.links.new(iamod_multbase_col_mix_n.inputs[0], mult_base_col_mix_n.outputs['Vector']) + node_tree.links.new(iamod_multbase_col_mix_n.inputs[1], iamod_scale_col_n.outputs['Color']) + + node_tree.links.new(vcol_mult_n.inputs[1], iamod_multbase_col_mix_n.outputs['Vector']) + + node_tree.links.new(spec_mult_n.inputs[1], remap_alpha_n.outputs['Weighted Alpha']) + + @staticmethod + def set_iamod_texture(node_tree, image): + """Set inverse alpha modulating texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assigned to iamod texture node + :type image: bpy.types.Texture + """ + + node_tree.nodes[DifSpecMultDifIamodDifAddEnv.IAMOD_TEX_NODE].image = image + + @staticmethod + def set_iamod_texture_settings(node_tree, settings): + """Set inverse alpha modulating texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + _material_utils.set_texture_settings_to_node(node_tree.nodes[DifSpecMultDifIamodDifAddEnv.IAMOD_TEX_NODE], settings) + + @staticmethod + def set_iamod_uv(node_tree, uv_layer): + """Set UV layer to inverse alpha modulating texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for iamod texture + :type uv_layer: str + """ + + if uv_layer is None or uv_layer == "": + uv_layer = _MESH_consts.none_uv + + node_tree.nodes[DifSpecMultDifIamodDifAddEnv.THIRD_UVMAP_NODE].uv_map = uv_layer + + @staticmethod + def set_alpha_test_flavor(node_tree, switch_on): + """Set alpha test flavor to this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param switch_on: flag indication if alpha test should be switched on or off + :type switch_on: bool + """ + + pass # NOTE: no support for this flavor; overriding with empty function + + @staticmethod + def set_blend_over_flavor(node_tree, switch_on): + """Set blend over flavor to this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param switch_on: flag indication if blend over should be switched on or off + :type switch_on: bool + """ + + pass # NOTE: no support for this flavor; overriding with empty function + + @staticmethod + def set_blend_add_flavor(node_tree, switch_on): + """Set blend add flavor to this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param switch_on: flag indication if blend add should be switched on or off + :type switch_on: bool + """ + + pass # NOTE: no support for this flavor; overriding with empty function + + @staticmethod + def set_blend_mult_flavor(node_tree, switch_on): + """Set blend mult flavor to this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param switch_on: flag indication if blend mult should be switched on or off + :type switch_on: bool + """ + + pass # NOTE: no support for this flavor; overriding with empty function diff --git a/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py index b6316bd..6e6430d 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py @@ -18,6 +18,7 @@ # Copyright (C) 2015-2024: SCS Software +from io_scs_tools.consts import Mesh as _MESH_consts from io_scs_tools.internals.shaders.eut2.parameters import get_fresnel_window from io_scs_tools.internals.shaders.eut2.dif_spec_add_env import DifSpecAddEnv from io_scs_tools.utils import material as _material_utils @@ -33,6 +34,7 @@ class InteriorLit(DifSpecAddEnv): NMAP_TEX_NODE = "NmapTex" ENV_SEP_XYZ_NODE = "EnvSepXYZ" ENV_CHECK_XYZ_NODE = "EnvCheckXYZ" + PERTURBATION_UVMAP_NODE = "PerturbationUVMap" @staticmethod @@ -65,9 +67,6 @@ def init(node_tree): # set fresnel type to schlick add_env_group_n.inputs['Fresnel Type'].default_value = 1.0 - # Doesn't work... - # node_tree.nodes[DifSpecAddEnv.BASE_TEX_NODE].extension = 'REPEAT' - # delete existing node_tree.nodes.remove(node_tree.nodes[DifSpecAddEnv.OPACITY_NODE]) @@ -76,6 +75,12 @@ def init(node_tree): vcol_mult_n.location.x += pos_x_shift # node creation + # - column -1 - + pert_uv_n = node_tree.nodes.new("ShaderNodeUVMap") + pert_uv_n.name = pert_uv_n.label = InteriorLit.PERTURBATION_UVMAP_NODE + pert_uv_n.location = (start_pos_x - pos_x_shift, start_pos_y + 950) + pert_uv_n.uv_map = _MESH_consts.none_uv + # - column 0 - env_sep_xyz_n = node_tree.nodes.new("ShaderNodeSeparateXYZ") env_sep_xyz_n.name = env_sep_xyz_n.label = InteriorLit.ENV_SEP_XYZ_NODE @@ -92,6 +97,7 @@ def init(node_tree): glass_col_n.name = glass_col_n.label = InteriorLit.GLASS_COL_NODE glass_col_n.location = (start_pos_x + pos_x_shift, start_pos_y + 900) + """ layer0_tex_n = node_tree.nodes.new("ShaderNodeTexImage") layer0_tex_n.name = layer0_tex_n.label = InteriorLit.LAYER0_TEX_NODE layer0_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 700) @@ -111,6 +117,7 @@ def init(node_tree): nmap_tex_n.name = nmap_tex_n.label = InteriorLit.NMAP_TEX_NODE nmap_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y - 50) nmap_tex_n.width = 140 + """ # - column 2 - glass_col_fac_n = node_tree.nodes.new("ShaderNodeValue") @@ -255,3 +262,18 @@ def set_base_texture_settings(node_tree, settings): """ node_tree.nodes[DifSpecAddEnv.BASE_TEX_NODE].extension = 'REPEAT' + + @staticmethod + def set_perturbation_mapping(node_tree, uv_layer): + """Set Perturbation UV layer to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for base texture + :type uv_layer: str + """ + + if uv_layer is None or uv_layer == "": + uv_layer = _MESH_consts.none_uv + + node_tree.nodes[InteriorLit.PERTURBATION_UVMAP_NODE].uv_map = uv_layer diff --git a/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/refl_normal_ng.py b/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/refl_normal_ng.py index 5216457..15215bb 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/refl_normal_ng.py +++ b/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/refl_normal_ng.py @@ -61,7 +61,7 @@ def __create_refl_normal_group__(): view_vector_n = refl_normal_g.nodes.new("ShaderNodeVectorMath") view_vector_n.location = (185, 250) view_vector_n.operation = "MULTIPLY" - view_vector_n.inputs[1].default_value = (-1,1,1) + view_vector_n.inputs[1].default_value = (-1,) * 3 view_vector_norm_n = refl_normal_g.nodes.new("ShaderNodeVectorMath") view_vector_norm_n.location = (185 * 2, 250) diff --git a/addon/io_scs_tools/internals/shaders/shader.py b/addon/io_scs_tools/internals/shaders/shader.py index 2c69859..08a7efc 100644 --- a/addon/io_scs_tools/internals/shaders/shader.py +++ b/addon/io_scs_tools/internals/shaders/shader.py @@ -110,7 +110,7 @@ def setup_nodes(material, effect, attr_dict, tex_dict, tex_settings_dict, recrea if effect.endswith(".flipsheet") or ".flipsheet." in effect: flavors["flipsheet"] = True - __setup_nodes__(material, effect, attr_dict, tex_dict, tex_settings_dict, {}, flavors, recreate) + __setup_nodes__(material, effect, attr_dict, tex_dict, tex_settings_dict, {}, {}, flavors, recreate) def set_attribute(material, attr_type, attr_value): @@ -123,7 +123,7 @@ def set_attribute(material, attr_type, attr_value): :param attr_value: value which should be set to attribute in shader :type attr_value: object """ - __setup_nodes__(material, material.scs_props.mat_effect_name, {attr_type: attr_value}, {}, {}, {}, {}, False) + __setup_nodes__(material, material.scs_props.mat_effect_name, {attr_type: attr_value}, {}, {}, {}, {}, {}, False) def set_texture(material, tex_type, image): @@ -136,7 +136,7 @@ def set_texture(material, tex_type, image): :param image: blender texture image object :type image: bpy.types.Image """ - __setup_nodes__(material, material.scs_props.mat_effect_name, {}, {tex_type: image}, {}, {}, {}, False) + __setup_nodes__(material, material.scs_props.mat_effect_name, {}, {tex_type: image}, {}, {}, {}, {}, False) def set_texture_settings(material, tex_type, settings): @@ -149,7 +149,7 @@ def set_texture_settings(material, tex_type, settings): :param settings: binary string of TOBJ settings gotten from tobj import :type settings: str """ - __setup_nodes__(material, material.scs_props.mat_effect_name, {}, {}, {tex_type: settings}, {}, {}, False) + __setup_nodes__(material, material.scs_props.mat_effect_name, {}, {}, {tex_type: settings}, {}, {}, {}, False) def set_uv(material, tex_type, uv_layer, tex_coord): @@ -188,10 +188,24 @@ def set_uv(material, tex_type, uv_layer, tex_coord): is_valid_input = False if is_valid_input: - __setup_nodes__(material, material.scs_props.mat_effect_name, {}, {}, {}, {tex_type: uv_layer}, {}, False) + __setup_nodes__(material, material.scs_props.mat_effect_name, {}, {}, {}, {tex_type: uv_layer}, {}, {}, False) +def set_mapping(material, mapping_type, uv_layer, tex_coord): + """Set UV layer to given texture type in material. -def __setup_nodes__(material, effect, attr_dict, tex_dict, tex_settings_dict, uvs_dict, flavors_dict, recreate): + :param material: blender material + :type material: bpy.types.Material + :param mapping_type: type of SCS mapping to set + :type mapping_type: str + :param uv_layer: uv layer name which should be assigned to this texture + :type uv_layer: str + :param tex_coord: index of tex_coord this mapping uses + :type tex_coord: int + """ + + __setup_nodes__(material, material.scs_props.mat_effect_name, {}, {}, {}, {}, {mapping_type: uv_layer}, {}, False) + +def __setup_nodes__(material, effect, attr_dict, tex_dict, tex_settings_dict, uvs_dict, mapping_dict, flavors_dict, recreate): """Wrapping setup of nodes for given material in central function. It properly setup nodes for 3D view visualization in real time. @@ -207,6 +221,8 @@ def __setup_nodes__(material, effect, attr_dict, tex_dict, tex_settings_dict, uv :type tex_settings_dict: dict :param uvs_dict: shader uv layers which should be set on given material; entry: (texture_type: string of uv layer) :type uvs_dict: dict + :param mapping_dict: shader uv layers which should be set on given material; entry: (texture_type: string of uv layer) + :type mapping_dict: dict :param flavors_dict: shader flavors which should be set on given material; entry: (flavor_type: flavor_data) :type flavors_dict: dict :param recreate: flag indicating if shader nodes should be recreated. Should be triggered if effect name changes. @@ -265,6 +281,14 @@ def __setup_nodes__(material, effect, attr_dict, tex_dict, tex_settings_dict, uv else: lprint("D Unsupported set_uv with type %r called on shader %r", (tex_type, shader_module.get_name())) + # set mappings + for mapping_type in mapping_dict: + shader_set_mapping = getattr(shader_module, "set_" + mapping_type + "_mapping", None) + if shader_set_mapping: + shader_set_mapping(node_tree, mapping_dict[mapping_type]) + else: + lprint("D Unsupported set_mapping with type %r called on shader %r", (mapping_type, shader_module.get_name())) + # finalize shader on recreate (set material blending method, backface culling etc.) if recreate: shader_module.finalize(node_tree, material) diff --git a/addon/io_scs_tools/operators/mesh.py b/addon/io_scs_tools/operators/mesh.py index b6ec3cc..62b484f 100644 --- a/addon/io_scs_tools/operators/mesh.py +++ b/addon/io_scs_tools/operators/mesh.py @@ -26,6 +26,7 @@ from bpy.props import StringProperty, FloatProperty from io_scs_tools.consts import Mesh as _MESH_consts from io_scs_tools.consts import LampTools as _LT_consts +from io_scs_tools.consts import InteriorWindowTools as _IWT_consts from io_scs_tools.consts import VertexColorTools as _VCT_consts from io_scs_tools.utils import mesh as _mesh_utils from io_scs_tools.utils import view3d as _view3d_utils @@ -136,6 +137,78 @@ def execute(self, context): self.report({"INFO"}, "Lamp mask UV tool set %i faces to '%s'" % (polys_changed, changed_type)) return {'FINISHED'} +class InteriorWindowTool: + """ + Wrapper class for better navigation in file + """ + + class SCS_TOOLS_OT_SetGlassReflectionUV(bpy.types.Operator): + bl_label = "Set UV to glass" + bl_idname = "mesh.scs_tools_set_glassreflection_uv" + bl_description = "Sets offset for base interior UV according to given glass reflection state." + + glass_state: StringProperty( + description="", + default="", + options={'HIDDEN'}, + ) + + @classmethod + def poll(cls, context): + return context.object is not None and context.object.mode == "EDIT" + + def execute(self, context): + mesh = context.object.data + bm = bmesh.from_edit_mesh(mesh) # use bmesh module because we are working in edit mode + + # decide which offset to use depending on glass reflection state + offset_x = 0 + offset_y = 0 + if _IWT_consts.GlassReflection.Enable.name == self.glass_state: # glass reflection state checking + offset_y = 0 + elif _IWT_consts.GlassReflection.Disable.name == self.glass_state: + offset_y = 1 + else: + self.report({"ERROR"}, "Unsupported window glass state!") + return {"FINISHED"} + + polys_changed = 0 + for face in bm.faces: + + if face.select and len(context.object.material_slots) > 0: + material = context.object.material_slots[face.material_index].material + if material and len(material.scs_props.shader_texture_mask_uv) > 0: + + # use first mapping from mask texture + uv_lay_name = material.scs_props.shader_texture_mask_uv[0].value + + # if mask uv layer specified by current material doesn't exists + # move to next face + if uv_lay_name not in mesh.uv_layers: + self.report({"ERROR"}, "UV layer: '%s' not found in this object!" % uv_lay_name) + break + + uv_lay = bm.loops.layers.uv[uv_lay_name] + for loop in face.loops: + + uv = loop[uv_lay].uv + uv = (offset_x + (uv[0] - int(uv[0])), offset_y + (uv[1] - int(uv[1]))) + loop[uv_lay].uv = uv + + polys_changed += 1 + + # write data back if modified + if polys_changed > 0: + bmesh.update_edit_mesh(mesh) + + if self.glass_state != "": + changed_type = self.glass_state + else: + changed_type = "INVALID" + + self.report({"INFO"}, "Interior Window Tool set %i faces to '%s'" % (polys_changed, changed_type)) + return {'FINISHED'} + class VertexColorTools: """ @@ -658,6 +731,8 @@ def execute(self, context): classes = ( LampTool.SCS_TOOLS_OT_SetLampmaskUV, + InteriorWindowTool.SCS_TOOLS_OT_SetGlassReflectionUV, + VertexColorTools.SCS_TOOLS_OT_AddVertexColorsToActive, VertexColorTools.SCS_TOOLS_OT_AddVertexColorsToAll, VertexColorTools.SCS_TOOLS_OT_PrintVertexColorsStats, diff --git a/addon/io_scs_tools/properties/material.py b/addon/io_scs_tools/properties/material.py index 4fed34c..dec2bcb 100644 --- a/addon/io_scs_tools/properties/material.py +++ b/addon/io_scs_tools/properties/material.py @@ -238,6 +238,42 @@ def update_value(self, context): tex_coord: IntProperty(default=-1) # used upon export for mapping uv to tex_coord field texture_type: StringProperty() # used in update function to be able to identify which texture should be updated + class UVAddMappingItem(bpy.types.PropertyGroup): + """Class for saving uv map reference for SCS mapping + """ + + def update_value(self, context): + __update_look__(self, context) + + material = _material_utils.get_material_from_context(context) + + if material: + _shader.set_mapping(material, self.mapping_type, self.value, self.tex_coord) + + # synchronize all scs mappings that uses the same tex_coord field in current material + if "scs_shader_attributes" in material and "mappings" in material["scs_shader_attributes"]: + for mapping_entry in material["scs_shader_attributes"]["mappings"].values(): + if "Tag" in mapping_entry: + curr_map_type = mapping_entry["Tag"] + if curr_map_type != self.mapping_type: # if different mapping from current + uv_mappings = getattr(material.scs_props, "shader_mapping_" + curr_map_type, []) + if uv_mappings and len(uv_mappings) > 0: + for uv_mapping in uv_mappings: + # if tex_coord props are the same and uv mapping differs then set current uv mapping value to it + if self.tex_coord != -1 and uv_mapping.tex_coord == self.tex_coord and uv_mapping.value != self.value: + uv_mapping.value = self.value + + value: StringProperty( + name="Mapping UV Set", + description="Mapping of UV Set to current mapping type", + default="", + options={'HIDDEN'}, + update=update_value + ) + + tex_coord: IntProperty(default=-1) # used upon export for mapping uv to tex_coord field + mapping_type: StringProperty() # used in update function to be able to identify which mapping should be updated + class TexCoordItem(bpy.types.PropertyGroup): """Property group holding data how to map uv maps to exported PIM file. It should be used only on material with imported shader. """ @@ -271,10 +307,9 @@ def get_texture_types(): :return: SCS Shader Texture Types :rtype: dict """ - return {'base', 'reflection', 'over', 'oclu', 'mask', 'mult', 'iamod', 'lightmap', 'paintjob', - 'flakenoise', 'nmap', 'base_1', 'mult_1', 'detail', 'nmap_detail', 'layer0', 'layer1', - 'sky_weather_base_a', 'sky_weather_base_b', 'sky_weather_over_a', 'sky_weather_over_b', - 'nmap_over'} + return {'base', 'reflection', 'over', 'oclu', 'mask' , 'mask_1' , 'mask_2', 'mask_3', 'mult', 'iamod', 'lightmap', 'paintjob', + 'flakenoise', 'nmap', 'base_1', 'mult_1', 'detail', 'nmap_detail', 'nmap_over' , 'layer0', 'layer1', + 'sky_weather_base_a', 'sky_weather_base_b', 'sky_weather_over_a', 'sky_weather_over_b'} def get_id(self): """Gets unique ID for material within current Blend file. If ID does not exists yet it's calculated. @@ -397,6 +432,24 @@ def update_shader_texture_mask(self, context): def update_shader_texture_mask_settings(self, context): __update_shader_texture_tobj_file__(self, context, "mask") + def update_shader_texture_mask_1(self, context): + __update_shader_texture__(self, context, "mask_1") + + def update_shader_texture_mask_1_settings(self, context): + __update_shader_texture_tobj_file__(self, context, "mask_1") + + def update_shader_texture_mask_2(self, context): + __update_shader_texture__(self, context, "mask_2") + + def update_shader_texture_mask_2_settings(self, context): + __update_shader_texture_tobj_file__(self, context, "mask_2") + + def update_shader_texture_mask_3(self, context): + __update_shader_texture__(self, context, "mask_3") + + def update_shader_texture_mask_3_settings(self, context): + __update_shader_texture_tobj_file__(self, context, "mask_3") + def update_shader_texture_mult(self, context): __update_shader_texture__(self, context, "mult") @@ -1183,6 +1236,159 @@ def update_shader_texture_sky_weather_over_b_settings(self, context): options={'HIDDEN'}, ) + # TEXTURE: MASK_1 + shader_texture_mask_1: StringProperty( + name="Texture Mask", + description="Texture Mask for active Material", + default=_MAT_consts.unset_bitmap_filepath, + options={'HIDDEN'}, + subtype='NONE', + update=update_shader_texture_mask_1, + ) + shader_texture_mask_1_imported_tobj: StringProperty( + name="Imported TOBJ Path", + description="Use imported TOBJ path reference which will be exported into material (NOTE: export will not take care of any TOBJ files!)", + default="", + update=__update_look__ + ) + shader_texture_mask_1_locked: BoolProperty( + name="Texture Locked", + description="Tells if texture is locked and should not be changed by user(intended for internal usage only)", + default=False + ) + shader_texture_mask_1_map_type: StringProperty( + name="Texture Map Type", + description="Stores texture mapping type and should not be changed by user(intended for internal usage only)", + default="2d" + ) + shader_texture_mask_1_settings: EnumProperty( + name="Settings", + description="TOBJ settings for this texture", + items=__get_texture_settings__(), + default=set(), + options={'ENUM_FLAG'}, + update=update_shader_texture_mask_1_settings + ) + shader_texture_mask_1_tobj_load_time: StringProperty( + name="Last TOBJ load time", + description="Time string of last loading", + default="", + ) + shader_texture_mask_1_use_imported: BoolProperty( + name="Use Imported", + description="Use custom provided path for TOBJ reference", + default=False, + update=__update_look__ + ) + shader_texture_mask_1_uv: CollectionProperty( + name="Texture Mask UV Sets", + description="Texture Mask UV sets for active Material", + type=UVMappingItem, + options={'HIDDEN'}, + ) + + # TEXTURE: MASK_2 + shader_texture_mask_2: StringProperty( + name="Texture Mask", + description="Texture Mask for active Material", + default=_MAT_consts.unset_bitmap_filepath, + options={'HIDDEN'}, + subtype='NONE', + update=update_shader_texture_mask_2, + ) + shader_texture_mask_2_imported_tobj: StringProperty( + name="Imported TOBJ Path", + description="Use imported TOBJ path reference which will be exported into material (NOTE: export will not take care of any TOBJ files!)", + default="", + update=__update_look__ + ) + shader_texture_mask_2_locked: BoolProperty( + name="Texture Locked", + description="Tells if texture is locked and should not be changed by user(intended for internal usage only)", + default=False + ) + shader_texture_mask_2_map_type: StringProperty( + name="Texture Map Type", + description="Stores texture mapping type and should not be changed by user(intended for internal usage only)", + default="2d" + ) + shader_texture_mask_2_settings: EnumProperty( + name="Settings", + description="TOBJ settings for this texture", + items=__get_texture_settings__(), + default=set(), + options={'ENUM_FLAG'}, + update=update_shader_texture_mask_2_settings + ) + shader_texture_mask_2_tobj_load_time: StringProperty( + name="Last TOBJ load time", + description="Time string of last loading", + default="", + ) + shader_texture_mask_2_use_imported: BoolProperty( + name="Use Imported", + description="Use custom provided path for TOBJ reference", + default=False, + update=__update_look__ + ) + shader_texture_mask_2_uv: CollectionProperty( + name="Texture Mask UV Sets", + description="Texture Mask UV sets for active Material", + type=UVMappingItem, + options={'HIDDEN'}, + ) + + # TEXTURE: MASK_3 + shader_texture_mask_3: StringProperty( + name="Texture Mask", + description="Texture Mask for active Material", + default=_MAT_consts.unset_bitmap_filepath, + options={'HIDDEN'}, + subtype='NONE', + update=update_shader_texture_mask_3, + ) + shader_texture_mask_3_imported_tobj: StringProperty( + name="Imported TOBJ Path", + description="Use imported TOBJ path reference which will be exported into material (NOTE: export will not take care of any TOBJ files!)", + default="", + update=__update_look__ + ) + shader_texture_mask_3_locked: BoolProperty( + name="Texture Locked", + description="Tells if texture is locked and should not be changed by user(intended for internal usage only)", + default=False + ) + shader_texture_mask_3_map_type: StringProperty( + name="Texture Map Type", + description="Stores texture mapping type and should not be changed by user(intended for internal usage only)", + default="2d" + ) + shader_texture_mask_3_settings: EnumProperty( + name="Settings", + description="TOBJ settings for this texture", + items=__get_texture_settings__(), + default=set(), + options={'ENUM_FLAG'}, + update=update_shader_texture_mask_3_settings + ) + shader_texture_mask_3_tobj_load_time: StringProperty( + name="Last TOBJ load time", + description="Time string of last loading", + default="", + ) + shader_texture_mask_3_use_imported: BoolProperty( + name="Use Imported", + description="Use custom provided path for TOBJ reference", + default=False, + update=__update_look__ + ) + shader_texture_mask_3_uv: CollectionProperty( + name="Texture Mask UV Sets", + description="Texture Mask UV sets for active Material", + type=UVMappingItem, + options={'HIDDEN'}, + ) + # TEXTURE: MULT shader_texture_mult: StringProperty( name="Texture Mult", @@ -1846,6 +2052,14 @@ def update_shader_texture_sky_weather_over_b_settings(self, context): options={'HIDDEN'}, ) + # MAPPING: PERTURBATION + shader_mapping_perturbation: CollectionProperty( + name="Perturbation UV Sets", + description="Perturbation UV sets for active Material", + type=UVAddMappingItem, + options={'HIDDEN'}, + ) + # # Following String property is fed from MATERIAL SUBSTANCE data list, which is usually loaded from # # "//base/material/material.db" file and stored at "scs_inventories.matsubs". substance: StringProperty( @@ -1861,6 +2075,7 @@ def update_shader_texture_sky_weather_over_b_settings(self, context): MaterialSCSTools.TexCoordItem, MaterialSCSTools.AuxiliaryItem, MaterialSCSTools.UVMappingItem, + MaterialSCSTools.UVAddMappingItem, MaterialSCSTools ) diff --git a/addon/io_scs_tools/shader_presets.txt b/addon/io_scs_tools/shader_presets.txt index f4950b3..b134225 100644 --- a/addon/io_scs_tools/shader_presets.txt +++ b/addon/io_scs_tools/shader_presets.txt @@ -656,6 +656,67 @@ Shader { TexCoord: ( -1 ) } } +Shader { + PresetName: "dif.spec.mult.dif.iamod.dif.add.env" + Effect: "eut2.dif.spec.mult.dif.iamod.dif.add.env" + Flavors: ( "NMAP_TS|NMAP_TS_UV|NMAP_TS_16|NMAP_TS_UV_16" ) + Flags: 0 + Attribute { + Format: FLOAT3 + Tag: "diffuse" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT3 + Tag: "specular" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT + Tag: "shininess" + Value: ( 60.0 ) + } + Attribute { + Format: FLOAT + Tag: "add_ambient" + Value: ( 0.0 ) + } + Attribute { + Format: FLOAT + Tag: "reflection" + Value: ( 0.0 ) + } + Attribute { + Format: FLOAT2 + Tag: "fresnel" + Value: ( 0.2 0.9 ) + } + Attribute { + Format: FLOAT3 + Tag: "env_factor" + Value: ( 0.8000000119 0.8000000119 0.8000000119 ) + } + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_mult" + Value: "" + TexCoord: ( 1 ) + } + Texture { + Tag: "texture[X]:texture_iamod" + Value: "" + TexCoord: ( 2 ) + } + Texture { + Tag: "texture[X]:texture_reflection" + Value: "/material/environment/building_reflection/building_ref" + TexCoord: ( -1 ) + } +} Shader { PresetName: "dif.spec.mult.dif.spec.iamod.dif.spec" Effect: "eut2.dif.spec.mult.dif.spec.iamod.dif.spec" @@ -1321,7 +1382,7 @@ Shader { Shader { PresetName: "lamp" Effect: "eut2.lamp" - Flavors: ( "NMAP_TS|NMAP_TS_UV|NMAP_TS_16|NMAP_TS_UV_16" "ENVMAP" "SHADOW" ) + Flavors: ( "ANIM" "NMAP_TS|NMAP_TS_UV|NMAP_TS_16|NMAP_TS_UV_16" "SHADOW" "ENVMAP" ) Flags: 0 Attribute { Format: FLOAT3 @@ -1911,6 +1972,10 @@ Shader { Value: "/material/environment/building_reflection/building_ref" TexCoord: ( -1 ) } + Mapping { + Tag: "perturbation" + TexCoord: ( 1 ) + } } Shader { PresetName: "interior.curtain.lit" @@ -2000,6 +2065,11 @@ Shader { Value: "/material/environment/building_reflection/building_ref" TexCoord: ( -1 ) } + Mapping { + Tag: "perturbation" + TexCoord: ( 1 ) + } +} } Flavor { Type: "AIRBRUSH" @@ -2118,6 +2188,25 @@ Flavor { TexCoord: ( -1 ) } } +Flavor { + Type: "ENVMAP_NOFAC" + Name: "add.env" + Attribute { + Format: FLOAT2 + Tag: "fresnel" + Value: ( 0.2 0.9 ) + } + Texture { + Tag: "texture[X]:texture_mask" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_reflection" + Value: "/material/environment/vehicle_reflection" + TexCoord: ( -1 ) + } +} Flavor { Type: "FADESHEET" Name: "fadesheet" @@ -2164,6 +2253,42 @@ Flavor { Hide: "True" } } +Flavor { + Type: "ANIM" + Name: "anim" + Attribute { + Format: FLOAT4 + Tag: "aux[0]" + FriendlyTag: "Sheet frame size (R, G)" + Value: ( 1.0 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT4 + Tag: "aux[1]" + FriendlyTag: "Sheet frame size (B, A)" + Value: ( 1.0 1.0 1.0 1.0 ) + } + Texture { + Tag: "texture[X]:texture_mask" + Value: "" + TexCoord: ( 1 ) + } + Texture { + Tag: "texture[X]:texture_mask_1" + Value: "" + TexCoord: ( 1 ) + } + Texture { + Tag: "texture[X]:texture_mask_2" + Value: "" + TexCoord: ( 1 ) + } + Texture { + Tag: "texture[X]:texture_mask_3" + Value: "" + TexCoord: ( 1 ) + } +} Flavor { Type: "FLAT" Name: "flat" diff --git a/addon/io_scs_tools/supported_effects.bin b/addon/io_scs_tools/supported_effects.bin index f6a56b1c0cf59e5c4de0b3af50086133ce96a066..f6cc9a7f7dde2cd277916909520484d0126fc1a0 100644 GIT binary patch literal 192085 zcmbrn>2hYtaV4l8voW=}vnYvFYbUi(8VSuxu_cOg@dD;_UL~^Rt`VPwp=7Z!WK6kaPXZ@b&vQXV<2U^AJaeJ9~R~`R4t#Jo%AMV~Tq7qqCb=XZP=4K0f@wUVn4-<&Q+8 zZ*DJ4$)+|4`tjdCK71!9@pZbKFY;gQ1(`+kAU0~RH+#K%{jo0AC(Osj;zZjv{^P@c zpF_JWAOAfpcYprLrKqlJosuxgei|v>37-7p zxuX6@)8ga9U)U4Ndd@z%zIyw~_4#L)Sl2i0!Mn>(t}kD`yZT%_<99l(=z3lV)Bfu5 zfhL6p!fc9~znfwWgTMb=bh!ws1VZM9vVvZ>%KH5zSOurVh#(Hv{+~}VHuzCt9v{AD z&wYM%ae1q9{BFLc#H*S%@_l^x`~1U(79p-%D#MGszQnBqL1Zc;Qa9PltLy8Rx94{k zXBw{FUS7zMp#yi+$A=$Jc|y(cKTO1U7j9tm!mx@(JU)DX4vocun4L(71@KUX1h`ds&V5A{L-R-~q=3D*CYb!|%^I695jvy+oL)bQST@L+{jYa>#$n1cnC5DrYJ;eI%*ECHyW2aVx$l|= zUJ9FBgs5jX8hsxh{+#*vt<3oDOyjG~A@T11-z76Dv)VsnR#~q(5ZP(tKxYoJJvX`R z{=|Qq)`C7%5swdhW4Sa)INSj8-s8hx@#-|&SaXMu|4o7qrAKXrE}f%=Tza$6q5)V$ z2*wTI$zB^d$t<|7r&U{@tHCY6L<}j>)#nBgH+DRQ9`OJ5^*lTN))VIL`!I0%O+>cz7Y!S({Xb%Rs<%rxyuCBDMqPqXBR&>R`|-q-4#xR% zX&{g~eHQ-ej6#u6fotR4zCEw1XL2zi7prby2)jAZkE|cc>_DNBcZ;)_9?^@EJqS`n z2ayJl5Opmoo!?x&L86C@Y{7QLGtXx|M=hgDeslln<>fm7&r7&JOiLM*wTkp58{VZJ z%7nt}D7Obe+gFeSJF*->|CHk!2B)&1i+GG9#4IlE%==G8(-jgkdWG{DEmWYjs{ zy%AcVssWmJR^8NWBrf1Rvn{{{RbbP z8e15g>bR2zSahnokt)w$GQ%s~dDc_;wRIRMX2%kPmIBP+O406fs6LQ665%B~bK{$! z!N1=nzd?Ss_z#S{$6e!hU$Ah1Wq5>MtTftBO^0RH$A{;=1SbyuA&-T;K84mQL`D11 zAcH+Vi1(gug?vn%kji5de#wn8oVmh2F^zCx!em#f&}>w=3G7<%a4;6$iU9eK&!p{fOUqwgI4J#Xge?do?=UyoHt&^^V=Kg5(a}j)2#%q3k@#VpCdTKR+^@;QFzpoGfJEYQ3b1`3p zR|-;T$E$2cLv@f}@|EVc$T3E#{ky}0$`xV1a-yC0`V68U3mP8V{&Gi;S-Vx&_wnJU zLlK6hGR|B?nqBGK*o{(oJZ=Wi$Yv?M+Y5?!x>{OxLLS+)dwlrKU%vnR#og;{^kr>GLl>y?Q6ev@H>LKBCP@cCjwu_*CJnTD;X(?d5#IOGGPM zA0Iv-5|j_qXr)Y#yS_6y0ItD@I51l{~guo|K&qLk$(p+hOwqWn=tv5xy zA0m4XS8rusC$;7;TTWlj8kQEzcPFo43%~NphdgA2<0al0bU&=!*-%vRmLr-z6wTCc z+2V97=I-|P%`ZNGvE+wI8N;PR6`JAfTk+}a0j8j{KTBoWaG|_dIa1~&zuKmHu29-W z8GhFi5?L}@uIZz|RIWvlN~OzOebTG7-)JMUIUS-zjclg;cJihTYe_B5H{=&LQd1$L z*~M;G^GqWs5|1He7gc%}VT^-(BZ6quAWk!)t3@|s;NkL*4}X$&j;B=XU>&D^3Qe#^ z0%vgtu}-mqbtjZHyuIK<9&|lMR*=D=MWG7L?zf}UW2SR6F|9~~(7PKh1XZ*R7HH5& z%QDq7ylTcHvwg2eT{zu;8)lE)K%y4tGZqgw>`{XNOmB=id})Nh0RTf*i2Utf72Sci z{7y{gAu5V^?fAs_Vdm&mQ`WB29z}WeR(gC0wAA356idSV?)K(V_HxejT!Z$`W%GGj zV@}F=)FlceboM=&`3pLGB)l1`vYd@{X>9E^KckJil;=2U)0*`AOE{A@xIxDE+^zpj ziO^|lBFf9^oyXEb24sgz5`1=kb@%e_{r#s)jT5@W zBCuf5>abyuF0sZigpqT1z=Ya9|3D@-iVQCk8iV_QM=U(WPN5HL_f4Avh7!Z>YoZLm zo0^E?uxn4m@IjrjC<7Wg>u`sg?6nn!?)qI$UrY?oH`+4ErGbEmBt?c2gd&L4PMoDg z1_meYI@M=><753=f{CM?(v&Ba0jUtxwg2+{)%C^I&1++LJ)Y++^nI{jwU30+jYYe% z6JOn0VPWf`%a&FT`sT1=s81y9f1_n7k`VOlGAkxiXT*{Ml>NEyd&bTHd|Z>=<(Y8P zgU;3J-1@xd;LAY}zyd0F{m{sGi2CChv^|1Vm1rP=7~pM3Qf2dlfnCo&&QZ%e7O@=L zf%Qg&Ns_3jxC9tTD9=uK)RBT%xtAQS8$O(A*@kr@Gur^~Tc7k#MqKbFWkv=c@&}x6 z)giY$S#i2LHq5RFTOx!mHDiSLNVyWpLdb0*+FgohXgs*5!|RlDmrW29cAEtbg45}^ zF2fNU)a9L(>N}a#r;;Tjnpk0Ae`&O1nFClOU`paNtXtcto`gD(`tAbcUMmjF)==s4 zg|}11gvW<)n!MXlYd}%)<)XOb@pjMKtIy^gAvie^KxXNyJ|7u=;z7Gk`l1m@$z2kiIfTb4vyZGQ^2h1pDG zsqYW5%xFqE)=O6N+u#Q^#iA>?<3Z~ra|au9u=5v1!T#F0og5&4$!B7Dz7$zT!80|G zF}Oln{%yQ&KJWo0#(>PS?-TB!1o-0Y&H4RjFUr>>Z(26R6)zTjsOiK@l|`1B&1GWo z2>MRB6!d|{K`<6){B3`UT5tM~)n%zJL(2#rAHJdnbv?=f?_>v6acCYHDW?LB^F5uQ zzKJyoAb5aPY09PKNLMNU*(T|y=rLF3D$WE*rd+HEG5k?!;)K$J#14F)o<`P2X;Vy( zti`4$O9Ytw$%T8)+(#y)+UQvkKI(4YVz+$dR zg$ADSWqP+@&EDV7Mbn7*YBgPzw&-Q1eoA zCC6H|;*BN-UIZBwRL7rzL})`EFHE;SjAi1*CJWU#M9AegGnJJrB>&+AqD1P<>}^Kc zaog%ohU_-n@)};ma^)QhJ>>J7$I9S<2%U_Wyfzqx^1=CJ6D8-6x_2lf(qZ%ASti9_ zbjY}bvOQ5D>qP6DNM)HG=}P1Pjw}j{!?CpjcvcHT7=X!&s+eDOpqK2W7Fn+Y!>52dVR@l?Jm~Dt3Q=eyevqM1gYE zgS-=x4@gH^HY>?}Mg=o+Wmp)Zz_~kGlNLi4<)C?Vq4e#*JIY0IPEONtGZYp$IMDqu z4$9O)@IbjQ-w1*76%00vD|n%elE7^*c_WMXrlIH)xv1eo^iF;%*li(mEjNrXKQAUd zI+jEMa&bOip$Ajyt(^uolA@l5o0>}kQO8qJE!3wBx9D#8<`|WfJb@HL8p{&mwn{^q zaEO;}#JAypr`I>SmH5*467A~a{hRaiv&)OudPwJ;+*~*l#=H}icn7^unLUgTNjL%+ z5r*l_L6+%Jo!4?sw-2Y+*+{y+e|h`<=9Sz`R0z&Pdz!pS%yhbTnDIC*O>ac99=X9D z<;Y-u%W|BH^S9Ea{o7r>lQ);_QgL1n{#dHigXlV(1$MU{fY_zV8G~{26!{~CUILOY z&NV@hn@-dQb(bR~Zy|4qGYQ}W!3SG$b=0I+IbNJOGFove6&49>A~ZS6@hoqmawecw z4~ee4qo)85lqz_Z@_{*5Qv*i& zX^wOpQ+i+?n)%s$c}@nE_@ok-c%_<-R9nNR-+WC#w##!G>;^3z!ki>b6oe3}@e-3# zu%=fev9%LM5lhpNXb9NI63rJ6*8Njkgl(WMR);#mXI)OqgjH>D*QHIax_^B5*VKT` z@L`J11dWOck_h04{TT&0rQO4u@pu__SBE&KIzV@6M;j$_3J17l@2zU`5pwssb`-;5 z)#cPkCd0b7jW0DMsao%^j*cS6dOOjpGa`SNz->h*BpQ+`C_O&>WEw3bZ33Gu%0R8&s=K9I@f_VDS0$6@GO4nlRa8C|{T=G}Hh7fobPZOE0pyM> z^0={nqv4Txiyphm;%Q68`bMs*NKoKTLuXE)uTsNv%wl8S_hA0K`` zy0A;t$x&LA*0cqIAI^ z!RW_osa3OOT@3CJ4Fgwz)9^JK*pW9-`7#tziFFJ|YlSif8O)cw?4b^SOwxh-$h!a& z6~Shdo-2save>8jnVyH^MlS!?+fbd^_B`)Igtcdn7+<}Q@<&#Zw*0@X^UL*pvG*r> zus>449}3EaV~O`7wK8o+dJKy!u5)3+<7!gJcNwYxWjA==!qV( z6e0CKKKRvrc{$yIiE3HV%s4Cq4?ZYGr43A4QDqcPA1}CH(xBzjQwMPNnKZ+KK@59J zs?$TDJN?(V@{abM)Yks5e`5Zi-GrCdmp2zcvk`Li6vmNR%NxtKmNm7Q>QdECi>2-s z{$fMK0*9suChD(V-(C9WA)dXZ(2X0GBR%=D4Q5e!EDf$5aME!4X0RUZt?yog3&$I^ znNX^M9Rzy)OKkRl{cW-1aV%IGNjsTxDK;Z92ONMs&G7W=rOB4>lCHJ{ie%MWK8C%% z(NrIe!HHMuOoS$9L8%&$OmpX88CTqg7Y`#6+R9vMmO%>l3@CNeHlg3tuuNz%(-T8W zMz|gd%6PsMf3P7(lwR@p#-@CQ=ko4KK5SwqBG2?}?Go@qwyxX=l!!yodfbHxXQM=% zq38oz5xaJV9BQB>AL|XwF5LYMHGZ8r=?5*%%TmZN4#6rE5X9R2u87FL6d_@a-td zz#tiAMPmIJh640d>{x!JpaOjFD19NemD56TaJROvys!{yQQuI`1#1}xkzF_0x_iiy z6%0WQld&MzX?l@Y}@?AgG2XR+1oabj`C>6tijIzG?#YXf}w$sS^O_w32W4**Wx($?^GY$s2Thk<= zYl!4?R~hp$-#=e25b^VS97k5E7=IMn{9Xlzr>N<*#sBbr{^*NsPKEWYBWW zgc(QA{vG3qTjJ^Amq{B!_Efs%Qr#+M?4)TLbE8Br&b>lym+Yn@mp$7ZDn&+LP~VU> zJ#N8aD9eb3`4ZQbx*gz;aHUIDJI9w=6HLmfCa7V#whmjWOgZbm^M&a$o;i@0%@_iM zzXnIsT$NmVV~rN0f_}YXbIZht(DDvi{zyscMYSI#Iy5g5Y&wvDLc+~Quxl}`(M$+U zup63)l*rEAQ$^>`nGUvGLBo>113Ka%zEiTVc?6{w`h`im#}Z8BuI&q40$pB$s(7cj z`^GumLK$rhgoyD!N#pU~33kaPDGRj`^Lcm&S=Z&J##<=6v~hCe95J46B+|pQxeTP} zEGPfgHyPVPd*CDy)`6zbDa3Nr3vY_c%jqD>kAn47B69Y84ONeY1y`TNKZHIPI#cI= znlqd-ilMeEv8!c`CZ;#$gHc&Q=2V6@2Bhh8vZaNCN#k4-Wl>=xjGqYbiLftRS6%v| z{L`WoCa3YtG?my+&AQ6T?Y9DnpQ3v6OrXAruJv|(7ae3wsTP(uaz!&zg^TZ|d0X{t z@;_s*wWn=Cd&QrXVZ|n2|1_S)rGyxTxIM&x0kOXyfbZ7?RZ|)8DQj}m$P?4J?jBDR z&nn7N6+*2TI3taz?E~7qY6YQc;>-Q=17OgCy-2Y@fn}G8`aL+EV9SmME??i@Jnc{Y zdvLVEO$cuqu^eU(_OT?GPnoNNx?xf`aKZum@g`kaJ$aPSh$zMxzV+gmiNWN3^5RWQ zq8X;`15&QVgC`^Vc2@N#$xTlgT&!fMTDAnv-@LrKj4#Ri*U}C@Rx2{=Q55Y2&o5TK zzS9HUl+K@$#$_RE&KE+r3hiKoZy3YG7uZ#lT}Mj?k>1$650T$Dv=mnUy!^U}Z;Ytz z5en_A>Sy=wWdH2V*_*37`56IpQnQt4=h!J8&s9t_3x;x8LO)BA1U$t}@t!2n797#M zS!R1O7eOpOAS9=2y}n&iGm$NO5YNf3*F@Dm&D3|B^dl?F!LU>MNp1~7qnJ*McDGN8 zh~_ID`j`gb2?(;2`0#2^zR2S?lqFMy8I59>Y7e6ZY4vB7h$!at%AmOdDF$P%@i}S! ziQvOpB-fmZ88RCwdH_kkc=i77o%{;f+G3|+Cl*2@ZJES`VgGmz6_qT0$*#NFpaKgZ zl)gc6m4y?iL>S37GPQ|&jh=Z?G$iSCgAczZCL9)>UR0xb__6r{E~kN4B*cvuRgXhs11Q#KoKw-eQv{i+(caVH0J%Ym_#BmmED5iVps4)syVHPsN@>{rZLi+ z>+^HhnndAUiL_x_JF@>&=OuKmW+z6PsA{>I_jdm|newRIX{6ZR4pdg+-P`^KzpZB> zBQhG0ym!$7zQ$+L_|c^JbTj2cuIEBsjJSbSHx_xP#ubEJ9NQqqmoB%v6Wx)YdR;n= z`14?0tlq8VWgK6Z50OlTb;YncANB_-GQ;}V0a6rr1oYl?9P}UsviClDh`&5X(^K!t zSinzH#G;>d2C$8m5zj937gvNT)PbBcC2j_ICv9qD_CL8Vdc4pt+M>0cK8%5x z;RS7BI@{^4!xbv2(R`3atpVt=KgU+e_-n0>%Ew_JiPs$8S{S9S4eTK=0U1t0ROIYP zHJ4~Oqa=C0um}{KKrca=Cp&ZgQS6oq+w^-z}#?OwE$xzBUiBABqe z?T8T&p>U`hX^ZKQvWKk>(*tJ8qW_!#%Fsy7z3uWhc!?i1wuDmgYP86gfjvnIC=+4i zDraOnK872V{G0Eu&feVK+%8v?V6lOW0$`Lj&&UMINS3C2#bd4hPV2#86-+&nac&f<9L~$YDzw`d@P<2KvNnv=Zpmo=ahG7dGj5X z6U4D(NJdsFRzEK#qmM7%0kKbiiA)X&ALeZgidc}C48cwB=*w?qdT4Nsjc}Ac&~D9n zvgsLtorU9{-TCpCKi02(Uh8k8dz7VopiUn@SF6JmCjTzoo^~@Fi;J#b2g-BSvmQ59 z5-p81o-s%LhJ=Hi2Sl?`MIIaT;hn%nEW|z0r&I@XeN$&N zjDZZqna+Vp2OstI6U~QMs?I&EPD{4=qQm+5?Uj65NsjGbU)~F`Q_ae{?4o(HzNBb+ z6pgY;(okjSNJP*`-;T(%xz3!4^x3+_|TO zYl}a5I=samv9v&hMO(Mo8}6msIJb~t!UHTpwMFjWbT0%m%@Vi%DBB^{;CII%<}Tf# z;I>m&C)Jn`3xA;|&D6O=sCgcxz{8U&Cb-Y*P)pPWp%~0Ef3qZm_+yhZ$PDH@w7{l@ zzlMBWdcZ_t)2FU)D4>nN~4+=u)oL_;`#vijzpOlbozt zzMuf}jIa<^r;ZM$-kyuba?`2wQ^bUa&QpTQrfRGZQ<9%I(w*xS$$MPB$Xa9tv{EB!%EdY zlx&!{vSu2|Q!2P8;&45BcF3Z1-9y2j9);QVOHy@{OA|}v5RqY4l*INbO%E)SE*wpy zZ9Gf37on3}3{ll0F+_CiDrNN#P|zoMRHZ&OSqxK$X~&Sh8S)PkohOko#ie+@OSW=} zhmA+3>b~=$s}ldIFCF2NU`{!wv*g{1WiU76lB-oNnN$@!n13? zsysWiJC8877QMGViD6ru=>+2H(#ZmxL>aJIkkn(gF$5-aLkW(z>M+kPz7EJqVf``iMZ~%8)Z9GeistmH*VQ_RmbYXrDUi zQPn0Vw#b_yOc}=)QhA32#H2lq;VMedpDMzUa;hVfCqn$Akxvn&Yp~Pq%pn}5S<-wR zZG%|f0r*VR1AHuO7`h)YMai+8h_SFk8z;~zbXjg|Rikqc8FP3S3~q#F-LE*IMTrC^ z8c7e&<_<%d^i+t$mA~rAdq~j1feD8Y1t85>dGh*o+7i|(i$Btw5??IQFK6NRSJCV~ zI4l7#BJ=Cgk6MwCa3NkOwOMaM;RrBz0co-fw0uWwO5|@KLtU7ZvYEjNqPWP$!+1K` zB=qL0jsf~j13y`#e~LT21W70&4C|?^bwG2kw)#^E40LEp9?XYM3#kB<1F%^bT>}}p4lio zUEvIKXgaVIN)TJm*e_)?G*|^^M2jWKouC4KgCrc?`#qz!UliPKL*>Un?305QC?p59 zEQxMuVy>~&X1F*v=(oY@x9BcE|HYlOZlz&6Ly^o9Nz!Z-WLyXe@Qjs0p(M4LDT`bY zNhgu`GW>PI;12oQ8fi(ux1mpP?@r^erBb71iuqvpzdLIyIP;U9PaFV1G9(V}bJAuc zYz17&#E}k|O9h?!Ho9$kT%D$gjO$qGfyQ|nCGVOlbN^9GSi`~Vv{%I8_ZxSZ6` zIP$#_Sw&hp7kNtBPG3tO>_Caul*6Gg=Gq=5530;z>Sh~rmHhHW{2Ghm!*b(qW-Nru z*Vog94c#@l`%K?o2^J9e+FZ`>yaI=T`uzSo9+Zzv?dHpx37c^%AEEZV7^=PvAy2#J z(p70GyDJ$YqnjQ#STiL^F&xF=BLt@@IULbnHC%+6{$j~#=PzBz7p*_P|95e#j`3KdI~Z@0cp=uB1^RX)h1j6BL_ah`pOwb_frkl4N28(5Rkq-%^YPZ#jARee#*E z3<~PIP6vzQ+d`SHDD0%MH}4W<(i15W(YcW(6a$1FMIk&l6qw6!qWJNGY5Zi9ohGeM zGR$(#QPWO)3Vns)W7g%QFi8`7Up#i`JXcor@Ypv|*Vrd4n9X$*r9M51XF@+Nky)3| zQRzQgv^55%t)~&lQoS+GL3_L!1|cAjOd*Rz^oPeB?gvY(!;3RVSZH8)=TI$nQ*!5t zl37du5QLiyNWyDp$V?JdtR8<4ydlZ*KguCxEF{k!T++`WG3 ztqJ+rGCP_@l`Z)K298yUDGsA}_(j1$lY|I;4g=a`9Gqo!k=gktne-b;ZxB%dczE`* zNirrt%npgnJWD8<7M~F7tco*^%cnl1uh75SO+JeOIVAQrjH#G9Kg;!E3bp$nffbAI z(DRUE$JO#TC~|2{l;X2zgY(Q^#U7{h8b586LrV0x&t{-sP+>7s@qfw$s`w}zG#kvi=NT>6}v5=^L>5|$ix!e0W-Hr;$8lT#x)cEb$ zwu|l;NT`H^1Qz203w!EL$VVDsS`E6Z^3=F>DhFgL-Kh_%f_=iUz2#R#;d2_S1pY92 zwZccSf4IprEGq;h03v^aWuq~KkmMG${jJ_uFgnmwCw|e>VbW5EP^)#2y;pI4dH(sO zUeY+1bL+AP0xGQiJ>ijHHFAlmnx>L&yrm&ORhSC&{3qICG|}p(JrHK`Nsz)s?6DaL zBpaACfj6E3(Hz7xynrYfZxjBp-sO7Ks7^sDKy|WhCI8z)cn%A~+R&cNk0fjP7UYb? zf<fF;PnfK=5vZ$2?f{~m8YAL zz)?BRi1%dz_nIRf)MGJ!k5kmvCQ0kbZDSIKSgik$-&9`9e{d*^M&8 z;r@MNh!EUd4eL@nMa=Q^c+r8(nTua|X#FadP~O4M>YesHpwfzp1Lx+zRtVB%Nc^Uq z+|Wxm13_nKPKFEfIk(O4Ug{J=_~XpSLE7&VdbA`u9TQp>J{C^m=@8a7v_t4%2YX}9 zr?$@y=M@bRwGNNRt{T-^-Mv0V{9G(xCw~ap zP)#Ak)#{v2dl!?)@oKtobBSmCOuclCm&O!^oaP&*2%oE8QI+PDyoQ#@(yG!=-fLNd zdWqYU`LWM|VB(2x$;^s%QnGkR8cs!nU~#E0z=qmZGr9JstB4rRO8f3MuZp!jt7)NO z-_-U@&Z7)siUYn?grS63qZNkV$}pIXiQ4>(BY8z4lKxXNx;nKj!JEpmQUW_UosVqB zC-baQ|y{XO6w`$o;Pa|j}QM9D#B-WETa1HEO~B;-4J~wxZ0>X zKvPddO%>FBo<6IRSsi>x#%h9vKS6`T+)s)1=Q3k#;fr^Y1a7f zbW>@I)~RZ(;p?` z!JsjMseoe0$z>{u(H;uK&mH5VDrIUql&$B3ju$rt zS$7bO8W*AcFAsaMFZ45q?Sj{Ve@!(e|0jG-bzrqACqE_f&fo@#NO299f?yNrX|I z5^1mRk=IUu>f?=4>O7J33QS#|*>lC*&Qvwk(&dLO3d*)tgHWZ?3=0oeA0*(;^dcxj zpCf{u&viFTg571Os*~V3>XdZx*n5_QbuQnONofN4_7Kn*REJpZbKot1+>jWu*gL|` zL|IMh>LH{Z^cYtEi5gw~QnoMOve~J&i_&yht!@G0A{dRJ-|L zVNsuS9c+K;{{H+{+~LjJ+q?7YUtCL znf!q0IA9?IE>)oq4$_Q#BY%)8E1v~Q!=WH_+KhnY`0yy@g#(MD8t#GTMWVK#i- zIF243Qi;6~Lp>%@6%r4}|77Om|Gn(q4mOPJA=uvf3ARC^^iC*aAsXosu-G3g-&ti+FsYp!mUz`re>Apct#shy$x4dmX3zG;`#MEZ7-4= zP84UrP?90W1hPwZdm3MGZ#PO7{-2ZhKr&3Y#IpB~nFp5bc+yGt$#TgMJf-#`LN zG?G6K1&~u2h>E~ASfv@^S=RQ^JTx*3Sy0cH6x`7;jBM1!r3iX3gG41l?#2#acw*`x z4Ja5k69l>hlu_cjA~Amh+7s8XBel9zjc>YKE6t6G^X!Wo*$+a>iC&vaA~0E}3FGcy zmS6J0#Lxn3H6^*A zo7zoSvwrh|2$SS%0mx8aqy!*bF2i`^vR}5gE>A#0Rzdf1pr=8NK(SA*_;q5eTg&oK zeO+XGI1?o@yU%9FqfKAQl434m;_+|=2TUVtSxUe03XqH!+_evS7aMG3{;6;v*`UY< zxO+Wth&ffZ-?E(f{_6G3=`gLs`>BW)rb937;D0r=6;0k^az?2m71@XgT1_DBJptb8 z!w?S*U0TiMkIm0pDJ_ii9TXd56zFTJ*`kj9MzfV@^4;urS5=|?;^nf-9LQEB&PELOK3e?&HxGuli73%1f)dJ?2dp-96IBCBps8 zJRy~QFo-!&uUlY*m0BS9;6YJ0$WPHlE5|Et#H1tl32Hw3Gg(%}nMB%Q zF@w9(mm@-$jODWxE#VwbACOUaOPSna#6eai{YT2GF#1H3x$f8Gx4%BQm8Px#FgzWJ z2)M(AloG3i+r!R8P0~6LB$VRTbyA<)=&{QG@&TC-YzngHu-m$y{af>1ocbn=zhe9h z#?WO`M|aDKy^Yp@OY)o5j^7V_(0qGp8UC({x6W*Ct|Q+=jBPvyM1+A|+8EBt+zLo- z(+Q!`_4P#e(cOxYq_K{ePaKt0bedh<$&pzlCE3uV5hEUo`*U#kc`!#*Jrrwg=ulOv z*%}OrlROXaEA~EHiseWaeJ=$xY%smDl;Y8)&d%y#xVjO6=gifB_ndVu5;JvcBY>Pp zSa9l>v=P{K%pl+Yea*G;!BMS@Uh1#EXL@0R-g-}f4I*1OD{NvIinGV&ZeI~h$eHY^9(snt z6`A|&-z^iznU(&r6!~db(O^5A^X=4$V%l*|4AIajV2JYcAbt+g%mTT`!Z4AgkMlgR zft`whcv>}}$2P5zLpE>X0UTfe$?J$!20(%-jPVZE!&#Ilz^E*b)u~K+fVAXhZph|H zM#MNNoBM~k1DhMT?F6m=n?vBEG?q@Q!-zZ43gL8WD)(>$CpP6(?<%3I$n8DP+gh)% zTg>1#ebMpmZx;!<%Wu$ zzT7%Q9n9sXp(2_oP?oi%t4Jk?Wu~Tipm0$;4T2g7Ke{mLpp&BlBoHb*%b|24W<;={ zmj0C3#|BT3vtnXGXRNB6$S~&*%cBuIH8Y`LxSBYgb?75!u#ltHG{14q^=y>JgSy%8 zD{RULeaqbhH3p$PbrhbNCK$(gtr)kc-rQbPi_};A`0x#LblnUH&E$rmf-Z?;`C5m4 z1~hMuETuYDH&|Mhrdk0St--FRf^P3G&+KgA)y?a(S9h16$S2F6bg&Ncg+q>*dWmhr zs(R?)gIdDnYi4afjO@_jE__Ry79ko`-NpSFU^}PawB~n*(D=%>NUQ-W$7mhPR3PGw z#@c7Tg+LX`P){${k**pZPua>O@1BD1%&PddOW{kV*wWtsOus6{{|xC?BdzT^O2ccQx$X^5w>A z2W9}-2rSIXkN^3{zwuvwL;vrA?19-iBDni_ObB-%G#$Mu;HWDmW*Db^O<46y@3pdK zwW4ew@~Ao3DQIDi;S;{}$OD$p1@WOOWI_mozWr7oUX2@~)~Tou;zbH*?K01F*pI<- z)Jh;{hBU(r5h~n*?ZZ-8VCY}0y1*Gad?j3l!+`<~S9(u1DqZ_aeQVq|q&5260n6jU z520>Rd5h`xOn9=0hJGA1y$}V=Fw5n`Cwv2ZFF4u)1Xc``ED6vP!<%;e5coXGBVR%^ zJsxDU2}|=pzt=H8|BAmNZk%v5XfcSLFNQSL(ej%rlgd0d&dZ z=0p$*K(q?H`htzpB&`mSA_sA0vsyOkzb3p+KW+;>DAa=#l`J~$Q8@CtSUQE(%LBY zPZ2M^hcyqvRuIL}+SxhC1yhnrqsV_QTXT3M{bsI<8ufTO#ESUc!NZx$`bkzL>*10`w(T%NZBE0e@RaxOZw6NZidN!$*vH7fIQmcT@+aA5SX?FcwM?26U&AdHc*z`fo z6i|kORH<=Bo$Lnt21A&6=;Q<*2`*_!K(65t?K#(>dTNLao1!MB8_omi>HAW{e^@V2 ztYr; z@PTU<<`m;18D&T&JV6@#^+YYF1%dtSF>?6ySsQekXi2hZPJcSnAzu?2KWzy23D&UY z65k84YK!97fV~$hoq0|}JJz#0CaH-Q)&oXJ)Shh*)@OWE*2ABBQlK$^+cS0;zW zDm=UevQ;b8kDRME5C=WG&rn+hkay>&w4wQFCAhGnG2@@^bfDjy@=qN6M8CR6gH9c% zZgbf6D9xt2LEeXG|M=jE-_h4sC5CN(g-(tvU5Y^B74!OKc$#uCnjY{;QE=SUp`Ei} zb!-rYQ&|RO$`X48D90MlSccZ2m9Kdb@RQ}k7 zCYN!Ay52!bM2TW=Y+aH9r?S&1p0%&nTuKaqBGn5ihmV3a+RuQ9?%@&{6AtmyY0Xnz z-|eFQ&&Xqj)ZBuWzjD&vUxv?yQ9ny8R|Ft%f?KmziNP!bmENMJQuPK}mR2IgWIXM=}ysUpm}c-tk&4w}4{n?>X!M6KW0RVbTLp z^8&Sl`&y3$f#c6n zY5eB={M#|%c@UhnVxF7E;3S`8ITre#XXny&gX7IO{*w7n$fD{6T8 zpa4gbyYFt~C%EG#ubeiLgwmb4ttzC+FXQ8?tT~f!U|I&4H0UExUI$ycm{izr7zRlo z?cKxR&=z7%aJGGZXj^KJJAlp!bie^ad*o5D9gx;cntbNuLMN@c_$8mjR3kF1bz*ga z@}7v!qshO!ge!9!M?AHOIC8+58}{|pxPFS}h!&;f%Tp!!CvyphU!z$QBM=m;Ucwq| zDJ;>cbbk;|s!lx!M-7X>IWmq2uqCCFg%1z>Cg=IfGP^2Q7@M0_n<82s#-h@x>^H%C zVQa@hWkYEf0OrS~qvqFN(xim}DX~B^&qA9U_bCC*F1{mMVJV{G|Mvb08XC_C+FDT??1h~d?!rW z)$Rb}hx3?>Q%auK^(@-omz8q+JxE|9r(d=crWApO z-~*56)x`lEvOX!>p*d1tZM#5KoU@X5W#d}brhixYEf;X8j<;yQsD@Nu?B%} zPlMo2uE}5j_eysgiO_~iu8vT3?E%tAaj>E;le}R%Wi3v9b9s0Tk{up(?!XAa#npt0 zSZ`TR&HDI2q4UTJuJ6Vn2Q(K#)Z-$~$pX)xbZ4Pmgt7Y8u0r%ak%vdV^{gv`vJozh z(yj>pc*nV#KpN#1^U!NlV+~CpCGhJFezC%>aC>w8OQD%BZtt!yq%PDux}>k6hLKuO z^K?9@?xygYUs=Ofhnzl&fEs`h5EV!#1M~KmqjmTHiS!6x-FEpX(;RDPHB}~6wkT5d z1bEeTvI2q>o*X<6nv}<>vo^fJTyHs9hY>5+bV{l#ugd%;wdcp#1(0l^|5p4yPel7Q zf^pv9RZm<(ip1WnNs;v`9;n_i+NR13YDh_6y}x@WU!Om-&^&%LEZ>A0f?C3>l{ZDJ z#1;GB@lwDp)HUEx@xxV2(3wlw3M3N{X~M!w4l!mHNFl|uJu9Ez_mP(BA>b5QH4a9O z%@N8zrsP2!p-B;$+9JEB%V`5B6m`aGtci7kccGJZei?bb_2|i*yT@Jl#r;+>K#Z=@ zgXYupR+k(>!10_-Yna`k3NZ*NcqqngV68k>PZ09Oc4;Jg(kaI!9{=Nq@hPwc0E!k= zjqwp-qI6T4+gV^AmbL`I&jzGhOLq3#(6FT`#UW#S!U-U_Pa0Xu<3n!Eeevm)e)63hX#?E!qa5R>I~2@r zQf35lhGb?Er`HHt&W@JDe}kt|D+7y=J#CW+BfU_5xT-#kr^ctFARC<(el3|kPXA-n z$jwLyn2==lYRwa!s<+$cx{__@@%t7ZO(#~F(5}FNvcernX9tP@pe8|2D;2y+K#iX$ zDC5g8SJ&4sZ_n>8fb*z*$*52b%_X4la?Z1hpJj{KlDWA!3~|I9qON6YJYcbT)m7sZ zLZK{P(%D~}>9)_jI2ixeb(p`RXsyzVMXJi(vKKLTUXhtCsHV~)J%>dm&SWls>k z9hTi5t`VD?@+#lch;MLn=2I>Q@?B+H4~b`7P=AhM__XLi>6$pP)na%bn05`x(2e~g znW#c59_?$AnHIayi0RV^+C(Z-STSY*Ow&h~xK!UHz-W}xVzdmaMoaZj8-bNr#ZvaP z5*>Uh*G&8ri75@alP;-k!)^zyJ2Rd0z>;hzhsaLt8*(ns5R8048;c-Ih*6{1e(v}c zX6^34J3}YNOK9%+U$0~q#8~+>e(~WGoWWXZ_O#$nSX;hiU==~s5b0Z}2 zhDmqTaat?fOl`l*rdm6@er{|fWBpbQ5-*_WsYF?OYNwMhQ4^9(*FL4{q$yXBF+LS5 zuwm+bQ!x^w!>uW>M}m|mt5z<0PJ)nffPc7b+xoE6trNc6aPAWV=I(5~iTU>Gvs*cW zaVUy%&7^lw}qh z*3O8aQ3iAGq5KXw@S)5b{kh!q)ukxSrd9}`L+|O=3fpBDB_73`z7B#MpSR#WT>=<( zX?IRM=NZ7>TBNWjZ!T8DXwFz+{g1M)(W5WnYMG3A3h(-yH`O9;rA`lzg`lfH_5jH5 zAsI2XC|0mX*4oEn7m=6^!={-WBZ>#r0dktQJ38NpgvJfFM7oV2Wg!WSACe9xW$kjI z+0czgMKPqr0poU(PS&)+r*r)Tb=b_Gh`PQCLSx8~HBMF=C-pD25hV?&gnZdc_pO>l7Cmled?Idy4zX$L zd_&|mq)KWM+wapT7bkK9AMlA~jx5UTPhA{XyvkOeWZNF4clX%A`&0wbq54=kraw}& z6`u|X+;a6W;#+}^E6$@*g1QN|Y{p^Ym6C!!opGvi?wAWy6Yw!4rq|6pGEYn0DykG~ zt!%hgvCBqd?;mwxJkfbh>FB8XT`e>&<|n`}zkG{B?!7$G&yQ?#`RxL;S?e}c8fc6l z%)JaYT%_&2R07ksiaefa>@t+Byr|!=fPE66Vz^~mHfB6LVr#LQfnypV+&`c)Sri#d z&xrD?u7PiriP&PwB>Ht}4v&s)eR`nH_u%SiG=dMV8dU45l2TWn%x;x2nSSaZAH}4` zoA!eY{gcP%Z(d$q$`8Frc`7Z;kAWBQU$&G zD8);oak?S0$*;(d`SGRMJ7;1fu+jcJ1;{ zlS-;JIL<|hCA{xOJEsBKa^JQQ|0JiP_n$S@l5ZG+FIOv z@#Tv%`2@i)UW!fRJElo(5}}^h7;Z*be94@G;5QyZXNMXPd;KU%)MZHR=4C{DrpKjW zwAWzslq@%OCNC_d>|5{@7tQ>fSpTkoo0+q`O72>-td9DB+Z@>I2v_Ffb-UmZSnZz) z5MZk2qN(Ire{<>8QpauDS8R`kXyN9&VoKMB znCUx9s=?;Lbdr%wSWydG89v|!UaB|S`g=aJx;3cS*(48{&if0eN<-0IvBy!iw^$UJ z&{8W*Xf(}x+>tdeztT5f0h*R6jp-@n-2|b?+(@Swl}cRbX*s+c1IPd5-Vo*!?haO> ztwKD2s}j)DwgYLPT6gd?1Z8bVr!ZZMjz$O8tfsOj)c{+qe{;McB79Y1o@YL^nW|yI zuOj(u-gkO^C%*x7adCJ1_CCCrqU$~kx=8_l$N^vvSVC`Q>L~<*+lM-U5nPMu3g%3obME|ia zMlX{G;}Kj3bu?}aaMSX~)442ImE@liEXB#v>z>a8m)^VfZH7JjPwpQY^@u|xj_9z) zY(5aT?i=T+P5Z=CmCar~<^gNb^^zE3d4qtwY2oJot6dJ57n4LE?OFj<*wfoOaq_0% zxcIZkxQ9?UYf7s8akMW$>ozlRn6YJQziFMkFhv-gfaXh`w$QXiC?=Le zY+B<7dsTOUip#^&n4A;vB`;QdH7nd*J%Wtg+WTkN`+0@#P!LJ3y?|Mm{bM@fl==6NQEF>^?Jt;RdTl<>9;zPVspX=uGBT5-UG?u*=lc)Jk}3|?6*%@YGqkO; z)qCq>j2?9Tz7&ccORv9{>om|>Gy|~aGl>@YC+GX*pNZlwgT@2 zjjC;JJxNgV3%njIEHshghi_1~3@wlCr_7QM7T-LuWgJT8{>jiW3L~-Y?pi3NMb#Wz zDp+bI9MDB!H-NTWyrLKLG1{ivVv$ETSS-oSPFrFJ!z1-1F-rzjuvi9)nLE=Lix=u(%w`7R!Q^4ivBd4gK%UW zIe}rosWU>Bz5DKX{G0udG_BVjr> zgUekP5Q0ujo3x7#B_$N*Zi~z2yRvm_DJbd81|;elia-VHLD0pBE2KBKuijtFr&@?c zAkPSbNVEd@+k3KBcXpEcm~OXFibH&rI&=-vPM|FcqPg1T1&L+FXv^-7A&Bl_BtYvn z>Kt{s^+P5vGdXr#+Nu&v3&2GrF_g*sUy&y!QQA3Of0W%ki;j+0!atTV>?ZVMS|~r# zUv`Bx9b1IQ)X-RoC_6)<90fYnp{WO@K*AB0d-)osecgGll7U&8i(C-vEJLKW;e)p1 z%8`{;Y*m&hP;tCFu9~Jn+lK6cG<>Zcu|wpUE=>hF6X`I$+u@+JCVS%L75NF0aMGfM zwQ`l7uj4{FxYMr#%<83i{4uy$^(fbF2s5w=$qFQR%1j;|Uf?$CzC^g*;Zc;Z)!CpF zSh0`&oy-zVC!qyzzmbszEVK>HBmF&r5%Z}>ZR2KZ3`uTsKW+cvp)B| znXR+N(No4**pVXH69UV${S!y(1r7b{ZXJBvc+r2a+TEP!9nP>4REJ3jr+9D|2rZD( zj|ZcSgMw?~Dp|Ytn=2gHVlavP?{aKxRbsF#QV@4UQvC!j#s@$9DlDy(STLO=nMP#3GjpKwAqc2Ut>oqCv(kT&-yD_pzec#T+RUCJhMY>& znWH&C+Xca-4qme%sWxl~4JS5q0woN-x2{OX@rLD(zA5Uz`jef@$0rWd`%L?8+Z3yn z{o&Q$Uql$5=svhTU1z$WvmTf&dJ4gdq)|KsP@z?M$lkG;u=NEDw(^0Y!;T_wyJG#- zDFD!Xs2u=QSZHk4S&TCM1dazY#d{Hn7Vvd;r#HZv!VYRI?(nOGw63J89 zj}cx5o1&z~j4_!-2D>{^tJQ@>@yJj~-Re0O>M>ix@0{Y}64k?rNQr+V3X);|K>usFpC zKz=a05sn9$gRi(cc@d9jf13M!fHr;ass;?{a%>eQ&g?7on`fkKUt)w36aS!y8xJ}?c&s>hzS%w07y?oVg*@zoqRp_i@d0&ehX#^# z?8)V~N-d@wGoDN5D{?;}+J}V0=MW|q6rJ`0aN`gTfDuz&}N6lljSR@5hEpf zn2{*j4s}2@WRLd3?lTlJm=TdFh)SLq5o>SO>>k)%)ERYr$+%pNScR#lrjtaz2Hwf+XeiDf8$@Je)>tnm%){K zo)~espg4>1meUZ~eyrX{7trjeWIQntwuaUH@?2= z*anOLV>bVW_p)0IDLl46K6qlFwo;cC*@%vy#R|k@)fBcvyoNxKeL%r)xKP)iJ>HkT zANxok9QGxT$Jl|^6M*z5#cBK*!#`n`7o&L{fePXcWe3+0J;IjJ`}6t9tLn^;gnAcj z)5FellRKeZr6IZvahUy;kyC9>P(L`@(j2?{}t z%*#o3c~O7SmnxzGL_be6T!v`55u0*zP#O_^duTLs+)b0cdPS=|9eSMS(?u|<`%7)rWOaNt~^LSGT$Qdb<;C|B8 zl!2GJpXT??)YGDCw8X_JvJa!y#$8wrSov9sx>FG*B3%rw&v92>9BeMFUYGii_T!P~ z>1yI4%K-(sB+=E4bi|L8^}96CyzRK}&e_3nq4yLHRZHqgl^-2wZ`sjs;gs<|s_q`s zTwnT`0&3gJM|9*z2d{2#&aeI2%J1nD?QYhOzx?r;+-ZJu{w01?B*&gM-z){u%ub3_ zXJG`=2uk)5U!{BsUt9AZ22zg75gRCMK~k_~i%Aqk@Z=Un(P^fl;gnL`A$~qHiqnR3 zVDy%XtZDJS^b227TM)r_&@9jyTB3zu?L(*Sm8A@ih2T9vnu0EE*vZq&KpUG&;Snyc z!dge`XH$)*^p1Cd#~6X=6M~Ng_kQCFyHR@kf>C@3^Zm>7C9L&9Mxl4w*@^Lq`UDIg zvs3FGw0Wm_`TV^7j!%ABD1v0e4bkbwBm!p08v5J^%EZACT-4(YnbwcX5ROB*l%HE+ zrR?J$1oSNDz_&wLE};k6DzF<#`U8f-d0i${GIFr|F%ku#_l2B`pHZJAZVvc+oI>E7JrFCxS3A|Vp3PJX_oU`XFayb=#obiRfrV`7LlEq&6qZ9N zDMW-2va*72)ixyzL{U+Fc4hVq=lD2H2Z5|HYY{5j;YREn6m!>ODSbbF+#e!4Z+KsGdS3Oq z^W6O3RY^r5u}t8HcofSU5n0S5PcOv}4cJw#&#Tm=yq!-}9M*S?xgx92uV~l4fo1j8 zn(O&?IHe{xUWSkUW8@=CtAPBaw-ub~_DYPk`s0gYHYPOV!~#_@zCNsgL(vieIF;q?;*4^(RRNdYBoJ;?gz>`CZU_@zys01x7 zW%4@*`-^Gr4s{Vd-gDRZ(KGTlIu*SmCYM@4t2RAFuoLCr+GVXip!nM`mZ%%KTLU$o z2}AeLIIMd6tH*~5jY4gT6FD2YKN}3#G%c6EC3|-9+;H%~iuM&TSKrcDGNG+RGOMzPu0u{q zS=q+(>Nlw>-BV-;crDypx>s9076yotiMNfC!z_3bn~AL+$_sVRK9&&3(p^LSY>9Mo z`u#hpug>DxIMl><13?cn^fwxx+N*9+gT!F|O~H#;X+2f0&c z0duXM*{QKXe0xYQ%uhPxfCuli1E3f0&#!;+$ZLzezYeX8-wbgMq=nK;>)(ZwnURx1n7d*0wCjsViTUmt%jkShm;I{Z^x0y)FxL>Z-EF zou6nh^(&J?^{Mxdwb1~W(c9qxwIeLeXhmXQck{}xV? zQmR|k8GQ2yQ?HBdnSTC0r2KB_yDQnH(u7s_*!s5|htn=!Xs|IuR}+p47=3^E{IUv#r)I<8C9#(`;!NCgw` zsVmwX-l%C2wWZw@lNTiWtYmt#h(9X2%(bFI-#0Ast6I~QmM&7}g~(MBLpE*q(k0$* z)nTL;q)Gj~f%b$&Taok|sxCL!mxi1Xa49yWM0|A3(N^5C$408Qv>>-j3JH-iQL#;y znF1Xd+^vWxd@AoCvIKcE4Y#ioHXg1-c7Ett?K6tCuj7ha_yl=eSguQ*Cvd)Ed5~P~ zz7sCxLgYEOC1lqi>&Sl5C;W+Ws^$%8#D6@MCBvkEQUTAHj51U_U9E7W;s>YYg9}_W zrPC#P4DffOmO}#$bc<*M7LiWp=Q_M2Y5 z(N~QMa_u80aKSwg(}d7;D6mJpMxHtFu8To6Wh3?{#@ec*2`(^(u z%!l*`3%FGr%K7nGV$>#N)nTtCVp z%ONJvlhI|D9Nz-9e=u6iu<7ZGTi%=Rw8t8T(xHmQjNYafEI|;!ALSQHHS!faTTT*M ztcZ`yd)aMIOZeyR$oIDhBs46&(A4hHXW+D({12&Z(?-5y|Aht3WtcA85tzX=BO~5( z-W)Z(NX(BO>7pG`+cvo9PapS931{RDP-T{EkKwp3m1`rgh>RTy+yF1uL@n*z147;G ziIFy-hCmkO{pJeWx>LQ5lE1WJ$_a$}8c8fYDg_E$`!$+-%qmcjvn3dUi3$kRP zq&$N#oAH4fNDpdey)|2xG^-q1L3uCk4! z4(~EW*Enha!!3>i{ytAI$Ovs9)1bt$6 zM%HAkmK&_9{kS!jm%+saBXu|#7*ee})+*OEv&DE6`Z0n^6>PTLAQ_B|7u0mW8C~S% z$4XD}33Hs%p;s(mEPH5bcnl>ac)KmXD>;s*c}Hmsed}`|;fKYM)SSZ^}LQIXXic$GX z6#?`TG*#P;HNSPEHrCvxO%U7s_)fO*zT25#6L!ip^y%DNdSfvPtdtb?2B`o(=H{(U3^>gMcWA>AKpkw zd|c|b<6&g?v8r!d^5s92?JHPLcO4n9`@2#(vYv&GLHb~1)JVHcQ7p#vv@~9QiLl~W zN_0agIHpdJ2f+79JNaC>kOGvRf)3*<6UrPy20c}Vj5QU%jNCfHk<3b03!xIkt7u|V z+Tj+kO||49JJ!F zQpX31ZzZh$0d-mJq{}D+yMx&FL-l(4pAM3S&{P*7bB)J`I^k)PX({)O?$pwz~}{i=mu0^I6HiAFI6+4DX0@$_+HPVHJt0 zbL*t7e@d>}=L{}NOSF87-&PFtYcl#XRZAFzshfLi^tU@U{ky;Sx*?sw$k#)+hXTKdc%?D+qG{ILDrr8!AMN&3;x_8qGM{WZr{&I1%( zA1zY~x6Tx4X($sLzy`h=n+&}1&r>?pTIIC-ULrqtHmUU&NR0pCh~U#(X=2Xv%)_yA z1bmXoS4`&D*XQ@r$Rj_4$e~_$GFN0IeHHbTqrH7*EKN#-vSQJlqp8B(07|Ss3G+0q zFFXy?lc!^KwJhn6nl`R4&p*Eub$rkN>-^2zIFVz1f2r5=DAEl^GNYiqC$sbp-kLf{ zbIFOwvs16NTwfsQ*lQ;1kWNRD=r?MrneQ`Dv(8i<+EN!W9PQgEn5#?y7xt0qEvUA= zwpc}?j+a1+Y!Ln-1eGN#Yb&ASBO6x9qs!^Nh=2VMXH5E=Ua6yNj#6JT$4Pt&FpaBV zw1Dhkj^KZ9`KqH0+VDTe?}Z(Z_)2>@DfKi1Pw{8Bom-AFm;f?cYssbu;Hke8IgeeY zUt8;yNA%rk1Au=x#e`fg764LX&1JSoYbiR>OF>;G!Q+E>P51jZlDlkoaOz}@-+c4( zJ&b6d6rs#Wm0U3Z{$L5Uxtry{J#?SHd3kjydm0|Sokm$kpU+(4?cJqJA-*(s&Q%>= z&@Jsd=%g}$1Pzfko}BbAju;JSv#qf`p-sPYx-MGxrHg^!@y+1^>^s*AxIrS<*e0 z((I(c!olMM9bzYim9g2gwb??7*@_-|@@zHB1^1VL|B|7q~2q|dfS<9e4Vq}NN!hmYbQv8iT$hoTNHx6K%GH6iyu&da#GP5e)Y=yojvuWwZ2nOc0_O@z=gxQhXx=txj+HkVP zscW#|D6EBQx2<4PT2G`*VRP*cnV3!UQC+!tjLmkyZa#*H?a@Ku^mPsTpGpCCE1d}W zU9x?Hel>+#*6l_KA|4)Gs=TDLwl9V0KLrJ;B;?go;TY3b(78oMIUTVJ^gS1#ojBqU zOfwT4o9gsp@uKKhL|!giVi^KjYE*1e+MgcvN(>M4zJ;7kn6(bKA%?q!7)u9k>U_AF zt)2K`KAzyRNBe%fJ||}qPxn!wIgoE0%*YdxGO8Z0alq(^ol?SlJ*GG`_pkfkD2f?{ z9pNB+vNq+KPpYlm+SCNt=?66W>wnwT&Q(>oHbFvc)BM3kv^y*cFk)liGE8pc_;&Gz zJflRT?PQ1$Ef!ocP?K~K0}GWLO+~7e!EIFfPHjSBhYhraiP^jai zyV)Nx54E4#lGZJMr6(NKUDUxy*-Gt{`a>;bMkF(f*gtD*OSiXwrVMW9wq0$@PM5ua z)dqa}3n*CB_#fTBlV9unT<-ha-oYu~5)EF98PBCgOt+%nv@j$F=3N*>+eMN~A*v+s#x zL2JE%_7`#BP!~0!EN0xu5ytw(3fO{jwzkk9Q%@*b4)g1`H6@9mkd0OPw4z;4p9oMx zU4bQ+PT;2yK5+8_pkrWPU}DJuFm>%1mI&+=IY(Xk{4+i%3q4G)Teq(8ti|R}NP{f; z>6I+NE4*x|9g7uJ5BrJ|De;*u4{^N_IluGlZQ>61KW8@0Z%5Arj`G7Wt&il2p?G6R z@W*lmVX!zuV|$C9Mj4aZhP3^oxTGGECBTQSVlzzgIqV4Z*wGAlY@kM zbC^KE5fnH}@jlUn)rB=d`&;KB*Kw>+y)=TV8ZZFZm+c{KxeSA6qmm%6oMI1gH8+D! zva%T7rlOw7wv|MAM=G@yhSaA%E};Q}(uf+m6FQM59%2wRR;d#b8JGfMGUoy1#BlW- zg`}O*1o4)GZn?C1O<3D>ORE{`%CHiqb_J6YO+layx1tP?k%NprA2i`yV@TgSn=BPM23&iN)!RU zIdg(I=0{t%G>`@lCfl{?$qCWOBJHP=+%-u%2M?!}{iTm)sL}|E z#)G0#F$YEY3;uQK+bijGzryisVyBcV@&OMOYOSR@^!zlF`)#_c2gc0B>Sq6XI4Otl zUel`4U@>c+`1brK^5LIiSa*pfIxC9e&hWt*V_z+ToUhW`OCTj5~?T5?HBxhJ! zvalI6D6>1K1zd=I@%YZklpVl_+x{Eb^|+F8yHgIhow^aZk<*eYkNwl-tmgFR&}&#I z1FF(B$+EB}j4_c*z5HD*9q~%%sIYC=>rj?Np2GnB&X?hJIrV;^v*5Tev^;czv)q;3 zB18@iGoiB{ASf$=woeMc^v=8n+6AHYxsN z+?iF?nisLgijy$AI=76cT;T@l5i~#A;QyFJ^(TxWJKJbr^Un@RA-#Ph`Ec{85?XmI z1PU0|cBYB|RNp`gn}sIn(7JGnufh?yZy@>z?U1c1&R^3xkN1XjP&-}Gd#mAi3(&Bp zsy<_NzAj22C(z(3v({_QPsPu{+b&wP$hL?;`r@cSk+R-lmr!bpx3Y5Sz!xz5>hBS=Zw9en5JdQM>5 zl=P>|rvQX3j@oOjPv92X?P{c>(j@I=i+2GVXfSj61Q}o=X<=>TX=0Us(0Fr@e*mI+ zco!8xB^UJj7vZ_~0ePIe)}JQObJseW{^Bg@BWS|qaf48AdwKv&iX|pRMhD+Ft|9f=$$8>{bm#*5#G1>>`$U*lU@4QBRGAx&=MgZw5gJTm?;*UKf`1tF` zLFD@b{UWPkqf^!TL z`G5%PJwf*gRkbgWF7CNjdx#}>83N~&mYD>HEoQXlKdpPZvyT&4cDX2zfYsRpfd50c zt`|aenlc(S`O#3V!9a0wF=Pj(jv=|^EhnL@kfP1WrJNcI+oWcMZGSw;OtcDGPEsE( zjq<|rFwd#hZ+>?WWeW$4aS-=PZ6s3=EEROqobe2K2TZ8;U6QN-(1A1*xl=({1O@zK zKMd_D256%)-qD4;IP?E_;q70tkvV{mgTVWrU;lr9!~U-w4aB}+5F_bg<3+NlaNNk} z$YVl4H%Db6<=^DVLr&WaT|VqeGLlVmrp`H3Y{903a#SsvTP;yOp;ST>hhe;7aM29< z2#4{wrT3`K&^-#-;^!BZG=5`>%8UB0uJJEHOK87O9~! zC*egXAcRB~<6x2Ucf)KP)zyHcn2g*)MuR?6$f1C?O>>Y_7eF*gJn)Ihb3xUei|ypQ zWzn%5_xNVywxH|*ro~&MIr? zcEpf_1v1xl!M9EI*8VdqQv$mxA)r{2_#2A}${Uy8u%{vVhwVOeSJ$NcJ2lt`d3|?zF8)jk+q$w@&js{oL3MJSmkf`mk5vfM zsAf!Kl%^l^2iRlr0{pU|g;z_nQL1#kRWW`jY*4;^+`eD?YMpVxHap=u{j3jnSru?$ zyWPH(qmjf4NON@x!h?5A`x1_pQ(ogK1mUoNrwGngw>Q_n6y?8qe|>%S#qHhog>=eZ z$yd6*X%)%)8wq#s-rrqHkfRuoV&htR3{DI-A1g|2r@A@g4e4zC$oirNaq~4k&o~-Cr?)rN)WOnGBpE241?g^o zyFy#%2J#oz^$m*0hq?DPnjls^Q^R$V{S>y2JWy0U^^!yi19RRpYx$D-IbmcdAeOJ= zFUb(>8Zo93xVZq;I8XfM-twL4x$+9q&eXaFuS346aBQu}ecp34nvNrwrUMjsnv)dH zZkLNFO$RO~vX7`?yqN!4qS=V?3FGmkDlbtp{9|qhOY#Sx zbZwNMSKra>>sA4g2qC2TV?O0I9VVIs`#9gAg+#>H@PtYe4WesAUl6H@Cvc(}VHJYE zjMNpZgV+GEiomIPRHi|c$zl;B1iE?;$}zJ-7FaYK3EB~{_{cWZ4Wsz7NRb2v+86N6 z76O@%b5Oou0Dq`DPt==M{kdWPC2{frG|_NG&Kc{0&e#+JgV|(sKXGYoQ;}-zmL*ee zeVi$pH619=zFX4#5Iw=4m}Xk!UlxN?HCa)wJ(T8rMQq`Mr;1D1ae85X8$1HM>dn(= zg4LpbpFDD!lMkx{IzKu<+6IOcm{EbrL;hDv5g5)fEs`=3>nOmxa;>r(vQlSOXSLpM zBfTC1tWQb4F@(w;BcdapU)D7uVezql5UoBo^6FL+(}FkNTn^_91&KD@v|l&;>t5I0 z?XBFj_ASvQNLsZF{7R zDKz2vb9@WIb`n+0kx1uuy63Xj`t2d(RmM&%AFaB6N-yfJ-sJSEFR-u_pLTKrr)j9> z*+(18!#OV=>2q4b9bKK0{1^r_f>Dz%=UJAl6t4`Mch|HWn7nQv&zwJC706D)Yag?4 zcerIHG34+G@Fm){b=U?QBnBcFQGR>1rFacA`F^6M{Oe0ufn@)w`n-bht;FqaR7 ztWyWupHYBpE>wge&Q7kc-rj$Dc^SVMVEuWz41r+?W3rHz7dohyJ6w3Tt=^?6Cph4U zmYF}sS8^yNtGwS7O5IY-+@|xi#_{uAtu5Q9HeY=CLVrwA;7S<}##v!e3Xr$_*k`*3 zA4c+X!x@33j59Lgr~`l#!Jk+QEQ+#6_T3z0Y}AEVoigYr9$7oC@xa z--M~YCqT}wypps1o1=vAYhe>K(1y3bNl7`Bm5+C=sXZSbe*WuJP(zVNIq@>N#i^y4 zh{p!j#8{5Bz$bwo>rn(d@>O5UUM&snQrox@5B(TkE0RJ#=#nlyf#)u{i;)We)P(TUyKSMG&jHyd_2; zXy*~EYc-BWbb6K_8>E&SJtJ|pVJMi5G|4y`wN`X79giN&m?cB+ziXb?(re$;06gk^ zY5TR<%t#kEI)I$0q1kRm1Mv5Conf8(a-6iYdL zB|@&)EcG1Fwc|wQs1H$i^mNNr{iZD){kNydI7NvL2`!Y@2kH`6uUyjGji`4dnL)t) zPV%%DZSp61k-n&$A;sR)k zrt7W0+ytd^)C-WP5@C5~uok4)WAaSKQq|6^bOB)Cl+qX;KKUb?PsGyOwcx~)8_D)Y zgBl&1G=_Otx@?TNR6$RXoS@RTfpsK1U!*>gcyC>|%zPFDp_$^*9L1Al|UQ%d;tgV<>iY?7uTGU4@ zmMZDq>?Zx^spzRnhyrvqvb0?tBo;ck@lr!e9s0U;9<(2a}Vj_`mD_X*cFEATMeGpNzY%PeXZkA)uBHpPqv15KW-|4^lqZ=j48 z1;VlaaHF52S<)p~E1689PRh4A_mru`>D_;+-r5}m>h`JZbwCVAi7Eeh5&9QFM6jtYEGZ}otJV*&G_T&2k zlLo@;YJW|j6fJA_VG_ET$QK#7)XA2FYKeSeRazHJMd)kzS)5}~f;io<@{W&kcYw%Z zQANvN(d@?}v40mD`!1yOY677NRx}4$QJYmQ;54%TPaj;OQdQ>t1Rhp_cN9G5xE!F zOV0fS+l7L@mYa1J6Q0BkxWx&UNCE1o0EWkHaHFD(8I?!aA1VJ0J#=+w904*l|2_E| zv=Ajhk)$JU?&r!!gTaIR?CUr5#$LCX8fdVt8@^R1M><5AEQ@Ni=lZ35aZc;$i6sOR&Yug~2u3Mn=D`hQZ5Z0`6D7WK(ocAvz4 z9PZWao42?3muJ=}yt)yeF@J5Fx}x%{o6GaNv&%2v!VxnYfTlrM^52WBW35V3UW;_9 z_tNP&Y1AKiIjun%ci?WD4r~ybbDNn$*#3N^p^uRZnH&dKJoLB%a?@ z25Mygc2~kH1XzrZw4u;6lAdu`Eeo&B4?$X0vp6z9t&&$W!eohF((R(yh zLgFQtS8;;AGzp9ccPYsx#lYh}+9xnduR-BJBtMjtN);iOz_KGtc_Fg#@2TVW z`~=@?Iowj7xM=QEhX$JOyYgJ`Zn*qBu{C|e4HxC_KBb~~uOGORUy`|d7yjk#(g z`egN=qh7RjvO$#`lC_Dr^Mm9TYvcO`tfjs_z)j%30o}g4wF@qCZ0Hv+rO{BULlgf* z>H`{ROt#dQz#93WYBE$u4ucm8%c4jMCwOKPc+EwYN_!7M5uzdkzFS#tJ>r4@76R8z zB~LiB&0$b(KP#w8y*s~otvBS*Ceeh@06^G~od{i(<%pD+VYQ*c5E)cZ*EP89 zOR+CVb2(m^&~b4iDRP>i8WHPTA?!9#57`7?Q&Q9+qJV7~B>BRfsF&itB@0la)b8~i zKy4tT{m3a!8pU{-&kO$e%OA&iL8@(-jY2y*!@}-O*`Z3rO4ZA_nXxto-S;U;u2TWB z)F*l#ZFYj6=#9=)z>fY-#8REX9ii>=;tW!Ko*efxC=14r0~!H4u`3;-*d&2PL9n;P z&%c}AwwAZ{{{G3Ho+w=TsyF&V5yp0TGzInz|CYtwagP*hZYlG^jPkS0)g z-A#Z;XJMys4MZDcpDrbR=hc2?6GM7qjhGdcim950g}?K<`q&GjP3>a{R>)F6Zivtd zf;f%vO}Rqw%lDtZko+lfL}GG#AGXfMgD^f9R@d)e$6LIOB!5oHi08o~={SG=@_jySoH~c64TF`A`}pWXwpM_g4>-EdUPL_7`uJBlflD%omchOoH z+a9%3RYj9o>pae#ioTSw*acy&+mEbn$2G3neZ|=-na?3BS z_mAr=6yhc+sDTn4{!XYAI=8b}5( zfCvdOK$hA9C25EUtY*)H1^%5_bZO*i=s9%SGj%zAz6@$G%?y&Wcr+I7y}>-nw6 zUT0sj*uupbwyIfIE*LU&8GXBpN%I1mWop=4``O^jpz7l@G2}@CBYKO`UbkZPtm zx~)wFTwA~;Rh;u%#hxXuHB!QXVZ+_bNHb;{3n(o9SKz26l3Hj@AMJ9D;7c8q<`ae( zI)>Jst|H9iR_fxhwoY?ae~7`8ogF2Q+Kr}iY>JwKZX}>|LbQ`GO4SUg#B1|Cfm`RJ z>@r%55;ih%p24HmO!upQ8v1i3qpF7hRB!i{HCv`Ppq->)rM4rWgr^+KM z>#&;$m=qs}zzR2QEz0-Dqjn%;D%qz!>A;pjQDeAUVpQ&n!`8%H-iPp1*->@jpj zrCy#C&UcKe@5Z(hj{7sN20ogs%2N~5RBx~2%mM;|7y(@!NY z_BX|3osohk5;cI2{2t_o+rc($-g_K-8bDZofMN+&sK5)gpeMp;gwPSf*IP-vG21=` z$Eq$?%XhcaHzoojiyAdU=u0dBL?)bKKggkKfto=HPmd@c(Ve8RaR$kr6C)%({AGH* z8>lt8DRNH5PTJbZ(BI*dXSBh(H4}bzI`V=D18$>&!e7WDRG`@}zPWMGaOb8z@J0Yt z3HVZh?dL!j-2znu0U)HYwKw-acB=?~X2Pm*yCcMDk=2%3ay1E};>VXAvLJ;({$ zL1!MeUkJGCDS(HNaHz$Pcb1Yc$iX{}ZlYn?JM&TFlCXV(jgzpH?QO{*5^EkxU@K)5 z*6DA%f1#;+J7(5{rgt~;lW&EF_NsG}s*$+z&%31Go<-(A z8d3fgV_iHNF>$HUpsSH5$-eF}l$g-NqiIT=qG6epm_%xN;3z?a+l|{8T8I^xjpr~e z$7gpX%4f(H!+!0(B|`;Y{h>V6t}tvn8)|fwdYC#42m!vo9ODZ6V;KSi;-F9j9zaet z-30!SX*4xN!1GXiOF%`l-7>(jiu|(wPA8o1(#=DM3$9H>YQRkPDFI*g*~>+A)S*P8@JU ziP2no5~r2FLk>4#kOn`yfAU+Vy;DZcGS_ypMLTdUxjD zF|!0$Hc=`~BD)R>5J&kL_$`Y};f8^ebxgNgRA+=7?BOf#yq_XKcuP{U0%69@K@K7r zl$KBNg2q~;-Af&w+q!rW;3EZ7eJsaF!%gEgb(0-rLE`b4+s#!r8NwE8r!+PxzWMye zfBN+IBM2y~8VFp5O1<=y|8eKOdfsHg$6Z&Nd&^`DXvZ-bRn|!dC^Zq|0zx-Th03Dk zlBPtXUHLSt7HaKAxYUH9K3~OSO*P*u){0PhUO|{$kB;OwidAEF4->NsceKU_%@hTx zCVy?@P_jP^sMC5?A%u;yg}-kPOuDu2vS4$Ni6;vcdzU!8EKZc+<{sq|<7M_;eR z6`MeeqU(Shf`j=Q9(TtfIr5q@7P6SxZpmsy(SWhwa* zL`mqfL2uTY0mnJOHL0m2F{X9`^<|G{-{70#5;!drNyT)3R9n9gL1%o*d`c%ZjV|kE zSZSXP7=W7OTR9Ry>?bvZ-$HkvVlQaSF;Yt1rfhQA!KBHQ(#~1;L0oWE!w7nVqm(}z z^gDE25M{g(hLqm{L?NJ@od5jU(qfYk8KL3RTs?1$if^pk?QOQUdWO@)myz-TdnsDT zNZ^S)F>66P#33Vwh)1m<2Jg$c{N~iJldNKqm`JOgBMn_a=QDo*>>0ilqPfc^{+QS! z#c%gQG9wNvlQl=y4V?t&nq1Dt443i-mk4x?CVtp6VrVe+&K-e8aloA6!elAPg%*PZwj<3R?sDL}@A1V@l%B4g~|B@*& zgTuTFh8pI3D~QrdAis;jMpP^tfDFkDVJuD>>SYVl`|@barcyPA#me%4x}g*^nT@Go zU(9PQ@lS1KlMqYECZJ!bQ<~U(9c8fR4y`5=rxdwcih?c!mniip$2Do%G7i0YA$a5`5D3wAsYpRhEOpk&$yUguG6 zjSW2?mNO|8c58w@oF3oZ+<*V{{;fovALT5(rb}bmS$A55I)w>!?1k#bR?9C_UVvw3 zshu34vQ2m<$MP5Qh^OG$3@QJ*>M0il8<3_t)%>6^WNBp=6-(xBp}k0AMgi?&Bp=0& z1qwl@1@)yM>n^?h3Qyv5I2%=zv8>bQq*U`f%f_LfrME(^nQFv;ux{^YXv?Fo#7d4{kN#;exbe zrP>F92qq)bV@~JR7>C(6Inea@NSM}GVbCqT?bhHGWoNgCKAoyRxlIwwhfS3~Mjm7O zIiG_%?|O)~6qVhJa?Gh>YPjCN>=bTLVmTMS75P0~(n0m&;Glt-rjVK7lP68{b>`Dj zBJZICY&;}fxDjNIS4w>low(0$&b0#{0s!`-!_xxb*`^CVc^TPfENbqy4SU604||SM z^unY;u}FWSA(U;$(IpuI6vMOqq@(!(wLc(IRLD_bbqk~t`y6e?ynmyZbFmJvA?w7~ zfbb=qTP+Fsqkj{ycO6K`xe@a)bye1!GJ@65EEKO3YL&B?5Zn#E*aAaitK+K&RC3WO=c{pj)pZN%)1Nz zzpf%Q@S!|#qLyz;#&W?Z&7ng+k>nAE49&YPD0^DXb~v^8#TLhMR3)Tcxo;n=jqS~k z{bJh)Aj=_WGYL0PAy(X-Zj})PZusSCT^53tHT4pZWYM-zNoWXmm}$AMYXLp@#Gh17 z?-Y$)`*6B@y8T{ACA8TYPp>5s zYn09TEq`zRcr2sS1aOjm;JgI3P%Cp1GGA5x!Y&W)S{TWWJPu>lRnap`Ev)FWh!^`0 zB?JlNer67M9;_w_VIWsbBFHPlW6W+T&lp55|q?UVbdzS}UA-&~nJZPB06**bl*^6d*)~R+%HtB?3>?rRnLj$yR z1>=Sr2VH{L(aMmpbxH{~CX*Ix#CU|Xtz3!M)0bLWPJmPJ78N0=E*}c_4d^s4ayj|H zVg+x1->9a~n6yIjYUrA#UP-vENHJ#5fosGyOtsKP(9LVij1GEfMNVRNN>-teKs(Gu z3Cz2u<*Dyx5*bg$|1lnQch#6h011ULWdk*qh|_ckOuA+iax7|5&fw@*N4e74yrSOK zcbDIMeqX^~_HP9ZrTUOWfV1hPT?{C}ox!Z>Gb})?D<2&QSf~zY#6l?!Me@g+8?v@aXM zL%=Gl=$m^YxoO78lI>z7(*86k&;^{5|6XSE@eC*qlUY8F2z$uxZ2E767Wdz4)UK7%E7K6pUZ_h221l@H@0hPUlu&BrET;-PzKA{s9oa#oX_cLu*t=;MU!|CzOb zy|yoDd?TA)Hlfi6Yi1J>@C)&`Va0@MK(Wl7PZE7g;Vfyiw&y{2bx1(GjbM4Vv?1bL zd<-$ne0G_T^v^`^P7iWvnsT}T24p-;)&i?igCXv${|+8kXsMsS5%rGfLvTF3ICyiv z7rA4+!z}dSPA;b>5T36CjCzxlP-BV}8=0Qy$t{36FjC4l@Wolsk-^9ReU{TsshQmv z3FH_Vtz+0Z@NJPXx*HbhZMU8R&Aw-jeCOneA13t=w{2yJ5qFFHAog(jLFcd~x7-zw z<~Fl}T&{E{FBpomU7c-mQ&*7x>Aahk+lepv$)1Jor?+73LnFuw8#U(o?E`2A25aB99O$Ek3cVt?dk~F=aTNhsIg0``C>AqGv*v?p<|s zVh6dC(arF!N#tK;D={({OEA8$e|__K^CZWQ6!#&lp&NsUKm+SgAB6(ET`rf>AiKqr zDP?zKA zAv<49CBzts5Y@Efann`U0-U7vurd}3Ik-rmS_Jv?snP@4#hRmoSL)mLc7K|(gT{=^ zYTlq|Nx~qo)f6LE`-+q~;H^}jKdjtVVy&sWPrHR*=$|RXrDgWO5DM_YxphcPf%Vtv zb3LIA9cB79bmnN#zGmoV<$Z%))-ya_yq(N%k;HgjMUQ&OeyMQ|e~4DhsC{?mcLpyV zLspC-`KQ>r$$GouOOuReJo2KS#qDF1z^-e?BI5hUTOmeX@zf#@-7P61EL^xo*ZT_m zE|*lsT%3m~0KV#~W)pG&I=CCEjxEA79rUPnO$ow%M~tJs0oYBPEmc{4nz@E@*pRL(jjPK_6Oh`?7Xx&2$)@dM9!9z(b}oOpBzj;OTgHmw-4^zQtbi zOWI4>!$vn#$kA+|z)eQ1N+(9~L?sq3Ew?2~{0|xJlAPxiS)TbLRw$AiZ+M$Q{O~t4 zEe;%vUDkL7ecNXyX#?b6XFxH-(95o*y6p#2@a&8(Mr+zr4`54URFz&wQ8iv+MEeq+ z#24^5rEO$Gw6kbzC_x03U}g_f26LodF&@D8L0gSu+R`$Fop`R@A&vsaAlTf)9>#e< zo6`cdv9yx_$V?r?UsaFb9W!4#?W#XsXg>w*F@U1eb_=US5VQ9wBi?I%qWibgM6D+D zDLYLhtg~RN4A_mJ(`>wF+Q+OLTjZ_NreH)K`d}za(uo2vgcYA55Js*_S`DBY&}68l zia2Pxve2+smJy@LA7mch=^cfB2JRXrkQ#8pOrWDdO2$r+5qq3)la@a%WR5LT3jx7| zZdf`W8zhMVT~tKqt&vlGF$F81{6hns0>8830jLh*tMWBKuJ5434AfNpO(C$WN&N7VBo7*BfLkBss?<+r8d`u&_u1uStx{#E7Sa48(^8)tbwJ z6P|3ub|n#qE#R~i(Ev;A4NB*NDRTqK>=D!4eoWs)`|A67oHV~pK}8uk>1F9A9e^n6 zmrhxf$$58SNtJ53b`Cv@PczXj{p=t5{C$KTlJb@g3kX|?Sp^o(;<3=*K?Af!Bnu5> zU}LS2fEgIU8b};Py9mU?R@i$vvdLk<=~6&%y`e-5TQ|R}Y>LvC(izb^_>xtJgphk& z&T+-2K6yu0P20o-< zyZU34rVT||7NH+I`li9wZ!=k4RZDMdbl5K2QJmBL;sZ0goiTe!;U2%R&9WV!zvrQ8 z8d8i*#lU-IMUFD=0rt&s8>4yt<8wXRy+6HKKyeBH($4X>9n$ziE3bC&x)itj4bm$xB*rUXunJ z8tqm}t_bN4ybuYtXmIdG8swx=v!g2U%z0r~9xmkX^|Onb(77_XF*#1KY>UOnL3_C) z(IgKnC2bI+dVVgq*~iyiYLCmK&0>Me>Nxi3SFZ+#x)ek;c_1St?5C{3Sfdfzvo`Av{hRv=u~XCOJ;5>UGj7*iXf333qqdo>p( z2?({0PIOSS3Hrin9O_UA$Fjo}%xz65t`T}CtObi2<4?D1uhgszalba8SyIJ(R5NMX_?XU?2FI~d=1ywdB71KDo$Fw0 zceCz>+;*^u$hLg~lgOLmeK=jiPFE3vEH#Jyx!~Kmw)3jNP<0ASH&i*oat1H{{={^qVR{|GdNNfX2S)K>q z@*MQ|^C}esd&Leat~cAbqP)OyJhVa8httcC_wu__6la6n-CV;EDzH5!lti$OAuNXCkq9HCQRQ}q6d4KaX}>I? znT=fj`T<=@u@Jd3s!cO|{`6&b2&59y??iDs!XIAWet0RjZ<0AQ_4(4>iAZ<;YyoD| z^1(4+Brcx7j!;feJ7nF&VR!1K>#OWt@6@h?tBgd6@zCCmF~GguV3}!ixP#a84jVUe zCD#dO%A`V+c zqn2w0pj&ZtBQ;NvOJn^`XEfiVvQJYqUvEtLfRro3Fi9`hBt!z!z6hg-(=coDoG0-p zYv}Rr=H}Up``d?C7^OCByFdMKm|F$cVSHXOP|1~ig(*c6KndnlbTYdfnhy9dX=r01z*u&gFAr`ivlyMr{!i;DV=3+N-6X)PKhElCS$m_kUe>O(ot6gY=wV9 z-eb3O_+8rFX&Zow2(Zh5WUOo+8I4STWjUQ5Px^o4JrSv##7+Gd#euBt38|(HK#2i* zZdKDOp{2r`N+4q+4a9Ugw^oLhOIk0pkD!NOqzJ;*+jBo1p1s0&8eAZWSSrj_d$Bnz zuFvF@;Y2fzOaY=&Kd+B7d?ok&dHn2QH|^H3q@78)rKEK49$!3ue0p1Bq*oOwJ$ytg zpC1V;)w^tXYgB1XUJoqkex0oOVPpG!3=dkAa!*^ELuE@1x^ql8(c;BWM&cf$ajKWeIYMZHlU`1UTiis&!+VG)9*4_>|NxLbjH_Vl!pDq<=^5Qs~!L2A{?BE zFD6upS)Om@zyW5F=|tSE7E`QV<>xhLky^R^8a^FeS(B0k)GjFS{uCGHzqTPaNf)2~ z`%&&kyLb z%T44n8E)eA&)o3YV~txzdvPuq=;{bZ*0CiMXGi?o*m~H1`=b~o9gL)jA^NFSXsF!G zHM|;|riMC7EN|lJy(B|PuGqYwe0XO@7e5@QR&IELgK|kyp}POFpX)6KEh&$`@T1V@6*Q8|}5;iCc z-!inM_2Vh2BHZ5-h$zAGff?tRwTNyT4d0>1dgfGc@ zLKg{6uQ76WKs(YfNs@Oe%L`TGtif)^qErKP4p$Q4dbLDn;Rg?=U^_e#Ahg(o0&w|w za;6*DEcKFE)+(>TIwvr62Y)k>;Or~mswrr?*5QauB9c-8yfxJmTe-#HmoMr}*{)aG z_Wg3R?*8+KDHZB3hm^fc!D3;cb2NQt6m||gPUQfr7ExJ) z=7+Koy>t`F0M42LwoXAArc;m~SlXJzB89~|CufiVw#h>5s8twSaUL%cr2ZaO6vEe- zk?jDouE9u41|yETa0%%rL*e;$Tthh>cr`24w-%Upnp4zc*K?Gb$m8iw!2X>B5k~*t zd)Ndr?KnDmS|o%9$Pl->fT*QDAW(Bv%L}uks6CW~yk+r=w$GY!$Zj5wnEL#v^8V@m zP3e0E6b>)@rXiU%6 zsN#d94Kci2T|FzE(;QtLnAK6=%j7||99_S3s@Z|jCsggR$G=@4LAr*+I_J>|`jSgq zZpQl(`?ViC?|@aC*44j`r!b{#Kjn>$UjsfqG|v${g$Sr~jM+2&+4CN^6bw z{)CFtF!<|SCp_&Z#AZpF!r$UuvLMKBFd?{P7PPM)@JbquvutmC<)rFWa{qHDbCfki z+}I8c6D&-0jWwle-Hd}-Y&DM~3b*x2mMPZn{t0hH{&!W5{O#|BTS`0{geB647QCNV zc}rA-)T#)XrJy_Fuc?dph=Y@luc-5;G5U{})g+{Pb+)4vArB54d;yDNzPU%UI{r*} z@FzP!90WbF$V~uqK-v_|wk`^_1u8pmEKN99_3}>T3CkN4$4!AfTy1a)WaXKou|y+%+-h4}jBJW#-R+~RzmF;lha z%5(eS34sJ(YZdz9{&adL1G9SL*2caXisji8b+nqlsSfNexRI+MBSa!H{Aoi5MQYJv`=CbzaQAR~BR_U?^W##pPsg#? UH%SQ7a7aCrcp#!6*dL$$A2WKHHUIzs literal 190943 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μLgRaCC&`OtbSh3=FPSv5~SU6x%02Lu5 zJ%XUINhCTl(z~B$FqzF=>szTMvG-$qQJiEup%Y0!8Oorym;oQDW#<|{CK(lG_1;ul z-Zb%aO+~7Y4fB*@@{<2}+T*|dzyIIw*#F^&w6CtOU)-MG$xd_p9D+ju{kST5MYM`n(gjJfJ3zM2S|9W$$ZMv|vc76G4`|Rd#3A zG__-W20|+LFfX17P*4>zeAKiZWa)mVa(vKdhSi1ic>~63V9J{z-(D|Onp3U-^Z@yj zkPRb|vc0*zXa`x$T_D8%8x|e%>dRZ{Zd}VazrVQg6=!IRbq=W~l!d|TtA`Q9*7@+VSx-@|x@ zm^K!sb}djB4qjBLk^8$(L4jkatXYBhv^hl+z^C7zo%A_XH*!wyA2Qz<(Tc$`^snrK zI^mD9zTSNzMNr%sw|c1Vz{FR!JeU{yWA7J0RDC=F*H?G4uS+_arh$fB z;c&MTWkg;use~rY)sPc|AgrG2?b30nk>PGKvJG=Zkf)!Z*=N^k;w zEkX?@Q`cDzWJCPI9LUa{tKVyV%*zC?p~l)GHoU^lLTlN2I~n}_g<`>$?p55)($}Z% zo8g+cP`=#Q%gi*?6yqEqCb z1~j#`@82)f(G7jv2O=fyajiDq@#niGGdoRIOf@d zHZ(=wiNPEca&tXK3@Q&=8;g#yX?sv6rloukQXx%mvqi?J3a6;yV<8^If~xRLK43*5 zq&njYTn>CJl;C98y~E|$Ru2*Fbi;_E^;;R|-I?F!cW^UXK)t$oM@SKwDL*&xL4B#@ z1%!4Ger~^vMk2vsB5w{~dbhfe(pWq@V=Gxg4y;i~#A^e8k?<)3EbA@#B@JY77tM)7MZ+v{T5m6(s9k~Z(|K{XVD&hfKT;4vwt}g7$eQ+NW;>4LRu73z?!}uD>B1k7WB>+uH-uOH6{sr-OH1K+;w88clW4 zL-IAt!ASGvoXq<2rerv#%B&zbGMkJbb@d|iDPGP4C z$Tr+qHP#HnVhSfyYHHR+HO*cBoWraZ#gwD|v-B?V&L`hh^um>*-LYx_>R8*7i41B& z68in5z}jY7*?QnIb?LdhpKQWjgsnPGqErZs?vDgOUlZj8J3lW%$+$qfxnU%ig4%R0 zql^*C@Cb~SN#ZPqfKGE|@()5rhgL(oiGS?lbc)6@9iEfhqCTBPO9ze+-QQdv?jJ|J z{rILNdnnEuj@Ycj>Q~oxi3@bL3hNEK+BK3>Ek3fES(=*^pi=4GCznzR(+x@%`|6lT z^VO_=ni*f|1k3JIa!VmHy?#!JEB;7K5`mMLggzprJ?v$YNNy^0(5mF`;bL108hS~~ zgVCy?aZ;j8bMm&BAFE63zDSW4pM+J!+Vn4|qefb&zOhoN7ht!fJz23(v{XYIg39n> zgHR-dFEY3L6yEu#-Haxvg(2A1v`twc){SYrIB=}GRdd^4jxT8_xOj1Wc_XA#Wt9aY z3>2_8@%lD+mXFYwbQTiQRJTsJ)eDhbn7b=wJAu&4BuKrjh3Dz`IrCr$xP0eh`mJ$= z<&I*!qiLxV2E@lX*Jyp2v*?e&eY#`z{K_7ur6iuVTi>ZON0Fmg&{q)Wz5f^o>Bja) zGAxy2(D6i#{OiA`munnBu!PWokf3F^H#vy@<8B+k9mHQr$Mj8Ghc~r_hEXb}H#?g! z%cTg?B2%4N6wY2hZ@;TG`fjU2OS{I zIF)mm09FU~+B$9RZY#uggiVL#@-u_;)__PH-AblBhrnT$>V|N8&RQadQczkgL6L5< zNiM_2TQZwKLHsAfL;UZI4$^AbBi4r>2`-mDYTimSQJ>{h!(7GsOC7U2Ti7Ud7T!9i zba&zsiT!7d!3PUP?(|myFgV$MKh?l1AeEWY7`_kJDr>H!DV+heL>vi?mlt~bP=0Cm z{nc6CB(&7y7-eG)TZxgD#fo;V9605bF}uU0nzH ztMgF%Y05e@rmJ;L+d`KjB&R{-4iXb>2gqk3)tvjMV;?2p=zq^3X-s>T@!dpFon?TbID7)$)S$w`!mV66n9fO+#>N}Td39)m2$mz~9F_zz z)nRM^O6Wu(5nS@OS?O;&$@A4gw5oX$Z9ZLW>YHaI+E_=yzQ5fOkP@| zTOc;@7wMfoM_FCi0`meW(5-0o30n*OdZ>uPo3i55if|U}fq;5ReX2F6SWGh}RdS(@|}jP`u6sKQ=p_On304 z%XB~_OXU#^hpfR_h)!A)4mM*v(GV>iq(}GVj@s4C;bKsr9n?_C4^rVus3>9Z!M-iI zN?s$VV0U}QU97%m9Zh(mBy(i7#rQ=YsM`$lyjC8lZ;9#KG}4v!LCH!fC476CX<`%p zU>>t{6Xvt-{f`g!`xC}>4m2usk|a_;cKg73Hl+VHx)&?Ub*?BHOT^{Vjsv~K$8C)9d%o3fpLM?Kx&h6=UqSu+*krqB?CjO{u7sK)COQOTP} z{O-;bN0BoW>8u`(#LvY6Zf-xfd@i~+)iOz!(Kj-~CccI-a%nNOuMj-?izD^Z76t{^ z0~`sYd!(hOI0uYI$|*XMm;^hFk*Sq7$VT4Tf}MyFTRnu~CS*CN1y3?->NN!Pg&V>A zV5VbXiN(E1pc+s;rdGH%h$YTAP1ddn-Si!s=g~a(3Xj4m7Hv{ z?p&2jXs^p;iH8(9oKZ%k_!TnmKKXSIh_4ha2MEHjW{~&qZ@<2|KY#P~`tnS+uk)9q z?N##bCo|`C+dZ2D?DF zSJKfIRTI}u5hD|%#>Y^hs(t92+8A>{04ODPI3r3^hA}28MF_s?lwact$e~jnUdzJJ zg?7`gdO~67b6I7b`G_L?IiFnf*tQ3IVynU^*)x@DDEh39<&!Q9ofaOA-YDp7=q;D# zlaRGxGFF^Y_mZt_Mi;yFCDiB~;Y+=ls1vn96kllq`scgM{B%~H7ig;cJ6?!Z=3E6n zq$>*C<8(48ov3x!V{p9HGTqBU!CQg0vD_-lZmkr65(=?hT zZiFV?q`{4rO!lpwFD}n7uCHEy@$O!4kbHdj)f8#20z+aoB?fRKG5)j{fIGRu$g;`8Uwd5d}2#k?Ld{afcyS%@> z)*sCv+JmB3FF2@fBd*}RWWS{h*{O{f)l(4KkEt_~ZfYH8u{ER^XBCbb+S^LVb+nXY zSQpG(63a;ziRdm3)o_qze3n?$XzN&(pafHAD15B~Ndk4thh;#uy>W#%Kk2JB@S#*1 zhiEkVKRTi4e$Do%Ux?Pyt18<@vmWy(qjVLf0z*3I)wzSB%WAtQyW<|2Y*w7K`9t+E zSLR&XLt62$+VHbDxL-e6O{_W`%7^bRZ&n~#CU#`uQR6yh_CG3_=Zf%E4HfekbNJ^R zn38F{vC1sy`jag%`bnlw^a(UZ#YwamN~tSm7&2MpbQF(e*O`c{u%BhixH1nF_R*$R zpepEF0lL4Q%^$Ef$3a39t1;pIX}4R2<$Yq7Ng2Uk->w*&&S1c))|`PD3Pl8PAIYEA zh_f~>j;BN9qy5LUqHLlVZE()G5G+Dm12FP;a5^-RwLcg29J5l?Qc;4bP1snx~ z1G~FxB!LqM8_k1d@Pg%UCz(bRfrqWbSQ$?u*8eW5Iv8lUvND%7miF3kBQ}2@%uW-K zEo5lRU(6y)LWGf#wU35<1)f|LV))@!pu5bsEz7(A@;7Jq@6PY!OA0#rmq*Zz9_F=0 z2u+<4h;Vn2BJE63WrAbk%5@VzGO)BIeJP)0!fM|O$pA=VJr@WM7ef~trMe0v!C7Gi z|I|2r^$8hk6r(cY5I3PL1zhHVxJcBzt--z0BpZ(WV$o165ZvTH8MZ(CDMD+Q&%yxKzh?}QIUcOR?J``|Vz6DvRW3P=PeAE}k*K*qI+X~Yc*SEKC z=gG|KOL!%ST{kl_;>3wZW@SBE+`iY>S_yTojc$+tf1wV4 zUBaUmX9ntJgLLRCI3LbPhh!G0y||N#I-`jwdgrIgg_kue)k|ddVw$o%MXVN!x->Tu z5*QM^Q<}85oiM`WTD!9K>8HE94=;MoE=a#z{I~a2vM<1Z2{fL7Ba3|&${606OeAn6 z=hy#e;AT5v$dqgZOpqIwhH=XE0b|Galnh0y?P5IsT3*kLRLUBzl!`k4|0*jazo>OxRkkTLjC;HuU{BP{CNNJNvc&^>WFZ``2Z&~?B-rqy+;E(WfiUJ zatc2XOE6499jgd4GuSWhkvLfE1PU?q)Crz$F6ZdJth(y)UcwmCW4x#V=)A_zVWAf5 zv#Gr_Cf)m@!e=|os7E@N7YItR+~iX7st+Gl>2%b>;B~SSVCZ7u;24q+gX&AY!pSQm z^8b*s3OmSKanrg&w1afDQu(DUZ`-ouZ60}!*k3VS8MXtW4#Jt8!;s)Y+IyY@#OhXW zLs8t53*Et|7Ub^Cb|Pmv;Tw}VVAeV7aAL!&6%Mzj2i~Qt_XxU5ItcQU!}!PSzt=Ba zj~Z3O2@ILrZ@$M7g3**9&bUH_CR4i9?WaPs`7uT(%euHz%Sq?H1eu{0*tA^F$rES* zw9DYVqWVhn@u#Pk5B5sg#}Be|TK#xMTfF#s$ehE|1tQ2c-B@$uOY=k6MD>-;f(gY4 z_>or7qNb)Td@yujh5zkpV1 zzc=rf27ib+78H`kzJGm1NO?~+eU*i}k!0k!*iL<+xrOu3fij0A7MF(AEA`zR#YXI= zV=l2o!cla4Rk#AqvTGc)_@tp-@b1Es7fs}BW^_L#*WMP9qJ0ntRzp9znn`|XonIUr zTaKV4`j^lB#`(>^Hc(cGGrh!VwPX1WK$EAC-f~g<_Y6W~2jgP~>Ne1C0<3g+X{uN= zLVCaj^+ZHLTiYY%ZTJgBpn&ba4M}E*GX9{+8U}6Hr3Ulx=KY6c)lOpqLiu-621$Zp zKK+VKj{c_Ba6#b^ZTh+;q#?Lg>1TBc^uixHp` zmqr=L+?;9@U*v)ysvToYmnv2WvLWThvv_FmFyYT7oED2Hmv4q@GhTvM+`)6u{!BJq zz{q{oh9d(hoH$$U4)n-F;S$*A%3&@Q?z(i1tJ_)rXD^9)L(1=@Aax8Z2a1;7pg$E_ zZp8wU@PmF_*DhS@hqx(5bvwK93a^X*-J%K6z(3E#W#fOX#W5i(3jFgw@HZE(rmg%E zt2Edjn)$&SHD%vUio~U_pVT{SW-T&TEgDMX8kkOS6_VBQn$IaM;dZtQm#-eGM*Q-e zwFBobf428NH=lIzO{(Rq-`BbZZ$?RhW>2*?Ca-vVgHo+YL8+PLeVr|6B0Y(pN!x4R zRi0eaExKn!=u?j_ehcEPQyq;-ysAL(N4yY z6m1N(m5+79XjH3(#PVbWb5i|~Hy-cq>IdA?@0`&AsO@6Xe`<5U*VoaJr$k!#uwx>U z?d6>)N=W@SNF6$wr~5+~Myn-UoxPxDPiTCE>zRI;^+=%(=k88ZTE(oZ$S}Vgfc6of z>acWlIBiPu=Tv8N!=n6Sl8Xt%@WvENRE_m};A=)ujdVke94oRkgkChVJaN{`sqO2h zd0N8tknJDprImYIs?NpyJil-0Oqf2|B~}r@jpau62z*l75f6(?6i|8l?x6XFl_MmnXO4vbjR6wWr>+;-`GgEV|-PP24pG$O^ zGPk`cc|?D^L^uuLeQF`V_V5QS^W}xpP8hSp6zD1)kl*MabJWVN<~)F5FnMI*EcnsnFQ0IDl+C z$Y+!FAH8a-3cW>uDEpm%rphLK!$QGYvPKzwX>klTz~*;9-(f1GO{W-{0af8C%@ti1 z`^35bZb@DDa>p0~=%sC|XXv7XAMJO_{P1&cu+&>l8(m5){hdak;90+>WeMT2>;ZYl z8|*Qz^VEOB8|rnM7PG4rDD#Z5SCu9-qldSxwYI81xGc{R*$CKxQq%$9Fp2kA#!f|+ zRYYi~mC3peVK#o@{IfJAK^T006k zCQGGQ5d=mddmF4Y{*P;;EHq(%_u1BVJ5iu?opqhM8=<`dLtItdo3|`fR-pb zOqUihGW2xV!?g+EX|*M6$1SAQ&I`p1mYX>bpkP?0YA2evEz^bILE)D7ZY#kafIj0S zRty}DW`U6kck@V>1J8kcwqaa&VXAhUzN9Bo^dg7w+4>ub)`NL^`|_n6DV3|kV<*ev z$lJTuZ}in2qM^Yk4G8Wnf@G}=<_4y|npDM?V386(3?pdDOx6)|i-#K=;NO}r{65LV zL8H!Qk@H$RZW0UxF11s7isL%DBi`1l4}fQJSuvY`jD~W#>2ytdPBI7b9VFw7X1Iu* z>A8oZ=Ms>9WOsUe82*KNMCawEsWQ_omR|tBc&@7z*qi2slF2Fwh4G87b9AvNU4RdH zU+?1^`QEhL>KgdBA}F2YO9RNyqSJ?;z4Wzz`S?yu{o&)|UAV!rmKblCBRNn|PdOhy zuZaU3xV|;yo9l@|vzUL%cQS$P~`f2hCCF1OI z7yyy=GooiKTRqeQ`(Zr;M*T;kspl&%L_sy~_ELe_!tgpJVsc+t_I*HdmY-O0eE_o& zq|@_nlIB7d`69~hI_0t{>L;Ir_YwlSwt0o4c?)8tlvGYM*s(bO1 zT>i35$%}UWq3kLQI8ba;E2@?fPEl6p5n_t6Bs7>|E1R}>GEfnHHf{w$x#n!eE7m{= zF)@y04XTIs=Dh4n;zGs8AHV+-UZ1B3(qwfZd(Q{nL+HnIZgD&DzHci};i9*o_C1_w zV{aippz24z3&A>9`Y!w_fc?eez#mngQ$(`YZMhEp2=zhTY9-|glt?tW&6|9|3*Y#| z>4*A_^~YcIwHo8b3bb_IZaYbLAm7cUrr0DSQEA?P-Y$kfE>q#g&KW9OJ0p@qHJo*J z%R-+5gG;We^Y5|BI|>SJdEMc|-QzKzj%flq>39?~e0)4^#N$#$U9r4U5l|sUm=o#x zQTCl|*ocx4(X`$puc_1xo?QtE-$2zj9;fmY^;;}ciPlSb`k&~fbS|w(@-)L0t`iOyi9$4PdpGf!UHsp97t$DZoGg0{{9zyu)|)# zj`lHL`^+~V?Y3~Qv82d-jq_9?oi%*Of=y8lqdqr^O;y|Y@~ZM7adOOIeyu;S24AY! zk^<`S#7`iCXbZNbB5jA+0U<0 zh0mShX=6C|p3=R~s#=ALD!bZk2&i?oRt_0l=HxM2-Mq*~BC#YLPy?UZ11 z_5-+?sYODFP)UuAaq2}zKW-1Y|6pk?i>5+71l%%(>t)GJ6QHcP!{CDj1c%cL2(%&5 z_>ln1Xp16D3ep(4QU}AroQq;>%;n1RXR#_pU4#MR!uVNJE(8D?tD^LxC%XpJcZqSv zQXB9wy&9Psq@AuyT5+Y_bEzb^)&?{x_mYOS$BBYSZaiojpk{wF3nZ&EcJ=z8Ykhw- z0m7S31|8#q7+&sp_ba4a)zSv_MS2c(c%{za(OjO$e(UXm*#h4ZAGYzd|3o%Q|3)KS z?qjykOb|i2d<%SoN$f7JrLu~KK2hVKbjzw>MR47rb^(Hyw##;r2tQ!+pI=HMC>Ja} z-o1SL;_aKq#|KFZsgYrWgvnYPM(m0My89R=JoEm|e?6=%y*f>H zqj>j%38-HBo|S=6IM44QW^M)}9Wuj_O!g`{tSA{#?9t{M9BQf2W5g7+_E;?^0+GjyPl+iZ^%Vs%8A7Y(}(Cj!mD@~IKKc)hX5uDFjEn8 z{Mc$Fs<{VsYH34x!=OWAYoUAlHb^gQ>hR=p!h{^BtVY91sduYCtVhkpdMp$~xCDf3 zS2x<&*^SQrIe|DeIR~kyG6OCcdHuJ%>^>Y}gjoU%Ce>Jg9SG0yy>6Iqd%B~nlfAnC zSog1CAfU6lSu8uA(h&s)SAC19aI-eMXvR6}$5J2&%@A&~N51@ZLB$NRX#hhxs;gb< z7GaOl@|fP`wfTOVO%6{K?K>*g45{9;!b*+n2`d0}Y z&3%@A1^q3TE|zhq@7Z=M_N;3*cb`+^X(|bo2U1qbOI`WR)3bqa#rsTyenmifg6Q7h zOIn}n3?V)3IMglf{;h5qJAXFK^P(d2fi6j?5QA8j$#G;#&=*3s647DEifC>xefH-1 zc|<|MHwbDuW+4qg4<5_g0pZPQ)9TXZmV{rL7!j~|O!N{gmf2Da=q=PlA=b})QyQ%r zX1T8>)F1iJyhhCX{DW(%hh{c$Ti69H)HiYYJWx`PHYRp};n~ix`H`&TlgtXJX3vFs zd7rztw7*2^D|lqAvQV2@r@FtmQcjE0-xpcu=&S+3bYgtEVES>#T3nfif0JtzmbyPw zm+N*L;20j}y#?lLMk=WuBGSUXqXPTV__R(pEgndk&UK1LkKM+RXlNj^)>+$hD&J5o zN{qMbPt|i0Ar)dH2&eCa(#ABxOXAsoYs;zRM2{pzT4Mc^wv(!NklQEeC|w$Pd9D|R z(Y358+*TklNuyc{)tF<{Hg?*w=lgLEKEFQN&*{h}q~JMQiMQ}}MEE6WZp9aUI+SI- zw>W&5S@i?`MQ*pM+~&&`04onwG`9B? zWA~2_Q#LIjtPrU{zDQE3B|bSM?2u&OS=5d9dfM*R*O6hue`LtsFS5D>-z|2z+P<^k z2|u!92{ZrF=wV~Q!4_AvztQ5HIbt;eze(yCkOF`u>^i({khze$h+LT3%ip4*6pZz! zGkPnRo(!2hW9_ku4K^TW27sKxCp>ta6)(1ARDxM#;G=+O@HQv5;aZ_NRnm3*3_7x$Fm`z zzA%$dHOHz+m)QQ8Su1s|2WZn*uFN;|Ad?>YD`7hsv+>ZOE`cjVOGej6+@tH$f2JU} zJuMWlmqTK^j`2A7`k!(!CIy>m^$npU_ICljYiHSgBZHQpnH}rc9Y+12oBvvUEkI~a zsFr`WK>`m)P~N74i~B!EPi7DFjEPfvV`e1L_7h^wQ1Fgr?0Is^0aziCQbi5}Iq5zZ?8C7Iz6~ z7swO`c<#1gF!W+^lBLMCtK(lSz2*$7$^G0O+wavWDF>H>jItbxyE72D*Xgne5rLqR zH>45nF-;Ji(K_*TJp0?Ebk8towjA3n3S#XVsvfY#zR6ML^R!iv;|7cqca0M)Eju_6 zFF&J7LB~*nP*Y8I6B4sG&c;*cEhGG$$|m+rPxiWU$P|-o%a<*;pl4G7)*nAr z=F4Rz-nZBM&GJcWvq|3T*8c7S-p_6y6Y~TxsYor~7A(_Ip{b7;Agwbw!OjKuaxreZ zL{g(SUXlu9zzx|hv2_?zWX{YTp@h=u7#X%f|H+w<^1ED&;yS=iaec3b>;&O_>f_!0 ztB>E`Nl(QtSABSreQ`Jy#UtQPBwX4E!~_r?>qDlpV^1s~YgIZ&?L+DydgGFGNIru= zaIm2A3ebA)gqp^58Pu9{iEN$A9WVIfjFkPjXDbMGe6J{$Hq|DK7LZMGk%eT;n?I4U zJ=#*58_*eUvM<`=(TQKvGNsz_v1Ws5av@T-=|dG??*oABWZlh2w7#E^50 zG)?(+w@j5zZeR~*Tkej0!O5{7By0>1L{if?JX_aH<-t^Rl+vV_Y3HZBEY?aSau2LT z=>+uMZ=&s5$bE_IZ)J{*Jgf&5swxI^jaDZiZ>}zMviN!MhafFIPSQrGI_ZoN>?;#zTI4o%$ zJ?EA~9yLMH)JrGbLS5=onw8Gir}Q6H43~lSE+!2GSLKM|XOz^OtQ9hv804Egwip)_ zs4Bh%R}#SJF^D<(W@fN|x6~=w-;wP9;eW;;)+JL_d1Tl-a(4!|-EEncnI;&Y5|&hU z)1JFqzUO05FdC=QB(!Q{cN~(%Rwf#2Q5Y;?CdRIO9ut_3FL9Jhau@TtB3xdSD zThhxOnl^bA5}GrZR7-ZV|G7g(EWMn4384j;LpN>F)L{w*;qhhy6O#BehIiUUf`ub{ zoe{bXzy16YVA0|*e8f8N8eL}dyi>bxAZTxTH@$G)^@t<9FYF(R^c<<_6Qo-A{VHu% zjr7Oq=vOA^wDZ7DBTEZHB_DT{hR`r%7_wBP?viF zWZf7?1axoAW4wOz2jwCIF~*DWyQMM<6-=$U_w=q%C6F~1lE>N}U5?$`2Hl>BW8&tU zgyyk|mU>O!7S^d?O06pxlJ=P3B+mUr2NQlwecR$IQRA-R>#;_{?O&f*&KXmXu;`(2 z&-SsJ&d3Q?owa9)&P)-!#(Bykv$Qq}RCdv{!?V!+zkQB-7ruc%qj*+?9+wR4xbT*+ z{zlzZvZSETW47(s)|}-Flg?tBf1l?Bl*1Sy@H`-expo_a|PXw02js)f31lq|W)Db)HJ#irNhFP+Mxmn@X(^VmHP zrmFeIAuOsyCUJxwRQWy}u`_0iIHS)+Ta7ve#5B?JK44&k7vu8oSIbVuL2K@ubPa0+jeoJ`8;K zM57pYb%HQ@Q0+eALLb-CWv)4hy*6$ zLJVI#lE}Ii#cYd1be5mZE^pmtnO$Ba7W)KTjM}}Xdda@J9E1=&@ZQgx_56;NGG2&g ziv)ji9-fy5`UXU?p&_AJ$hof2RW$4jV?|b)(U;iQUtz?4J6752#tA}q^4b_1*Kxpp z)W-}PJ00eR1ksiY5KjjpK>L&h#zQ06i+#Z+Xe?cHLVfJuEg4O6*j-CwoMEEx4-hS= zZ`kWFR)w0&rS>&dgz6JxX>m+!(15o~6;J&kX_#)~1Yn_X}*;^#;76 z%GUkAKgxULcC!%aeru=}m|!qUoq~FYyB5dB2G2>CteG&gJBAvY%G5o32@QgYkQ=+& z{I-PO8E@x%E&DqZ_Nzx2)9vLNGZ=TB@J{G3=Pf$Yhymxx z4fgePqJCjM?=AY_wcPI@2O&-1-mA8e4^_q9-Wv$GobK%>_ZFDKC)h(VRH-?adpvdz2mk@ac;5Hd z5OOHHIV?2Djs%a9%Nbnyc%IbAn(1V{G?B-{k(&jEqal~EDnx+*9?>`}8tFt&)>O~R z$*_?nyM*6R9*39?ny=G!t=nU6z(wK6nITVXe@#yG6?-afhrk+w$ZV^00}v#{PP5T3 z;>;?K_S`?ce)Fi;TiUYrhMh(b=qsGs<*lk>`#FV?jsq7Qza%5X_!c_V^z()?tGN!n zB8F($5fV}OwV2_0idk973!R+A^2i_ISIQ|^Qr9R)9xD9!gtD^58|K)>4&FndLV8#j z=?4XKixl=*lXlWoHeGOU=Z}vse^IF=&Muemh|rJXJ5@(op3BN{(^KI!?*O>^~`VVOvS@HxqZ*HXyxTzuo$(_GAP68nD}**UxYlL{M`}z z`b?-OxeV{sK2zxBub?7bLAD;1K!fXSKy-MWJjV z5YA-deM4SYooli*jIr@U1t#37s3|LxlPyhWW7kKJPW`d<@ zxxu(G6NTgUWP;;xP}s4ql^CLioov$s#$HE#lgiC}J`QZQt*zy5uROY_Qf7P-C%96S z(+MI;&O4$3DvHI|x8Bt-s8XOLAlG6;4|g%U-(7~EXD+R~N;xgH!%S&^$X5h~Kbs5fy0ISO?CkXN4>#Gks_c;qE7D1#`|$d!+Ouc;C}F_n24a|YulbM z) 0: + + layout_box_col = item_space.column(align=True) + + for mapping in uv_mappings: + + item_space_row = layout_box_col.row(align=True) + + if mapping.value and mapping.value != "" and mapping.value in bpy.context.active_object.data.uv_layers: + icon = 'GROUP_UVS' + else: + icon = 'ERROR' + + item_space_row.prop_search( + data=mapping, + property="value", + search_data=bpy.context.active_object.data, + search_property='uv_layers', + text="", + icon=icon, + ) + + else: + layout_box_col = item_space.column(align=True) + mapping_row.label(text="Unsupported Shader Mapping Type!", icon='ERROR') + + def draw(self, context): + mat = context.active_object.active_material + + # DESYNCED LOOK! + if self.draw_desynced_look(self.layout, context): + return + + col = self.layout.column(align=True) + for mapping_key in sorted(self.mappings_data.keys()): + self.draw_mapping_item(col, mat, _UI_SPLIT_PERC, self.mappings_data[mapping_key]) + + class SCS_TOOLS_PT_LooksOnMaterial(_shared.HeaderIconPanel, _MaterialPanelBlDefs, Panel): """Draws SCS Looks panel on object tab.""" @@ -798,6 +892,7 @@ def draw(self, context): classes = ( SCS_TOOLS_PT_Material, SCS_TOOLS_PT_MaterialAttributes, + SCS_TOOLS_PT_MaterialMappings, SCS_TOOLS_PT_MaterialTextures, SCS_TOOLS_PT_LooksOnMaterial, SCS_TOOLS_UL_MaterialCustomMappingSlot, diff --git a/addon/io_scs_tools/ui/tool_shelf.py b/addon/io_scs_tools/ui/tool_shelf.py index 754fa02..746aed9 100644 --- a/addon/io_scs_tools/ui/tool_shelf.py +++ b/addon/io_scs_tools/ui/tool_shelf.py @@ -22,6 +22,7 @@ from bpy.types import Panel from io_scs_tools.consts import Icons as _ICONS_consts from io_scs_tools.consts import LampTools as _LT_consts +from io_scs_tools.consts import InteriorWindowTools as _IWT_consts from io_scs_tools.consts import Operators as _OP_consts from io_scs_tools.consts import VertexColorTools as _VCT_consts from io_scs_tools.internals.icons import get_icon @@ -502,6 +503,33 @@ def draw(self, context): props.traffic_light_color = _LT_consts.TrafficLightTypes.Green.name props.vehicle_side = props.aux_color = "" +class SCS_TOOLS_PT_InteriorWindowTool(_ToolShelfBlDefs, Panel): + """ + Creates Interior Window Tool panel for SCS Tools tab. + """ + bl_label = "Interior Window Tool" + bl_context = "mesh_edit" + + @classmethod + def poll(cls, context): + return context.mode == "EDIT_MESH" + + def draw(self, context): + if not self.poll(context): + self.layout.label(text="Not in 'Edit Mode'!", icon="INFO") + return + + layout = self.layout + + body_col = layout.column(align=True) + body_row = body_col.row(align=True) + body_row.label(text="Glass Reflection", icon='MOD_LATTICE') + + body_row = body_col.row(align=True) + props = body_row.operator("mesh.scs_tools_set_glassreflection_uv", text="Enable") + props.glass_state = _IWT_consts.GlassReflection.Enable.name + props = body_row.operator("mesh.scs_tools_set_glassreflection_uv", text="Disable") + props.glass_state = _IWT_consts.GlassReflection.Disable.name class SCS_TOOLS_PT_VColoring(_ToolShelfBlDefs, Panel): bl_label = "VColoring" @@ -590,6 +618,7 @@ def draw(self, context): SCS_TOOLS_PT_DisplayMethods, SCS_TOOLS_PT_LampSwitcher, SCS_TOOLS_PT_LampTool, + SCS_TOOLS_PT_InteriorWindowTool, SCS_TOOLS_PT_VColoring, SCS_TOOLS_PT_VertexColorStatsTool, SCS_TOOLS_PT_VertexColorWrapTool, @@ -607,6 +636,7 @@ def register(): SCS_TOOLS_MT_MainMenu.append_sidebar_entry("Sidebar - Display Methods", SCS_TOOLS_PT_DisplayMethods.__name__) SCS_TOOLS_MT_MainMenu.append_sidebar_entry("Sidebar - Lamp Switcher", SCS_TOOLS_PT_LampSwitcher.__name__) SCS_TOOLS_MT_MainMenu.append_sidebar_entry("Sidebar - Lamp Tool", SCS_TOOLS_PT_LampTool.__name__) + SCS_TOOLS_MT_MainMenu.append_sidebar_entry("Sidebar - Interior Window Tool", SCS_TOOLS_PT_InteriorWindowTool.__name__) SCS_TOOLS_MT_MainMenu.append_sidebar_entry("Sidebar - VColoring", SCS_TOOLS_PT_VColoring.__name__) SCS_TOOLS_MT_MainMenu.append_sidebar_entry("Sidebar - VColor Stats", SCS_TOOLS_PT_VertexColorStatsTool.__name__) SCS_TOOLS_MT_MainMenu.append_sidebar_entry("Sidebar - VColor Wrap", SCS_TOOLS_PT_VertexColorWrapTool.__name__) diff --git a/addon/io_scs_tools/utils/material.py b/addon/io_scs_tools/utils/material.py index 34be39c..213a213 100644 --- a/addon/io_scs_tools/utils/material.py +++ b/addon/io_scs_tools/utils/material.py @@ -436,10 +436,13 @@ def set_shader_data_to_material(material, section, is_import=False, override_bac attributes = {} textures = {} + mappings = {} attribute_i = 0 texture_i = 0 + mapping_i = 0 used_attribute_types = {} # attribute types used by current shader used_texture_types = {} # texture types used by current shader and should be overlooked during clearing of texture slots + used_mapping_types = {} # UV mapping types used by current shader (created especially for shaders that use UV without textures like 'interior' shader) for item in section.sections: if item.type == "Attribute": @@ -475,6 +478,20 @@ def set_shader_data_to_material(material, section, is_import=False, override_bac textures[str(texture_i)] = texture_data texture_i += 1 + elif item.type == "Mapping": + uvmapping_data = {} + for prop in item.props: + # print(' prop: "%s"' % str(prop)) + uvmapping_data[prop[0]] = prop[1] + + # APPLY SECTION MAPPING VALUES + mapping_type = uvmapping_data['Tag'] + + used_mapping_types[mapping_type] = uvmapping_data + + mappings[str(mapping_i)] = uvmapping_data + mapping_i += 1 + scs_props_keys = set(material.scs_props.keys()) # if overriding back data also make sure to clear attribute values for current shader # to prevent storing of unused values from blend data block @@ -492,6 +509,11 @@ def set_shader_data_to_material(material, section, is_import=False, override_bac if used_tex_type in key[14:]: is_key_used = True + if key.startswith("shader_mapping"): + for used_map_type in used_mapping_types: + if used_map_type in key[14:]: + is_key_used = True + # delete only unused shader keys everything else should stay in the place # as those keys might be used in some other way if not is_key_used and key.startswith("shader_"): @@ -677,12 +699,72 @@ def set_shader_data_to_material(material, section, is_import=False, override_bac settings, map_type = _tobj_imp.get_settings_and_type(tobj_abs_path) created_tex_settings[tex_type] = settings + # collect old uv mappings per tex_coord values and delete them from material (they will be set back later) + old_uv_mappings = {} + for mapping_type in used_mapping_types: + + uv_mappings = getattr(material.scs_props, "shader_mapping_" + mapping_type, []) + if override_back_data: + while len(uv_mappings) > 0: + + # save only set uv mapping tex_cord:value pairs + if uv_mappings[0].value != "": + old_uv_mappings[uv_mappings[0].tex_coord] = uv_mappings[0].value + + uv_mappings.remove(0) + + # apply used mappings + created_uv_mappings = [] + for mapping_type in used_mapping_types.keys(): + + # skip unknown mapping type + if mapping_type not in ("perturbation"): + lprint("D Trying to apply unknown mapping type to SCS material: %r", (mapping_type,)) + continue + + uvmapping_data = used_mapping_types[mapping_type] + + uv_mappings = getattr(material.scs_props, "shader_mapping_" + mapping_type) + + # if there is an info about mapping in shader use it (in case of imported material this condition will fall!) + if "TexCoord" in uvmapping_data: + + for tex_coord_i, tex_coord in enumerate(uvmapping_data['TexCoord']): + tex_coord = int(tex_coord) + + if tex_coord != -1: + mapping = uv_mappings.add() + mapping['mapping_type'] = mapping_type + mapping['tex_coord'] = tex_coord + + # apply uv mappings either from imported data or from old mappings of previous shader + if "scs_tex_aliases" in material: # scs_tex_aliases are present only on import + + # if mesh is corrupted then tex aliases won't be filled in properly in material from PIM importer, + # so report error and skip creation of texture mapping for current tex_coord. + if str(tex_coord) not in material["scs_tex_aliases"]: + lprint("E Material %r is missing mapping coordinate aliases, some UV mappings in Material will remain empty!", + (material.name,)) + continue + + mapping['value'] = material["scs_tex_aliases"][str(tex_coord)] + created_uv_mappings.append((mapping_type, mapping.value, tex_coord)) + + elif tex_coord in old_uv_mappings: + + mapping['value'] = old_uv_mappings[tex_coord] + created_uv_mappings.append((mapping_type, mapping.value, tex_coord)) + + else: + lprint("D Trying to apply negative tex_coord in SCS Material Mappings: %r", (mapping_type,)) + # override shader data for identifying used attributes and textures in UI if override_back_data: shader_data = {'effect': preset_effect, 'attributes': attributes, - 'textures': textures} + 'textures': textures, + 'mappings' : mappings} material["scs_shader_attributes"] = shader_data # setup nodes for 3D view visualization @@ -696,6 +778,14 @@ def set_shader_data_to_material(material, section, is_import=False, override_bac # data[2] = tex coord value _shader.set_uv(material, mapping_data[0], mapping_data[1], mapping_data[2]) + for mapping_data in created_uv_mappings: + + # data[0] = mapping type; + # data[1] = uv mapping value; + # data[2] = tex coord value + + _shader.set_mapping(material, mapping_data[0], mapping_data[1], mapping_data[2]) + def reload_tobj_settings(material, tex_type): """Relaods TOBJ settings on given texture type of material. From a2266f9d7b65e9012bfe4743b1995c872fb97f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Wed, 4 Dec 2024 00:49:27 +0100 Subject: [PATCH 12/15] aux5 fix, "baked" shader - Fixed "aux[5]" in "eut2.building.asafew.a.lvcol.day" shader. - Added support for "baked" shader (with flavors). - Changed "Specular Color" input in "add_env" node from required to optional (because "baked" shader don't use it) --- addon/io_scs_tools/__init__.py | 2 +- .../internals/shaders/eut2/__init__.py | 14 + .../internals/shaders/eut2/baked/__init__.py | 268 ++++++++++++++++++ .../internals/shaders/eut2/baked/add_env.py | 128 +++++++++ .../internals/shaders/eut2/baked/spec.py | 114 ++++++++ .../std_node_groups/spec_texture_calc_ng.py | 110 +++++++ .../shaders/eut2/std_passes/add_env.py | 9 +- addon/io_scs_tools/shader_presets.txt | 103 +++++-- 8 files changed, 722 insertions(+), 26 deletions(-) create mode 100644 addon/io_scs_tools/internals/shaders/eut2/baked/__init__.py create mode 100644 addon/io_scs_tools/internals/shaders/eut2/baked/add_env.py create mode 100644 addon/io_scs_tools/internals/shaders/eut2/baked/spec.py create mode 100644 addon/io_scs_tools/internals/shaders/eut2/std_node_groups/spec_texture_calc_ng.py diff --git a/addon/io_scs_tools/__init__.py b/addon/io_scs_tools/__init__.py index 984e7bf..c9c82ad 100644 --- a/addon/io_scs_tools/__init__.py +++ b/addon/io_scs_tools/__init__.py @@ -22,7 +22,7 @@ "name": "SCS Tools", "description": "Setup models, Import-Export SCS data format", "author": "Simon Lusenc (50keda), Milos Zajic (4museman), Michal (Michaleczeq)", - "version": (2, 4, "aeadde03", 1), + "version": (2, 4, "aeadde03", 2), "blender": (3, 2, 0), "location": "File > Import-Export", "doc_url": "http://modding.scssoft.com/wiki/Documentation/Tools/SCS_Blender_Tools", diff --git a/addon/io_scs_tools/internals/shaders/eut2/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/__init__.py index c3e99f2..eff9207 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/__init__.py @@ -244,6 +244,20 @@ def get_shader(effect): from io_scs_tools.internals.shaders.eut2.dif import Dif as Shader + elif effect.startswith("baked.spec"): + + if ".add.env" in effect: + + from io_scs_tools.internals.shaders.eut2.baked.add_env import BakedSpecAddEnv as Shader + + else: + + from io_scs_tools.internals.shaders.eut2.baked.spec import BakedSpec as Shader + + elif effect.startswith("baked"): + + from io_scs_tools.internals.shaders.eut2.baked import Baked as Shader + else: return None diff --git a/addon/io_scs_tools/internals/shaders/eut2/baked/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/baked/__init__.py new file mode 100644 index 0000000..e4664a5 --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/baked/__init__.py @@ -0,0 +1,268 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2015-2024: SCS Software + +from io_scs_tools.consts import Mesh as _MESH_consts +from io_scs_tools.internals.shaders.base import BaseShader +from io_scs_tools.internals.shaders.eut2.std_node_groups import compose_lighting_ng +from io_scs_tools.internals.shaders.eut2.std_node_groups import lighting_evaluator_ng +from io_scs_tools.internals.shaders.eut2.std_node_groups import vcolor_input_ng +from io_scs_tools.internals.shaders.flavors import nmap +from io_scs_tools.utils import convert as _convert_utils +from io_scs_tools.utils import material as _material_utils + + +class Baked(BaseShader): + GEOM_NODE = "Geometry" + UVMAP_NODE = "FirstUVs" + VCOL_GROUP_NODE = "VColorGroup" + BASE_TEX_NODE = "BaseTex" + VCOLOR_MULT_NODE = "VertexColorMultiplier" + VCOLOR_SCALE_NODE = "VertexColorScale" + LIGHTING_EVAL_NODE = "LightingEvaluator" + COMPOSE_LIGHTING_NODE = "ComposeLighting" + OUTPUT_NODE = "Output" + + @staticmethod + def get_name(): + """Get name of this shader file with full modules path.""" + return __name__ + + @staticmethod + def init(node_tree): + """Initialize node tree with links for this shader. + + :param node_tree: node tree on which this shader should be created + :type node_tree: bpy.types.NodeTree + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + # node creation + vcol_group_n = node_tree.nodes.new("ShaderNodeGroup") + vcol_group_n.name = Baked.VCOL_GROUP_NODE + vcol_group_n.label = Baked.VCOL_GROUP_NODE + vcol_group_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1650) + vcol_group_n.node_tree = vcolor_input_ng.get_node_group() + + uvmap_n = node_tree.nodes.new("ShaderNodeUVMap") + uvmap_n.name = Baked.UVMAP_NODE + uvmap_n.label = Baked.UVMAP_NODE + uvmap_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1500) + uvmap_n.uv_map = _MESH_consts.none_uv + + geometry_n = node_tree.nodes.new("ShaderNodeNewGeometry") + geometry_n.name = Baked.GEOM_NODE + geometry_n.label = Baked.GEOM_NODE + geometry_n.location = (start_pos_x - pos_x_shift, start_pos_y + 1350) + + vcol_scale_n = node_tree.nodes.new("ShaderNodeVectorMath") + vcol_scale_n.name = Baked.VCOLOR_SCALE_NODE + vcol_scale_n.label = Baked.VCOLOR_SCALE_NODE + vcol_scale_n.location = (start_pos_x + pos_x_shift * 3, start_pos_y + 1550) + vcol_scale_n.operation = "MULTIPLY" + vcol_scale_n.inputs[1].default_value = (2,) * 3 + + base_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + base_tex_n.name = Baked.BASE_TEX_NODE + base_tex_n.label = Baked.BASE_TEX_NODE + base_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 1500) + base_tex_n.width = 140 + + vcol_mult_n = node_tree.nodes.new("ShaderNodeVectorMath") + vcol_mult_n.name = Baked.VCOLOR_MULT_NODE + vcol_mult_n.label = Baked.VCOLOR_MULT_NODE + vcol_mult_n.location = (start_pos_x + pos_x_shift * 4, start_pos_y + 1500) + vcol_mult_n.operation = "MULTIPLY" + + lighting_eval_n = node_tree.nodes.new("ShaderNodeGroup") + lighting_eval_n.name = Baked.LIGHTING_EVAL_NODE + lighting_eval_n.label = Baked.LIGHTING_EVAL_NODE + lighting_eval_n.location = (start_pos_x + pos_x_shift * 7, start_pos_y + 1800) + lighting_eval_n.node_tree = lighting_evaluator_ng.get_node_group() + + compose_lighting_n = node_tree.nodes.new("ShaderNodeGroup") + compose_lighting_n.name = Baked.COMPOSE_LIGHTING_NODE + compose_lighting_n.label = Baked.COMPOSE_LIGHTING_NODE + compose_lighting_n.location = (start_pos_x + pos_x_shift * 8, start_pos_y + 2000) + compose_lighting_n.node_tree = compose_lighting_ng.get_node_group() + compose_lighting_n.inputs["Alpha"].default_value = 1.0 + + output_n = node_tree.nodes.new("ShaderNodeOutputMaterial") + output_n.name = Baked.OUTPUT_NODE + output_n.label = Baked.OUTPUT_NODE + output_n.location = (start_pos_x + pos_x_shift * 9, start_pos_y + 1800) + + # links creation + node_tree.links.new(base_tex_n.inputs['Vector'], uvmap_n.outputs['UV']) + node_tree.links.new(vcol_scale_n.inputs[0], vcol_group_n.outputs['Vertex Color']) + + node_tree.links.new(vcol_mult_n.inputs[0], vcol_scale_n.outputs[0]) + node_tree.links.new(vcol_mult_n.inputs[1], base_tex_n.outputs['Color']) + + node_tree.links.new(lighting_eval_n.inputs['Normal Vector'], geometry_n.outputs['Normal']) + node_tree.links.new(lighting_eval_n.inputs['Incoming Vector'], geometry_n.outputs['Incoming']) + + node_tree.links.new(compose_lighting_n.inputs['Diffuse Color'], vcol_mult_n.outputs[0]) + node_tree.links.new(compose_lighting_n.inputs['Specular Lighting'], lighting_eval_n.outputs['Specular Lighting']) + node_tree.links.new(compose_lighting_n.inputs['Diffuse Lighting'], lighting_eval_n.outputs['Diffuse Lighting']) + + node_tree.links.new(output_n.inputs['Surface'], compose_lighting_n.outputs['Shader']) + + @staticmethod + def finalize(node_tree, material): + """Finalize node tree and material settings. Should be called as last. + + :param node_tree: node tree on which this shader should be finalized + :type node_tree: bpy.types.NodeTree + :param material: material used for this shader + :type material: bpy.types.Material + """ + + material.use_backface_culling = True + material.blend_method = "OPAQUE" + + if material.blend_method == "OPAQUE" and node_tree.nodes[Baked.COMPOSE_LIGHTING_NODE].inputs['Alpha'].links: + node_tree.links.remove(node_tree.nodes[Baked.COMPOSE_LIGHTING_NODE].inputs['Alpha'].links[0]) + + @staticmethod + def set_shadow_bias(node_tree, value): + """Set shadow bias attirbute for this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param value: shador bias factor + :type value: float + """ + + pass # NOTE: shadow bias won't be visualized as game uses it's own implementation + + @staticmethod + def set_queue_bias(node_tree, value): + """Set queue bias attirbute for this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param value: queue bias index + :type value: int + """ + + pass # NOTE: shadow bias won't be visualized as game uses it's own implementation + + @staticmethod + def set_base_texture(node_tree, image): + """Set base texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assignet to base texture node + :type image: bpy.types.Image + """ + + node_tree.nodes[Baked.BASE_TEX_NODE].image = image + + @staticmethod + def set_base_texture_settings(node_tree, settings): + """Set base texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + _material_utils.set_texture_settings_to_node(node_tree.nodes[Baked.BASE_TEX_NODE], settings) + + @staticmethod + def set_base_uv(node_tree, uv_layer): + """Set UV layer to base texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for base texture + :type uv_layer: str + """ + + if uv_layer is None or uv_layer == "": + uv_layer = _MESH_consts.none_uv + + node_tree.nodes[Baked.UVMAP_NODE].uv_map = uv_layer + + @staticmethod + def set_nmap_flavor(node_tree, switch_on): + """Set normal map flavor to this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param switch_on: flag indication if normal map should be switched on or off + :type switch_on: bool + """ + + if switch_on: + + # find minimal y position for input nodes and position flavor beneath it + min_y = None + for node in node_tree.nodes: + if node.location.x <= 185 and (min_y is None or min_y > node.location.y): + min_y = node.location.y + + lighting_eval_n = node_tree.nodes[Baked.LIGHTING_EVAL_NODE] + geom_n = node_tree.nodes[Baked.GEOM_NODE] + location = (lighting_eval_n.location.x - 185, min_y - 400) + + nmap.init(node_tree, location, lighting_eval_n.inputs['Normal Vector'], geom_n.outputs['Normal']) + else: + nmap.delete(node_tree) + + @staticmethod + def set_nmap_texture(node_tree, image): + """Set normal map texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assignet to nmap texture node + :type image: bpy.types.Image + """ + + nmap.set_texture(node_tree, image) + + @staticmethod + def set_nmap_texture_settings(node_tree, settings): + """Set normal map texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + nmap.set_texture_settings(node_tree, settings) + + @staticmethod + def set_nmap_uv(node_tree, uv_layer): + """Set UV layer to normal map texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for nmap texture + :type uv_layer: str + """ + + nmap.set_uv(node_tree, uv_layer) diff --git a/addon/io_scs_tools/internals/shaders/eut2/baked/add_env.py b/addon/io_scs_tools/internals/shaders/eut2/baked/add_env.py new file mode 100644 index 0000000..1bba383 --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/baked/add_env.py @@ -0,0 +1,128 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2015-2024: SCS Software + +from io_scs_tools.internals.shaders.eut2.baked.spec import BakedSpec +from io_scs_tools.internals.shaders.eut2.std_node_groups import linear_to_srgb_ng +from io_scs_tools.internals.shaders.eut2.std_passes.add_env import StdAddEnv +from io_scs_tools.utils import material as _material_utils + +class BakedSpecAddEnv(BakedSpec, StdAddEnv): + MASK_TEX_NODE = "MaskTex" + MASK_LIN_TO_SRGB_NODE = "MaskLinearToSRGB" + + @staticmethod + def get_name(): + """Get name of this shader file with full modules path.""" + return __name__ + + @staticmethod + def init(node_tree): + BakedSpec.init(node_tree) + + @staticmethod + def init(node_tree): + """Initialize node tree with links for this shader. + + :param node_tree: node tree on which this shader should be created + :type node_tree: bpy.types.NodeTree + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + # init parent + BakedSpec.init(node_tree) + + + StdAddEnv.add(node_tree, + BakedSpec.GEOM_NODE, + None, + None, + node_tree.nodes[BakedSpec.LIGHTING_EVAL_NODE].outputs['Normal'], + node_tree.nodes[BakedSpec.COMPOSE_LIGHTING_NODE].inputs['Env Color']) + + uvmap_n = node_tree.nodes[BakedSpec.UVMAP_NODE] + + add_env_gn = node_tree.nodes[StdAddEnv.ADD_ENV_GROUP_NODE] + + # overrides + # set strength multiplier to 2 for better visualization in Blender + node_tree.nodes[StdAddEnv.ADD_ENV_GROUP_NODE].inputs['Strength Multiplier'].default_value = 2.0 + + + # node creation + mask_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + mask_tex_n.name = mask_tex_n.label = BakedSpecAddEnv.MASK_TEX_NODE + mask_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 2200) + mask_tex_n.width = 140 + + mask_lin_to_srgb_n = node_tree.nodes.new("ShaderNodeGroup") + mask_lin_to_srgb_n.name = mask_lin_to_srgb_n.label = BakedSpecAddEnv.MASK_LIN_TO_SRGB_NODE + mask_lin_to_srgb_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 2100) + mask_lin_to_srgb_n.node_tree = linear_to_srgb_ng.get_node_group() + + + # links creation + node_tree.links.new(uvmap_n.outputs['UV'], mask_tex_n.inputs['Vector']) + + node_tree.links.new(mask_tex_n.outputs['Color'], mask_lin_to_srgb_n.inputs['Value']) + + node_tree.links.new(mask_lin_to_srgb_n.outputs['Value'], add_env_gn.inputs['Env Factor Color']) + + + @staticmethod + def set_mask_texture(node_tree, image): + """Set mask texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assignet to mask texture node + :type image: bpy.types.Image + """ + + node_tree.nodes[BakedSpecAddEnv.MASK_TEX_NODE].image = image + + @staticmethod + def set_mask_texture_settings(node_tree, settings): + """Set mask texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + _material_utils.set_texture_settings_to_node(node_tree.nodes[BakedSpecAddEnv.MASK_TEX_NODE], settings) + + # due the fact mask colorspace is linear, we have to manually switch to sRGB and then convert values by node, for effect to work correctly + node_tree.nodes[BakedSpecAddEnv.MASK_TEX_NODE].image.colorspace_settings.name = 'sRGB' + + @staticmethod + def set_mask_uv(node_tree, uv_layer): + """Set UV layer to mask texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for nmap texture + :type uv_layer: str + """ + + pass # NOTE: as in "baked" shader textures use this same UVs as base_tex, we just ignore this \ No newline at end of file diff --git a/addon/io_scs_tools/internals/shaders/eut2/baked/spec.py b/addon/io_scs_tools/internals/shaders/eut2/baked/spec.py new file mode 100644 index 0000000..528e836 --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/baked/spec.py @@ -0,0 +1,114 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2015-2024: SCS Software + +from io_scs_tools.internals.shaders.eut2.baked import Baked +from io_scs_tools.internals.shaders.eut2.std_node_groups import spec_texture_calc_ng +from io_scs_tools.utils import material as _material_utils + +class BakedSpec(Baked): + OVER_TEX_NODE = "OverTex" + SPEC_TEX_CALC = "SpecTexCalc" + + @staticmethod + def get_name(): + """Get name of this shader file with full modules path.""" + return __name__ + + @staticmethod + def init(node_tree): + Baked.init(node_tree) + + @staticmethod + def init(node_tree): + """Initialize node tree with links for this shader. + + :param node_tree: node tree on which this shader should be created + :type node_tree: bpy.types.NodeTree + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + # init parent + Baked.init(node_tree) + + uvmap_n = node_tree.nodes[Baked.UVMAP_NODE] + lighting_eval_n = node_tree.nodes[Baked.LIGHTING_EVAL_NODE] + compose_lighting_n = node_tree.nodes[Baked.COMPOSE_LIGHTING_NODE] + + # node creation + over_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + over_tex_n.name = BakedSpec.OVER_TEX_NODE + over_tex_n.label = BakedSpec.OVER_TEX_NODE + over_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 1900) + over_tex_n.width = 140 + + over_tex_calc_ng = node_tree.nodes.new("ShaderNodeGroup") + over_tex_calc_ng.name = BakedSpec.SPEC_TEX_CALC + over_tex_calc_ng.label = BakedSpec.SPEC_TEX_CALC + over_tex_calc_ng.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 1900) + over_tex_calc_ng.node_tree = spec_texture_calc_ng.get_node_group() + + + # links creation + node_tree.links.new(uvmap_n.outputs['UV'], over_tex_n.inputs['Vector']) + + node_tree.links.new(over_tex_n.outputs['Color'], over_tex_calc_ng.inputs['Color']) + + node_tree.links.new(over_tex_calc_ng.outputs['Shininess'], lighting_eval_n.inputs['Shininess']) + node_tree.links.new(over_tex_calc_ng.outputs['Specular'], compose_lighting_n.inputs['Specular Color']) + + + @staticmethod + def set_over_texture(node_tree, image): + """Set over texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assignet to over texture node + :type image: bpy.types.Image + """ + + node_tree.nodes[BakedSpec.OVER_TEX_NODE].image = image + + @staticmethod + def set_over_texture_settings(node_tree, settings): + """Set over texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + _material_utils.set_texture_settings_to_node(node_tree.nodes[BakedSpec.OVER_TEX_NODE], settings) + + @staticmethod + def set_over_uv(node_tree, uv_layer): + """Set UV layer to over texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for nmap texture + :type uv_layer: str + """ + + pass # NOTE: as in "baked" shader textures use this same UVs as base_tex, we just ignore this \ No newline at end of file diff --git a/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/spec_texture_calc_ng.py b/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/spec_texture_calc_ng.py new file mode 100644 index 0000000..0869ec2 --- /dev/null +++ b/addon/io_scs_tools/internals/shaders/eut2/std_node_groups/spec_texture_calc_ng.py @@ -0,0 +1,110 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright (C) 2024: SCS Software + +import bpy +from io_scs_tools.consts import Material as _MAT_consts + +SPEC_TEXTURE_CALC_G = _MAT_consts.node_group_prefix + "SpecularTextureCalc" + +_COLOR_TO_RGB_NODE = "ColorToRGB" +_SHININESS_MULT = "ShininessMult" + + +def get_node_group(): + """Gets node group. + + :return: node group + :rtype: bpy.types.NodeGroup + """ + + if __group_needs_recreation__(): + __create_node_group__() + + return bpy.data.node_groups[SPEC_TEXTURE_CALC_G] + +def __group_needs_recreation__(): + """Tells if group needs recreation. + + :return: True group isn't up to date and has to be (re)created; False if group doesn't need to be (re)created + :rtype: bool + """ + # current checks: + # 1. group existence in blender data block + return SPEC_TEXTURE_CALC_G not in bpy.data.node_groups + +def __create_node_group__(): + """Creates group. + + Inputs: Color + Outputs: Shininess, Specular + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + if SPEC_TEXTURE_CALC_G not in bpy.data.node_groups: # creation + + spec_txt_calc_n = bpy.data.node_groups.new(type="ShaderNodeTree", name=SPEC_TEXTURE_CALC_G) + + else: # recreation + + spec_txt_calc_n = bpy.data.node_groups[SPEC_TEXTURE_CALC_G] + + # delete all inputs and outputs + spec_txt_calc_n.inputs.clear() + spec_txt_calc_n.outputs.clear() + + # delete all old nodes and links as they will be recreated now with actual version + spec_txt_calc_n.nodes.clear() + + # inputs defining + spec_txt_calc_n.inputs.new("NodeSocketColor", "Color") + + # outputs defining + spec_txt_calc_n.outputs.new("NodeSocketVector", "Shininess") + spec_txt_calc_n.outputs.new("NodeSocketVector", "Specular") + + # node creation + input_n = spec_txt_calc_n.nodes.new("NodeGroupInput") + input_n.location = (start_pos_x, start_pos_y) + + output_n = spec_txt_calc_n.nodes.new("NodeGroupOutput") + output_n.location = (start_pos_x + pos_x_shift * 3, start_pos_y) + + color_to_rgb_n = spec_txt_calc_n.nodes.new("ShaderNodeSeparateColor") + color_to_rgb_n.name = color_to_rgb_n.label = _COLOR_TO_RGB_NODE + color_to_rgb_n.location = (start_pos_x + pos_x_shift * 1, start_pos_y) + color_to_rgb_n.mode = "RGB" + + shininess_mult_n = spec_txt_calc_n.nodes.new("ShaderNodeVectorMath") + shininess_mult_n.name = shininess_mult_n.label = _SHININESS_MULT + shininess_mult_n.location = (start_pos_x + pos_x_shift * 2, start_pos_y + 100) + shininess_mult_n.operation = "MULTIPLY" + shininess_mult_n.inputs[1].default_value = (255,) * 3 + + # links + spec_txt_calc_n.links.new(input_n.outputs['Color'], color_to_rgb_n.inputs['Color']) + + spec_txt_calc_n.links.new(color_to_rgb_n.outputs['Red'], shininess_mult_n.inputs[0]) + spec_txt_calc_n.links.new(color_to_rgb_n.outputs['Green'], output_n.inputs['Specular']) + + spec_txt_calc_n.links.new(shininess_mult_n.outputs['Vector'], output_n.inputs['Shininess']) \ No newline at end of file diff --git a/addon/io_scs_tools/internals/shaders/eut2/std_passes/add_env.py b/addon/io_scs_tools/internals/shaders/eut2/std_passes/add_env.py index 3834702..26bf272 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/std_passes/add_env.py +++ b/addon/io_scs_tools/internals/shaders/eut2/std_passes/add_env.py @@ -42,8 +42,8 @@ def add(node_tree, geom_n_name, spec_col_socket, alpha_socket, final_normal_sock :type node_tree: bpy.types.NodeTree :param geom_n_name: name of geometry node from which normal and view vectors will be taken :type geom_n_name: str - :param spec_col_socket: specular color node socket from which specular color will be taken - :type spec_col_socket: bpy.type.NodeSocket + :param spec_col_socket: specular color node socket from which specular color will be taken (if None it won't be used) + :type spec_col_socket: bpy.type.NodeSocket | None :param alpha_socket: socket from which alpha will be taken (if None it won't be used) :type alpha_socket: bpy.type.NodeSocket | None :param final_normal_socket: socket of final normal, if not provided geometry normal is used @@ -105,7 +105,10 @@ def add(node_tree, geom_n_name, spec_col_socket, alpha_socket, final_normal_sock node_tree.links.new(add_env_n.inputs['Env Factor Color'], env_col_n.outputs['Color']) node_tree.links.new(add_env_n.inputs['Reflection Texture Color'], refl_tex_n.outputs['Color']) - node_tree.links.new(add_env_n.inputs['Specular Color'], spec_col_socket) + # fix for 'baked' shader that don't use specular + if spec_col_socket is not None: + node_tree.links.new(add_env_n.inputs['Specular Color'], spec_col_socket) + if add_env_n and alpha_socket: node_tree.links.new(add_env_n.inputs['Base Texture Alpha'], alpha_socket) diff --git a/addon/io_scs_tools/shader_presets.txt b/addon/io_scs_tools/shader_presets.txt index b134225..5ed3123 100644 --- a/addon/io_scs_tools/shader_presets.txt +++ b/addon/io_scs_tools/shader_presets.txt @@ -190,10 +190,10 @@ Shader { Value: ( 0.0 ) } Attribute { - Format: FLOAT + Format: FLOAT2 Tag: "aux[5]" - FriendlyTag: "Luminance Boost" - Value: ( 0.0 ) + FriendlyTag: "Luminance Output (Day, Night) (nit)" + Value: ( 0.0 0.0 ) } Texture { Tag: "texture[X]:texture_base" @@ -2070,6 +2070,66 @@ Shader { TexCoord: ( 1 ) } } +Shader { + PresetName: "baked" + Effect: "eut2.baked" + # Shader use also NIGHT flavor, but it's not used in shader (only "day") - probably game changing it depending on day time, like in other shaders with day/night in name + Flavors: ( "NMAP_TS" "SHADOW" "DAY" ) + Flags: 0 + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } +} +Shader { + PresetName: "baked.spec" + Effect: "eut2.baked.spec" + # Shader use also NIGHT flavor, but it's not used in shader (only "day") - probably game changing it depending on day time, like in other shaders with day/night in name + Flavors: ( "NMAP_TS" "SHADOW" "DAY" ) + Flags: 0 + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_over" + Value: "" + TexCoord: ( 0 ) + } +} +Shader { + PresetName: "baked.spec.add.env" + Effect: "eut2.baked.spec.add.env" + # Shader use also NIGHT flavor, but it's not used in shader (only "day") - probably game changing it depending on day time, like in other shaders with day/night in name + Flavors: ( "NMAP_TS" "PAINT" "SHADOW" "DAY" ) + Flags: 0 + Attribute { + Format: FLOAT2 + Tag: "fresnel" + Value: ( 0.2 0.9 ) + } + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_over" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_mask" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_reflection" + Value: "/material/environment/vehicle_reflection" + TexCoord: ( -1 ) + } } Flavor { Type: "AIRBRUSH" @@ -2188,25 +2248,6 @@ Flavor { TexCoord: ( -1 ) } } -Flavor { - Type: "ENVMAP_NOFAC" - Name: "add.env" - Attribute { - Format: FLOAT2 - Tag: "fresnel" - Value: ( 0.2 0.9 ) - } - Texture { - Tag: "texture[X]:texture_mask" - Value: "" - TexCoord: ( 0 ) - } - Texture { - Tag: "texture[X]:texture_reflection" - Value: "/material/environment/vehicle_reflection" - TexCoord: ( -1 ) - } -} Flavor { Type: "FADESHEET" Name: "fadesheet" @@ -2477,3 +2518,21 @@ Flavor { Value: ( 8.0 8.0 0.0 0.0 ) } } +Flavor { + Type: "DAY" + Name: "day" + Texture { + Tag: "texture[X]:texture_lightmap" + Value: "" + TexCoord: ( 0 ) + } +} +Flavor { + Type: "NIGHT" + Name: "night" + Texture { + Tag: "texture[X]:texture_lightmap" + Value: "" + TexCoord: ( 0 ) + } +} From e98dece922dd6d20bae44b9a2ad71e2944af9b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Wed, 4 Dec 2024 04:25:22 +0100 Subject: [PATCH 13/15] day/night replace, "building" fixes, visibility tools tweaks - Fixed problem with imported - Added parts starting with "_col" to collisions - Added automatic replace for outdated "window.day/night" shaders to "window.lit". - Added missing flavors in some "building" shaders - Added support for "building.add.env.lvcol.day" --- addon/io_scs_tools/imp/pit.py | 7 ++ .../internals/shaders/eut2/__init__.py | 16 ++-- addon/io_scs_tools/shader_presets.txt | 73 +++++++++++++++---- addon/io_scs_tools/utils/material.py | 2 +- 4 files changed, 76 insertions(+), 22 deletions(-) diff --git a/addon/io_scs_tools/imp/pit.py b/addon/io_scs_tools/imp/pit.py index b72cacf..6139217 100644 --- a/addon/io_scs_tools/imp/pit.py +++ b/addon/io_scs_tools/imp/pit.py @@ -189,6 +189,13 @@ def _get_look(section): mat_effect = mat_effect.replace(".night", ".day") lprint("W Night version of building shader detected in material %r, switching it to day!", (mat_alias,)) + # If day/night version of "window" shader is detected, switch it to "lit". + if mat_effect.startswith("eut2.window") and mat_effect.endswith((".day", ".night")): + + mat_effect = mat_effect.replace(".day", ".lit").replace(".night", ".lit") + + lprint("W Outdated Day or Night version of window shader detected in material %r, switching it to lit!", (mat_alias,)) + look_mat_settings[mat_alias] = (mat_effect, mat_flags, attributes, textures, sec) return look_name, look_mat_settings diff --git a/addon/io_scs_tools/internals/shaders/eut2/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/__init__.py index eff9207..cd48395 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/__init__.py @@ -168,15 +168,21 @@ def get_shader(effect): from io_scs_tools.internals.shaders.eut2.dif_spec_add_env.nofresnel import DifSpecAddEnvNoFresnel as Shader - elif effect.startswith("building.add.env.day"): + # Changed because of "lvcol.day" variant (all "buildings.add.env" use this same shader) + # + # elif effect.startswith("building.add.env.day"): + elif effect.startswith("building.add.env"): from io_scs_tools.internals.shaders.eut2.building.add_env_day import BuildingAddEnvDay as Shader - elif effect.startswith("building.lvcol.day"): - - from io_scs_tools.internals.shaders.eut2.building.lvcol_day import BuildingLvcolDay as Shader + # Changed because of "asafew.(...).day" variant (all non add.env "buildings" use this same shader) + # + # elif effect.startswith("building.lvcol.day"): + # + # from io_scs_tools.internals.shaders.eut2.building.lvcol_day import BuildingLvcolDay as Shader - elif effect.startswith("building.day"): + # elif effect.startswith("building.day"): + elif effect.startswith("building"): from io_scs_tools.internals.shaders.eut2.building.day import BuildingDay as Shader diff --git a/addon/io_scs_tools/shader_presets.txt b/addon/io_scs_tools/shader_presets.txt index 5ed3123..49faa72 100644 --- a/addon/io_scs_tools/shader_presets.txt +++ b/addon/io_scs_tools/shader_presets.txt @@ -9,6 +9,58 @@ Header { Shader { PresetName: "building.add.env.day" Effect: "eut2.building.add.env.day" + Flavors: ( "SHADOW" ) + Flags: 0 + Attribute { + Format: FLOAT3 + Tag: "diffuse" + Value: ( 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT3 + Tag: "specular" + Value: ( 0.9 0.9 0.9 ) + } + Attribute { + Format: FLOAT + Tag: "shininess" + Value: ( 60.0 ) + } + Attribute { + Format: FLOAT + Tag: "add_ambient" + Value: ( 0.0 ) + } + Attribute { + Format: FLOAT3 + Tag: "env_factor" + Value: ( 0.9 0.9 0.9 ) + } + Attribute { + Format: FLOAT2 + Tag: "fresnel" + Value: ( 0.2 0.9 ) + } + Attribute { + Format: FLOAT2 + Tag: "aux[5]" + FriendlyTag: "Luminance Output (Day, Night) (nit)" + Value: ( 0.0 0.0 ) + } + Texture { + Tag: "texture[X]:texture_base" + Value: "" + TexCoord: ( 0 ) + } + Texture { + Tag: "texture[X]:texture_reflection" + Value: "/material/environment/building_reflection/building_ref" + TexCoord: ( -1 ) + } +} +Shader { + PresetName: "building.add.env.lvcol.day" + Effect: "eut2.building.add.env.lvcol.day" Flags: 0 Attribute { Format: FLOAT3 @@ -60,6 +112,7 @@ Shader { Shader { PresetName: "building.day" Effect: "eut2.building.day" + Flavors: ( "SHADOW" ) Flags: 0 Attribute { Format: FLOAT3 @@ -2073,8 +2126,7 @@ Shader { Shader { PresetName: "baked" Effect: "eut2.baked" - # Shader use also NIGHT flavor, but it's not used in shader (only "day") - probably game changing it depending on day time, like in other shaders with day/night in name - Flavors: ( "NMAP_TS" "SHADOW" "DAY" ) + Flavors: ( "NMAP_TS" "SHADOW" "DAY_TEX" ) Flags: 0 Texture { Tag: "texture[X]:texture_base" @@ -2085,8 +2137,7 @@ Shader { Shader { PresetName: "baked.spec" Effect: "eut2.baked.spec" - # Shader use also NIGHT flavor, but it's not used in shader (only "day") - probably game changing it depending on day time, like in other shaders with day/night in name - Flavors: ( "NMAP_TS" "SHADOW" "DAY" ) + Flavors: ( "NMAP_TS" "SHADOW" "DAY_TEX" ) Flags: 0 Texture { Tag: "texture[X]:texture_base" @@ -2102,8 +2153,7 @@ Shader { Shader { PresetName: "baked.spec.add.env" Effect: "eut2.baked.spec.add.env" - # Shader use also NIGHT flavor, but it's not used in shader (only "day") - probably game changing it depending on day time, like in other shaders with day/night in name - Flavors: ( "NMAP_TS" "PAINT" "SHADOW" "DAY" ) + Flavors: ( "NMAP_TS" "PAINT" "SHADOW" "DAY_TEX" ) Flags: 0 Attribute { Format: FLOAT2 @@ -2519,7 +2569,7 @@ Flavor { } } Flavor { - Type: "DAY" + Type: "DAY_TEX" Name: "day" Texture { Tag: "texture[X]:texture_lightmap" @@ -2527,12 +2577,3 @@ Flavor { TexCoord: ( 0 ) } } -Flavor { - Type: "NIGHT" - Name: "night" - Texture { - Tag: "texture[X]:texture_lightmap" - Value: "" - TexCoord: ( 0 ) - } -} diff --git a/addon/io_scs_tools/utils/material.py b/addon/io_scs_tools/utils/material.py index 213a213..7b871e6 100644 --- a/addon/io_scs_tools/utils/material.py +++ b/addon/io_scs_tools/utils/material.py @@ -393,7 +393,7 @@ def get_material_info(obj): if slot.material: - if obj.scs_props.scs_part.startswith("coll"): + if obj.scs_props.scs_part.startswith(("coll", "_col")): has_static_collision = True effect_name = slot.material.scs_props.mat_effect_name.lower() From 42d58658cbe0652cc42343473d5cd66bf2e36422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Sat, 4 Jan 2025 06:26:22 +0100 Subject: [PATCH 14/15] new effects (.bin) + "baked" fixes * Added new effects in supported_effects.bin. * Fixed "paint" flavor in "baked" shader (added mask_1 and preview of "Base Paint Color"). * Renamed some stuff in "interior" shader files. * Renamed some new flavors in "shader_presets.txt" to better reflect them. * Sorted flavor entries in "shader_presets.txt" alphabetically for better orientation. --- .../internals/shaders/eut2/baked/add_env.py | 124 +++++++++++- .../shaders/eut2/interior/__init__.py | 6 +- addon/io_scs_tools/shader_presets.txt | 191 +++++++++--------- addon/io_scs_tools/supported_effects.bin | Bin 192085 -> 194096 bytes 4 files changed, 224 insertions(+), 97 deletions(-) diff --git a/addon/io_scs_tools/internals/shaders/eut2/baked/add_env.py b/addon/io_scs_tools/internals/shaders/eut2/baked/add_env.py index 1bba383..f52db34 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/baked/add_env.py +++ b/addon/io_scs_tools/internals/shaders/eut2/baked/add_env.py @@ -19,14 +19,20 @@ # Copyright (C) 2015-2024: SCS Software from io_scs_tools.internals.shaders.eut2.baked.spec import BakedSpec +from io_scs_tools.internals.shaders.eut2.parameters import get_fresnel_truckpaint from io_scs_tools.internals.shaders.eut2.std_node_groups import linear_to_srgb_ng from io_scs_tools.internals.shaders.eut2.std_passes.add_env import StdAddEnv +from io_scs_tools.utils import convert as _convert_utils from io_scs_tools.utils import material as _material_utils +from io_scs_tools.utils import get_scs_globals as _get_scs_globals class BakedSpecAddEnv(BakedSpec, StdAddEnv): MASK_TEX_NODE = "MaskTex" + MASK1_TEX_NODE = "Mask1Tex" MASK_LIN_TO_SRGB_NODE = "MaskLinearToSRGB" + BASE_PAINT_MULT_NODE = "BasePaintMult" + @staticmethod def get_name(): """Get name of this shader file with full modules path.""" @@ -88,6 +94,46 @@ def init(node_tree): node_tree.links.new(mask_lin_to_srgb_n.outputs['Value'], add_env_gn.inputs['Env Factor Color']) + @staticmethod + def init_paint(node_tree): + """Initialize extended node tree for colormask or airbrush flavors with links for this shader. + + :param node_tree: node tree on which this shader should be created + :type node_tree: bpy.types.NodeTree + """ + + start_pos_x = 0 + start_pos_y = 0 + + pos_x_shift = 185 + + # make sure to skip execution if node exists + if BakedSpecAddEnv.MASK1_TEX_NODE not in node_tree.nodes: + + uvmap_n = node_tree.nodes[BakedSpec.UVMAP_NODE] + vcol_mult_n = node_tree.nodes[BakedSpec.VCOLOR_MULT_NODE] + compose_lighting_n = node_tree.nodes[BakedSpec.COMPOSE_LIGHTING_NODE] + + # node creation + mask1_tex_n = node_tree.nodes.new("ShaderNodeTexImage") + mask1_tex_n.name = mask1_tex_n.label = BakedSpecAddEnv.MASK1_TEX_NODE + mask1_tex_n.location = (start_pos_x + pos_x_shift, start_pos_y + 1150) + mask1_tex_n.width = 140 + + base_paint_mult_n = node_tree.nodes.new("ShaderNodeMixRGB") + base_paint_mult_n.name = base_paint_mult_n.label = BakedSpecAddEnv.BASE_PAINT_MULT_NODE + base_paint_mult_n.location = (start_pos_x + pos_x_shift * 5, start_pos_y + 1500) + base_paint_mult_n.blend_type = "MULTIPLY" + base_paint_mult_n.inputs['Fac'].default_value = 1 + base_paint_mult_n.inputs['Color2'].default_value = _convert_utils.to_node_color(_get_scs_globals().base_paint_color) + + # links creation + node_tree.links.new(uvmap_n.outputs['UV'], mask1_tex_n.inputs['Vector']) + node_tree.links.new(mask1_tex_n.outputs['Color'], base_paint_mult_n.inputs['Fac']) + node_tree.links.new(vcol_mult_n.outputs['Vector'], base_paint_mult_n.inputs['Color1']) + node_tree.links.new(base_paint_mult_n.outputs['Color'], compose_lighting_n.inputs['Diffuse Color']) + + @staticmethod def set_mask_texture(node_tree, image): @@ -112,7 +158,7 @@ def set_mask_texture_settings(node_tree, settings): """ _material_utils.set_texture_settings_to_node(node_tree.nodes[BakedSpecAddEnv.MASK_TEX_NODE], settings) - # due the fact mask colorspace is linear, we have to manually switch to sRGB and then convert values by node, for effect to work correctly + # due the fact mask colorspace is linear, we have to manually switch to sRGB and then convert values by node, for effect to work correctly (blender don't like SCS format of linear DDS textures). node_tree.nodes[BakedSpecAddEnv.MASK_TEX_NODE].image.colorspace_settings.name = 'sRGB' @staticmethod @@ -121,8 +167,80 @@ def set_mask_uv(node_tree, uv_layer): :param node_tree: node tree of current shader :type node_tree: bpy.types.NodeTree - :param uv_layer: uv layer string used for nmap texture + :param uv_layer: uv layer string used for mask texture + :type uv_layer: str + """ + + pass # NOTE: as in "baked" shader textures use this same UVs as base_tex, we just ignore this + + @staticmethod + def set_mask_1_texture(node_tree, image): + """Set mask 1 texture to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param image: texture image which should be assigned to mask 1 texture node + :type image: bpy.types.Image + """ + + node_tree.nodes[BakedSpecAddEnv.MASK1_TEX_NODE].image = image + + @staticmethod + def set_mask_1_texture_settings(node_tree, settings): + """Set mask 1 texture settings to shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param settings: binary string of TOBJ settings gotten from tobj import + :type settings: str + """ + _material_utils.set_texture_settings_to_node(node_tree.nodes[BakedSpecAddEnv.MASK1_TEX_NODE], settings) + + # due the fact mask colorspace is linear, we have to manually switch to sRGB and then convert values by node, for effect to work correctly (blender don't like SCS format of linear DDS textures). + node_tree.nodes[BakedSpecAddEnv.MASK1_TEX_NODE].image.colorspace_settings.name = 'sRGB' + + @staticmethod + def set_mask_1_uv(node_tree, uv_layer): + """Set UV layer to mask 1 texture in shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param uv_layer: uv layer string used for mask 1 texture :type uv_layer: str """ - pass # NOTE: as in "baked" shader textures use this same UVs as base_tex, we just ignore this \ No newline at end of file + pass # NOTE: as in "baked" shader textures use this same UVs as base_tex, we just ignore this + + @staticmethod + def set_paint_flavor(node_tree, switch_on): + """Set paint flavor to this shader. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param switch_on: flag indication if flavor should be switched on or off + :type switch_on: bool + """ + + if switch_on: + BakedSpecAddEnv.init_paint(node_tree) + + @staticmethod + def set_fresnel(node_tree, bias_scale): + """Set fresnel bias and scale value to shader. + More tests are needed to determine if this is correct for paint flavor in baked shader, because without that, model is too glossy. + + :param node_tree: node tree of current shader + :type node_tree: bpy.types.NodeTree + :param bias_scale: bias and scale factors as tuple: (bias, scale) + :type bias_scale: (float, float) + """ + # skip ecxecution if node for "paint" flavor does not exist + if BakedSpecAddEnv.MASK1_TEX_NODE not in node_tree.nodes: + return + + bias_scale_truckpaint = get_fresnel_truckpaint(bias_scale[0], bias_scale[1]) + StdAddEnv.set_fresnel(node_tree, bias_scale_truckpaint) + + node_tree.nodes[StdAddEnv.ADD_ENV_GROUP_NODE].inputs['Fresnel Type'].default_value = 1 + + \ No newline at end of file diff --git a/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py b/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py index 6e6430d..c559882 100644 --- a/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py +++ b/addon/io_scs_tools/internals/shaders/eut2/interior/__init__.py @@ -34,7 +34,7 @@ class InteriorLit(DifSpecAddEnv): NMAP_TEX_NODE = "NmapTex" ENV_SEP_XYZ_NODE = "EnvSepXYZ" ENV_CHECK_XYZ_NODE = "EnvCheckXYZ" - PERTURBATION_UVMAP_NODE = "PerturbationUVMap" + PERT_UVMAP_NODE = "PerturbationUVMap" @staticmethod @@ -77,7 +77,7 @@ def init(node_tree): # node creation # - column -1 - pert_uv_n = node_tree.nodes.new("ShaderNodeUVMap") - pert_uv_n.name = pert_uv_n.label = InteriorLit.PERTURBATION_UVMAP_NODE + pert_uv_n.name = pert_uv_n.label = InteriorLit.PERT_UVMAP_NODE pert_uv_n.location = (start_pos_x - pos_x_shift, start_pos_y + 950) pert_uv_n.uv_map = _MESH_consts.none_uv @@ -276,4 +276,4 @@ def set_perturbation_mapping(node_tree, uv_layer): if uv_layer is None or uv_layer == "": uv_layer = _MESH_consts.none_uv - node_tree.nodes[InteriorLit.PERTURBATION_UVMAP_NODE].uv_map = uv_layer + node_tree.nodes[InteriorLit.PERT_UVMAP_NODE].uv_map = uv_layer diff --git a/addon/io_scs_tools/shader_presets.txt b/addon/io_scs_tools/shader_presets.txt index 49faa72..dae91b2 100644 --- a/addon/io_scs_tools/shader_presets.txt +++ b/addon/io_scs_tools/shader_presets.txt @@ -1587,7 +1587,7 @@ Shader { Shader { PresetName: "shadowonly" Effect: "eut2.shadowonly" - Flavors: ( "NOCULL" "SHDW_ALPHA" ) + Flavors: ( "NOCULL" "ALPHA_MASK" ) Flags: 0 Attribute { Format: FLOAT @@ -1682,7 +1682,7 @@ Shader { Shader { PresetName: "truckpaint" Effect: "eut2.truckpaint" - Flavors: ( "NMAP_TS|NMAP_TS_UV|NMAP_TS_16|NMAP_TS_UV_16" "SHADOW" "COLORMASK|AIRBRUSH" "FLIPFLAKE" "ALTUV" ) + Flavors: ( "NMAP_TS|NMAP_TS_UV|NMAP_TS_16|NMAP_TS_UV_16" "SHADOW" "COLORMASK|AIRBRUSH" "FLIPFLAKE" "ALTUV" "ASAFEWA" ) Flags: 0 Attribute { Format: FLOAT3 @@ -2126,7 +2126,7 @@ Shader { Shader { PresetName: "baked" Effect: "eut2.baked" - Flavors: ( "NMAP_TS" "SHADOW" "DAY_TEX" ) + Flavors: ( "NMAP_TS" "SHADOW" "DAY_MASK" ) Flags: 0 Texture { Tag: "texture[X]:texture_base" @@ -2137,7 +2137,7 @@ Shader { Shader { PresetName: "baked.spec" Effect: "eut2.baked.spec" - Flavors: ( "NMAP_TS" "SHADOW" "DAY_TEX" ) + Flavors: ( "NMAP_TS" "SHADOW" "DAY_MASK" ) Flags: 0 Texture { Tag: "texture[X]:texture_base" @@ -2153,7 +2153,7 @@ Shader { Shader { PresetName: "baked.spec.add.env" Effect: "eut2.baked.spec.add.env" - Flavors: ( "NMAP_TS" "PAINT" "SHADOW" "DAY_TEX" ) + Flavors: ( "NMAP_TS" "PAINT_MASK" "SHADOW" "DAY_MASK" ) Flags: 0 Attribute { Format: FLOAT2 @@ -2201,7 +2201,7 @@ Flavor { Name: "a" } Flavor { - Type: "SHDW_ALPHA" + Type: "ALPHA_MASK" Name: "a" Texture { Tag: "texture[X]:texture_base" @@ -2213,6 +2213,42 @@ Flavor { Type: "ALTUV" Name: "altuv" } +Flavor { + Type: "ANIM" + Name: "anim" + Attribute { + Format: FLOAT4 + Tag: "aux[0]" + FriendlyTag: "Sheet frame size (R, G)" + Value: ( 1.0 1.0 1.0 1.0 ) + } + Attribute { + Format: FLOAT4 + Tag: "aux[1]" + FriendlyTag: "Sheet frame size (B, A)" + Value: ( 1.0 1.0 1.0 1.0 ) + } + Texture { + Tag: "texture[X]:texture_mask" + Value: "" + TexCoord: ( 1 ) + } + Texture { + Tag: "texture[X]:texture_mask_1" + Value: "" + TexCoord: ( 1 ) + } + Texture { + Tag: "texture[X]:texture_mask_2" + Value: "" + TexCoord: ( 1 ) + } + Texture { + Tag: "texture[X]:texture_mask_3" + Value: "" + TexCoord: ( 1 ) + } +} Flavor { Type: "ASAFEW" Name: "asafew" @@ -2270,6 +2306,15 @@ Flavor { TexCoord: ( 1 2 ) } } +Flavor { + Type: "DAY_MASK" + Name: "day" + Texture { + Tag: "texture[X]:texture_lightmap" + Value: "" + TexCoord: ( 0 ) + } +} Flavor { Type: "DEPTH" Name: "decal" @@ -2344,42 +2389,6 @@ Flavor { Hide: "True" } } -Flavor { - Type: "ANIM" - Name: "anim" - Attribute { - Format: FLOAT4 - Tag: "aux[0]" - FriendlyTag: "Sheet frame size (R, G)" - Value: ( 1.0 1.0 1.0 1.0 ) - } - Attribute { - Format: FLOAT4 - Tag: "aux[1]" - FriendlyTag: "Sheet frame size (B, A)" - Value: ( 1.0 1.0 1.0 1.0 ) - } - Texture { - Tag: "texture[X]:texture_mask" - Value: "" - TexCoord: ( 1 ) - } - Texture { - Tag: "texture[X]:texture_mask_1" - Value: "" - TexCoord: ( 1 ) - } - Texture { - Tag: "texture[X]:texture_mask_2" - Value: "" - TexCoord: ( 1 ) - } - Texture { - Tag: "texture[X]:texture_mask_3" - Value: "" - TexCoord: ( 1 ) - } -} Flavor { Type: "FLAT" Name: "flat" @@ -2393,17 +2402,22 @@ Flavor { Name: "lvcol" } Flavor { - Type: "NMAP_TS" + Type: "NMAP_DETAIL" Name: "tsnmap" Texture { Tag: "texture[X]:texture_nmap" Value: "" TexCoord: ( 0 ) } + Texture { + Tag: "texture[X]:texture_nmap_detail" + Value: "" + TexCoord: ( 0 ) + } } Flavor { - Type: "NMAP_TS_16" - Name: "tsnmap16" + Type: "NMAP_TS" + Name: "tsnmap" Texture { Tag: "texture[X]:texture_nmap" Value: "" @@ -2411,31 +2425,35 @@ Flavor { } } Flavor { - Type: "NMAP_DETAIL" - Name: "tsnmap" + Type: "NMAP_TS_16" + Name: "tsnmap16" Texture { Tag: "texture[X]:texture_nmap" Value: "" TexCoord: ( 0 ) } +} +Flavor { + Type: "NMAP_TS_CALC" + Name: "tsnmapcalc" Texture { - Tag: "texture[X]:texture_nmap_detail" + Tag: "texture[X]:texture_nmap" Value: "" TexCoord: ( 0 ) } } Flavor { - Type: "NMAP_UV_DETAIL" - Name: "tsnmapuv" + Type: "NMAP_TS_CALC_OVER" + Name: "tsnmapcalc" Texture { Tag: "texture[X]:texture_nmap" Value: "" - TexCoord: ( 6 ) + TexCoord: ( 0 ) } Texture { - Tag: "texture[X]:texture_nmap_detail" + Tag: "texture[X]:texture_nmap_over" Value: "" - TexCoord: ( 6 ) + TexCoord: ( 1 ) } } Flavor { @@ -2457,31 +2475,47 @@ Flavor { } } Flavor { - Type: "NMAP_TS_CALC" - Name: "tsnmapcalc" + Type: "NMAP_UV_DETAIL" + Name: "tsnmapuv" Texture { Tag: "texture[X]:texture_nmap" Value: "" - TexCoord: ( 0 ) + TexCoord: ( 6 ) } -} -Flavor { - Type: "NMAP_TS_CALC_OVER" - Name: "tsnmapcalc" Texture { - Tag: "texture[X]:texture_nmap" + Tag: "texture[X]:texture_nmap_detail" Value: "" - TexCoord: ( 0 ) + TexCoord: ( 6 ) } +} +Flavor { + Type: "NOCULL" + Name: "nocull" +} +Flavor { + Type: "PAINT" + Name: "paint" +} +Flavor { + Type: "PAINT_MASK" + Name: "paint" Texture { - Tag: "texture[X]:texture_nmap_over" + Tag: "texture[X]:texture_mask_1" Value: "" - TexCoord: ( 1 ) + TexCoord: ( 0 ) } } Flavor { - Type: "NOCULL" - Name: "nocull" + Type: "RETROREFLECTIVE_DECAL" + Name: "decal.over" +} +Flavor { + Type: "RETROREFLECTIVE_DIM_ALLDIR" + Name: "dim.alldir" +} +Flavor { + Type: "RETROREFLECTIVE_PIKO_ALLDIR" + Name: "piko.alldir" } Flavor { Type: "SHADOW" @@ -2532,22 +2566,6 @@ Flavor { Hide: "False" } } -Flavor { - Type: "PAINT" - Name: "paint" -} -Flavor { - Type: "RETROREFLECTIVE_DECAL" - Name: "decal.over" -} -Flavor { - Type: "RETROREFLECTIVE_DIM_ALLDIR" - Name: "dim.alldir" -} -Flavor { - Type: "RETROREFLECTIVE_PIKO_ALLDIR" - Name: "piko.alldir" -} Flavor { Type: "TEXGEN0" Name: "tg0" @@ -2568,12 +2586,3 @@ Flavor { Value: ( 8.0 8.0 0.0 0.0 ) } } -Flavor { - Type: "DAY_TEX" - Name: "day" - Texture { - Tag: "texture[X]:texture_lightmap" - Value: "" - TexCoord: ( 0 ) - } -} diff --git a/addon/io_scs_tools/supported_effects.bin b/addon/io_scs_tools/supported_effects.bin index f6cc9a7f7dde2cd277916909520484d0126fc1a0..b084828889c4f961d4a191d0940eac41e399ac0e 100644 GIT binary patch literal 194096 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 UH%SQ7a7aCrcp#!6*dL$$A2WKHHUIzs From f76e333c336500547aa78497afb6c8cb566b8076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 6 Jan 2025 01:19:47 +0100 Subject: [PATCH 15/15] bgl replaces * Some bgl module replaces --- addon/io_scs_tools/__init__.py | 2 +- .../internals/open_gl/primitive.py | 25 +++++++++---------- addon/io_scs_tools/operators/wm.py | 13 ++++++---- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/addon/io_scs_tools/__init__.py b/addon/io_scs_tools/__init__.py index c9c82ad..f564d87 100644 --- a/addon/io_scs_tools/__init__.py +++ b/addon/io_scs_tools/__init__.py @@ -22,7 +22,7 @@ "name": "SCS Tools", "description": "Setup models, Import-Export SCS data format", "author": "Simon Lusenc (50keda), Milos Zajic (4museman), Michal (Michaleczeq)", - "version": (2, 4, "aeadde03", 2), + "version": (2, 4, "aeadde03", 3), "blender": (3, 2, 0), "location": "File > Import-Export", "doc_url": "http://modding.scssoft.com/wiki/Documentation/Tools/SCS_Blender_Tools", diff --git a/addon/io_scs_tools/internals/open_gl/primitive.py b/addon/io_scs_tools/internals/open_gl/primitive.py index a18f483..43b36ec 100644 --- a/addon/io_scs_tools/internals/open_gl/primitive.py +++ b/addon/io_scs_tools/internals/open_gl/primitive.py @@ -18,7 +18,6 @@ # Copyright (C) 2013-2019: SCS Software -import bgl import blf import gpu from array import array @@ -61,23 +60,23 @@ def __init__(self, buffer_type, draw_size, shader_type, attr_names): # depending on type setup callbacks executed before and after dispatching if buffer_type == _Buffer.Types.LINES: - self.__bgl_callback = bgl.glLineWidth - self.__bgl_callback_param_before = self.__draw_size - self.__bgl_callback_param_after = 1.0 + self.__gpu_callback = gpu.state.line_width_set + self.__gpu_callback_param_before = self.__draw_size + self.__gpu_callback_param_after = 1.0 self.__draw_type = 'LINES' elif buffer_type == _Buffer.Types.POINTS: - self.__bgl_callback = bgl.glPointSize - self.__bgl_callback_param_before = self.__draw_size - self.__bgl_callback_param_after = 1.0 + self.__gpu_callback = gpu.state.point_size_set + self.__gpu_callback_param_before = self.__draw_size + self.__gpu_callback_param_after = 1.0 self.__draw_type = 'POINTS' elif buffer_type == _Buffer.Types.TRIS: - self.__bgl_callback = lambda *args: None - self.__bgl_callback_param_before = None - self.__bgl_callback_param_after = None + self.__gpu_callback = lambda *args: None + self.__gpu_callback_param_before = None + self.__gpu_callback_param_after = None self.__draw_type = 'TRIS' def append_attr(self, attr_name, value): @@ -114,7 +113,7 @@ def draw(self, uniforms, space_3d): if self.__type == _Buffer.Types.TRIS and space_3d.shading.type == 'WIREFRAME': return - self.__bgl_callback(self.__bgl_callback_param_before) + self.__gpu_callback(self.__gpu_callback_param_before) # bind shader self.__shader.bind() @@ -133,7 +132,7 @@ def draw(self, uniforms, space_3d): batch = batch_for_shader(self.__shader, self.__draw_type, self.__data) batch.draw(self.__shader) - self.__bgl_callback(self.__bgl_callback_param_after) + self.__gpu_callback(self.__gpu_callback_param_after) def has_entries(self): """Checks if there is any antries in this buffer. @@ -902,7 +901,7 @@ def draw_rect_2d(positions, color): :param color: RGBA of rectangle :type color: tuple(float, float, float, float) """ - shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') + shader = gpu.shader.from_builtin('UNIFORM_COLOR') batch = batch_for_shader( shader, 'TRI_STRIP', { diff --git a/addon/io_scs_tools/operators/wm.py b/addon/io_scs_tools/operators/wm.py index 9a90d98..76f2f4e 100644 --- a/addon/io_scs_tools/operators/wm.py +++ b/addon/io_scs_tools/operators/wm.py @@ -19,6 +19,7 @@ # Copyright (C) 2013-2022: SCS Software +import gpu import bpy import os from bpy.props import StringProperty, BoolProperty, IntProperty @@ -136,13 +137,13 @@ def has_controls(window): @staticmethod def get_scs_banner_img_data(window): - """Loads image to blender data block, loads it to gl memory and gets bindcode address that can be used in - bgl module for image drawing. + """Loads image to blender data block, loads it to GPU memory and returns it's texture that can be used + for image drawing. :param window: window for which we should get banner image :type window: bpy.type.Window - :return: (bindcode of scs banner image, width of scs banner image, height of scs banner image - :rtype: (int, int, int) + :return: (texture, width of scs banner image, height of scs banner image + :rtype: (gpu.types.GPUTexture, int, int) """ if SCS_TOOLS_OT_Show3DViewReport.has_controls(window): @@ -161,12 +162,14 @@ def get_scs_banner_img_data(window): img = bpy.data.images[img_name] + texture = gpu.texture.from_image(img) + # ensure that image is loaded in GPU memory aka has proper bindcode, # we have to that each time because if operator is shown for long time blender might free it on it's own if img.bindcode == 0: img.gl_load() - return img.bindcode, img.size[0], img.size[1] + return texture, img.size[0], img.size[1] @staticmethod def get_lines():