Skip to content

Commit

Permalink
Release - 2.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
simon50keda committed Feb 19, 2020
1 parent 527891f commit 92708cf
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 44 deletions.
2 changes: 1 addition & 1 deletion addon/io_scs_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"name": "SCS Tools",
"description": "Setup models, Import-Export SCS data format",
"author": "Simon Lusenc (50keda), Milos Zajic (4museman)",
"version": (2, 0, "fae8eb4"),
"version": (2, 0, "dd0ff0b"),
"blender": (2, 81, 0),
"location": "File > Import-Export",
"wiki_url": "http://modding.scssoft.com/wiki/Documentation/Tools/SCS_Blender_Tools",
Expand Down
4 changes: 4 additions & 0 deletions addon/io_scs_tools/exp/pim/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ def execute(dirpath, name_suffix, root_object, armature_object, skeleton_filepat
# create mesh object data sections
for mesh_i, mesh_obj in enumerate(mesh_objects):

if mesh_obj.mode != 'OBJECT':
lprint("W Invalid object mode detected on: %r, skipping it on export!", (mesh_obj.name,))
continue

lprint("I Preparing mesh object: %r ...", (mesh_obj.name,))

# create part if it doesn't exists yet
Expand Down
4 changes: 4 additions & 0 deletions addon/io_scs_tools/exp/pim_ef/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ def execute(dirpath, name_suffix, root_object, armature_object, skeleton_filepat
# create mesh object data sections
for mesh_obj in mesh_objects:

if mesh_obj.mode != 'OBJECT':
lprint("W Invalid object mode detected on: %r, skipping it on export!", (mesh_obj.name,))
continue

vert_groups = mesh_obj.vertex_groups

# calculate faces flip state from all ancestors of current object
Expand Down
2 changes: 1 addition & 1 deletion addon/io_scs_tools/internals/shaders/flavors/paint.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,4 @@ def set_color(node_tree, color):
return

color = _convert_utils.to_node_color(color)
node_tree.nodes[PAINT_MULT_NODE].inputs[1].default_value = color
node_tree.nodes[PAINT_MULT_NODE].inputs[1].default_value = color[:3]
7 changes: 5 additions & 2 deletions addon/io_scs_tools/operators/bases/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def get_objects_for_export(self):
for child_obj in children:
if child_obj.select_get():
children_selected.append(child_obj)
else:
elif child_obj.users_scene: # unlinked objects shouldn't be exported
children_unselected.append(child_obj)

# if any children was selected make sure, to export only them
Expand All @@ -79,7 +79,10 @@ def get_objects_for_export(self):
elif export_scope == "scene":
objs_to_export = tuple(bpy.context.scene.objects)
elif export_scope == "scenes":
objs_to_export = tuple(bpy.data.objects)
scenes_objs = set()
for scene in bpy.data.scenes:
scenes_objs.update(scene.objects)
objs_to_export = tuple(scenes_objs)

# cache filtered list, to be able to retrive it quickly on second call
self.cached_objects = objs_to_export
Expand Down
54 changes: 30 additions & 24 deletions addon/io_scs_tools/operators/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ class SCS_TOOLS_OT_MaterialItemExtrasMenu(bpy.types.Operator):
bl_label = "More Options"
bl_idname = "material.scs_tools_material_item_extras"
bl_description = "Show more options for this material item (WT, Copy Linear Color etc.)"
bl_options = {'REGISTER', 'UNDO'}
bl_options = set()

property_str: StringProperty(
description="String representing which property should be worked on.",
Expand Down Expand Up @@ -635,12 +635,33 @@ class SCS_TOOLS_OT_WriteThroughLooks(bpy.types.Operator):
is_ctrl = False # WT to same look of this material in other SCS Roots
is_shift = False # is_shift + is_ctrl -> WT to all looks of this material in all SCS Roots

def init_control_states(self):

# decide which type of WT is it, prefer manually set type over ctrl and shift modifiers
if self.wt_type == self.WT_TYPE_NORMAL:
self.is_ctrl = False
self.is_shift = False
elif self.wt_type == self.WT_TYPE_SAME_LOOK:
self.is_ctrl = True
self.is_shift = False
elif self.wt_type == self.WT_TYPE_ALL:
self.is_ctrl = True
self.is_shift = True
else:
self.is_ctrl = False
self.is_shift = False

# always reset type for next invoke
self.wt_type = -1

def execute(self, context):
material = context.active_object.active_material

if not material or not hasattr(material.scs_props, self.property_str):
return {'CANCELLED'}

self.init_control_states()

scs_roots = []
active_scs_root = _object_utils.get_scs_root(context.active_object)
if active_scs_root:
Expand All @@ -652,11 +673,17 @@ def execute(self, context):
if self.is_shift or not self.is_ctrl: # WT either on active only or all SCS roots; (Shift + Ctrl) or none

altered_looks = 0
altered_scs_roots = 0
for scs_root in scs_roots:
altered_looks += _looks.write_through(scs_root, material, self.property_str)
res = _looks.write_through(scs_root, material, self.property_str)

# only log altered looks if write trought succeded
if res > 0:
altered_looks += res
altered_scs_roots += 1

if altered_looks > 0:
message = "Write through successfully altered %s looks on %s SCS Root Objects!" % (altered_looks, len(scs_roots))
message = "Write through successfully altered %s looks on %s SCS Root Objects!" % (altered_looks, altered_scs_roots)
else:
message = "Nothing to write through."

Expand Down Expand Up @@ -698,27 +725,6 @@ def execute(self, context):

return {'FINISHED'}

def invoke(self, context, event):

# decide which type of WT is it, prefer manually set type over ctrl and shift modifiers
if self.wt_type == self.WT_TYPE_NORMAL:
self.is_ctrl = False
self.is_shift = False
elif self.wt_type == self.WT_TYPE_SAME_LOOK:
self.is_ctrl = True
self.is_shift = False
elif self.wt_type == self.WT_TYPE_ALL:
self.is_ctrl = True
self.is_shift = True
else:
self.is_ctrl = False
self.is_shift = False

# always reset type for next invoke
self.wt_type = -1

return self.execute(context)


class Tobj:
"""
Expand Down
5 changes: 3 additions & 2 deletions addon/io_scs_tools/operators/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -2699,6 +2699,7 @@ def export_to_sii(self, op_inst, config_path):
pjs_alternate_uvset: BoolProperty(default=False)
pjs_flipflake: BoolProperty(default=False)
pjs_airbrush: BoolProperty(default=False)
pjs_stock: BoolProperty(default=False)

@staticmethod
def do_report(the_type, message, do_report=False):
Expand Down Expand Up @@ -2888,7 +2889,7 @@ def export_texture(self, orig_img, tgas_dir_path, texture_portion):

img = bpy.data.images[_SINGLE_COLOR_IMAGE_NAME]
img.colorspace_settings.name = "sRGB" # make sure we use sRGB color-profile
img.use_alpha = True
img.alpha_mode = 'STRAIGHT'
img.pixels[:] = comparing_pixel * 16

# we use shared prefix for 4x4 textures in case any other portion will be using same one
Expand All @@ -2898,7 +2899,7 @@ def export_texture(self, orig_img, tgas_dir_path, texture_portion):
int(comparing_pixel[3] * 255.0))
tga_path = os.path.join(tgas_dir_path, tga_name)

img.save_render(tga_path, bpy.context.scene)
img.save_render(tga_path, scene=bpy.context.scene)

lprint("I Texture portion %r has only one color in common texture, optimizing it by exporting 4x4px TGA!", (texture_portion.id,))

Expand Down
7 changes: 6 additions & 1 deletion addon/io_scs_tools/shader_presets.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,11 @@ Shader {
Tag: "tint_opacity"
Value: ( -0.01 )
}
Attribute {
Format: INT
Tag: "queue_bias"
Value: ( 0 )
}
Texture {
Tag: "texture[X]:texture_base"
Value: "/vehicle/truck/share/glass_ex"
Expand Down Expand Up @@ -2021,4 +2026,4 @@ Flavor {
FriendlyTag: "TexGen1 Scale (X,Z)"
Value: ( 8.0 8.0 )
}
}
}
31 changes: 19 additions & 12 deletions addon/io_scs_tools/utils/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,22 @@ def get_reflection_image(texture_path, report_invalid=False):
if not abs_tobj_filepath or not os.path.isfile(abs_tobj_filepath):
return None

# check existance of this cubemap
if teximag_id_name in bpy.data.images:
# 1. reuse existing image texture if possible, otherwise construct first free slot

if _path.get_abs_path(bpy.data.images[teximag_id_name].filepath) == abs_tobj_filepath:
return bpy.data.images[teximag_id_name]
postfix = 0
postfixed_tex = teximag_id_name
while postfixed_tex in bpy.data.images:

bpy.data.images.remove(bpy.data.images[teximag_id_name])
img_exists = postfixed_tex in bpy.data.images
if img_exists and _path.repair_path(bpy.data.images[postfixed_tex].filepath) == _path.repair_path(abs_tobj_filepath):
return bpy.data.images[postfixed_tex]

# 1. get all textures file paths and check their existance
postfix += 1
postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3)

teximag_id_name = postfixed_tex

# 2. get all textures file paths and check their existance

abs_texture_filepaths = _path.get_texture_paths_from_tobj(abs_tobj_filepath)

Expand Down Expand Up @@ -221,13 +228,13 @@ def get_reflection_image(texture_path, report_invalid=False):

return None

# 2. create image objects for all planes
# 3. create image objects for all planes

images = []
for abs_texture_filepath in abs_texture_filepaths:
images.append(bpy.data.images.load(abs_texture_filepath))

# 3. setup scene, create planes, create camera projector and assign images
# 4. setup scene, create planes, create camera projector and assign images

old_scene = bpy.context.window.scene
tmp_scene = bpy.data.scenes.new("cubemap")
Expand Down Expand Up @@ -314,7 +321,7 @@ def get_reflection_image(texture_path, report_invalid=False):

tmp_scene.collection.objects.link(cam_obj)

# 4. render & save image
# 5. render & save image

final_image_path = os.path.join(tempfile.gettempdir(), teximag_id_name + ".tga")

Expand All @@ -329,7 +336,7 @@ def get_reflection_image(texture_path, report_invalid=False):
tmp_scene.render.filepath = final_image_path
bpy.ops.render.render(write_still=True, scene=tmp_scene.name)

# 5. cleanup & scene restoring
# 6. cleanup & scene restoring

for obj in objects:
bpy.data.objects.remove(obj)
Expand All @@ -349,14 +356,14 @@ def get_reflection_image(texture_path, report_invalid=False):
bpy.context.window.scene = old_scene
bpy.data.scenes.remove(tmp_scene)

# 6. load temp image and pack it
# 7. load temp image and pack it

final_image = bpy.data.images.load(final_image_path)
final_image.name = teximag_id_name
final_image.alpha_mode = 'CHANNEL_PACKED'
final_image.pack()

# 7. set filepath to original image
# 8. set filepath to original image
final_image.filepath = abs_tobj_filepath

return final_image
Expand Down
6 changes: 5 additions & 1 deletion addon/io_scs_tools/utils/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,12 @@ def get_texture_path_from_tobj(tobj_filepath, raw_value=False):
:return: absolute texture file path if found or None
:rtype: str | None
"""
texture_paths = get_texture_paths_from_tobj(tobj_filepath, raw_value=raw_value, first_only=True)

return get_texture_paths_from_tobj(tobj_filepath, raw_value=raw_value, first_only=True)[0]
if not texture_paths:
return None

return texture_paths[0]


def get_texture_paths_from_tobj(tobj_filepath, raw_value=False, first_only=False):
Expand Down

0 comments on commit 92708cf

Please sign in to comment.