Skip to content

Commit

Permalink
Release - 2.3
Browse files Browse the repository at this point in the history
  • Loading branch information
simon50keda committed Jun 3, 2022
1 parent 96f323d commit f68bf7f
Show file tree
Hide file tree
Showing 606 changed files with 1,254 additions and 4,425 deletions.
4 changes: 2 additions & 2 deletions addon/io_scs_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"name": "SCS Tools",
"description": "Setup models, Import-Export SCS data format",
"author": "Simon Lusenc (50keda), Milos Zajic (4museman)",
"version": (2, 2, "a3b485be"),
"blender": (2, 90, 0),
"version": (2, 3, "a8090b9a"),
"blender": (3, 0, 0),
"location": "File > Import-Export",
"wiki_url": "http://modding.scssoft.com/wiki/Documentation/Tools/SCS_Blender_Tools",
"tracker_url": "http://forum.scssoft.com/viewforum.php?f=163",
Expand Down
15 changes: 13 additions & 2 deletions addon/io_scs_tools/exp/pia.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,19 +170,30 @@ def _get_bone_channels(scs_root_obj, armature, scs_animation, action, export_sca
mat_loc = Matrix.Translation(location)

# ROTATION MATRIX
if len(euler_rot_curves) > 0:
if len(euler_rot_curves) > 0 and pose_bone.rotation_mode != 'QUATERNION':
rotation = Euler()
for index in range(3):
if index in euler_rot_curves:
rotation[index] = euler_rot_curves[index].evaluate(actual_frame)
mat_rot = Euler(rotation, pose_bone.rotation_mode).to_matrix().to_4x4() # calc rotation by pose rotation mode

elif len(quat_rot_curves) > 0:
elif len(quat_rot_curves) > 0 and pose_bone.rotation_mode == 'QUATERNION':
rotation = Quaternion()
for index in range(4):
if index in quat_rot_curves:
rotation[index] = quat_rot_curves[index].evaluate(actual_frame)
mat_rot = rotation.to_matrix().to_4x4()
else:
if len(euler_rot_curves) > 0 and pose_bone.rotation_mode == 'QUATERNION':
lprint("W Rotation mode of bone %r from scs animation %r is desycned with it's stored keyframes mode\n\t "
"(keyframes are stored in Eulers but bone pose rotation mode is set to Quaternions), "
"no rotation will be stored for this bone!",
(bone_name, scs_animation.name))
elif len(quat_rot_curves) > 0 and pose_bone.rotation_mode != 'QUATERNION':
lprint("W Rotation mode of bone %r from scs animation %r is desycned with it's stored keyframes mode\n\t "
"(keyframes are stored in Eulers but bone pose rotation mode is set to Quaternions), "
"no rotation will be stored for this bone!",
(bone_name, scs_animation.name))

# SCALE MATRIX
if len(sca_curves) > 0:
Expand Down
26 changes: 15 additions & 11 deletions addon/io_scs_tools/exp/pim/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,18 +295,22 @@ def execute(dirpath, name_suffix, root_object, armature_object, skeleton_filepat
position = tuple(pos_transf_mat @ mesh.vertices[vert_i].co)

# 2. normal -> mesh_for_normals.loops[loop_i].normal -> calc_normals_split() has to be called before
normal = (0, 0, 0)
for i, normals_poly_loop_i in enumerate(normals_poly_loop_indices):
normal_loop = mesh_for_normals.loops[normals_poly_loop_i]

# match by vertex index as triangle will for sure have three unique vertices
if vert_i == normal_loop.vertex_index:
normal = nor_transf_mat @ normal_loop.normal
normal = tuple(Vector(normal).normalized())
del normals_poly_loop_indices[i]
break
vert_normal = (0, 0, 0)
if mesh_for_normals.has_custom_normals or poly.use_smooth:
for i, normals_poly_loop_i in enumerate(normals_poly_loop_indices):
normal_loop = mesh_for_normals.loops[normals_poly_loop_i]

# match by vertex index as triangle will for sure have three unique vertices
if vert_i == normal_loop.vertex_index:
vert_normal = normal_loop.normal
del normals_poly_loop_indices[i]
break
else:
lprint("E Normals data gathering went wrong, expect corrupted mesh! Shouldn't happen...")
else:
lprint("E Normals data gathering went wrong, expect corrupted mesh! Shouldn't happen...")
vert_normal = poly.normal
normal = nor_transf_mat @ vert_normal
normal = tuple(Vector(normal).normalized())

# 3. uvs -> uv_lay = mesh.uv_layers[0].data; uv_lay[loop_i].uv
uvs = []
Expand Down
2 changes: 1 addition & 1 deletion addon/io_scs_tools/exp/pim/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __init__(self, index, alias, effect, blend_mat):
self.__used_textures_count += 1
if "Tag" in tex_entry:
tex_type = tex_entry["Tag"].split(":")[1][8:].strip()
mappings = getattr(blend_mat.scs_props, "shader_texture_" + tex_type + "_uv")
mappings = getattr(blend_mat.scs_props, "shader_texture_" + tex_type + "_uv", [])

# if imported just use custom mappings defined separetly
if blend_mat.scs_props.active_shader_preset_name == "<imported>":
Expand Down
9 changes: 7 additions & 2 deletions addon/io_scs_tools/exp/pim/piece.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ def get_global_triangle_count():
return Piece.__global_triangle_count

@staticmethod
def __calc_vertex_hash(index, uvs, rgba, tangent):
def __calc_vertex_hash(index, normal, uvs, rgba, tangent):
"""Calculates vertex hash from original vertex index, uvs components and vertex color.
:param index: original index from Blender mesh
:type index: int
:param normal: normalized vector representation of the normal
:type normal: tuple | mathutils.Vector
:param uvs: list of uvs used on vertex (each uv must be in SCS coordinates)
:type uvs: list of (tuple | mathutils.Vector)
:param rgba: rgba representation of vertex color in SCS values
Expand All @@ -74,6 +76,9 @@ def __calc_vertex_hash(index, uvs, rgba, tangent):
"""

vertex_hash = str(index)

vertex_hash = "%s%.4f%.4f%.4f" % (vertex_hash, normal[0], normal[1], normal[2])

for uv in uvs:
vertex_hash = "%s%.4f%.4f" % (vertex_hash, uv[0], uv[1])

Expand Down Expand Up @@ -154,7 +159,7 @@ def add_vertex(self, vert_index, position, normal, uvs, uvs_aliases, rgba, tange
:rtype: int
"""

vertex_hash = self.__calc_vertex_hash(vert_index, uvs, rgba, tangent)
vertex_hash = self.__calc_vertex_hash(vert_index, normal, uvs, rgba, tangent)

# save vertex if the vertex with the same properties doesn't exists yet in streams
if vertex_hash not in self.__vertices_hash:
Expand Down
16 changes: 11 additions & 5 deletions addon/io_scs_tools/exp/pit.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,12 +588,18 @@ def export(root_object, filepath, name_suffix, used_parts, used_materials):

if tex_prop == "Tag":
tag_id_string = texture_dict[tex_prop].split(':')[1]
texture_section.props.append((tex_prop, texture_dict[tex_prop]))

if tex_prop == "Value" and tag_id_string != "":

tobj_rel_path = get_texture_path_from_material(material, tag_id_string, os.path.dirname(filepath))
texture_section.props.append((tex_prop, tobj_rel_path))

elif tex_prop == "Value":
if tag_id_string[8:] in material.scs_props.get_texture_types():
tobj_rel_path = get_texture_path_from_material(material, tag_id_string, os.path.dirname(filepath))
texture_section.props.append((tex_prop, tobj_rel_path))
else:
texture_section.props.append((tex_prop, texture_dict[tex_prop]))
if looks_count > 1:
lprint("W Texture of type %r on material %r with imported shader is not supported in Blender, "
"thus imported texture path from first look will be used on all of them!",
(tag_id_string, material_name))
else:
texture_section.props.append((tex_prop, texture_dict[tex_prop]))

Expand Down
16 changes: 11 additions & 5 deletions addon/io_scs_tools/exp/pit_ef.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,18 @@ def export(root_object, filepath, name_suffix, used_parts, used_materials):

if tex_prop == "Tag":
tag_id_string = texture_dict[tex_prop].split(':')[1]
texture_section.props.append((tex_prop, texture_dict[tex_prop]))

if tex_prop == "Value" and tag_id_string != "":

tobj_rel_path = get_texture_path_from_material(material, tag_id_string, os.path.dirname(filepath))
texture_section.props.append((tex_prop, tobj_rel_path))

elif tex_prop == "Value":
if tag_id_string[8:] in material.scs_props.get_texture_types():
tobj_rel_path = get_texture_path_from_material(material, tag_id_string, os.path.dirname(filepath))
texture_section.props.append((tex_prop, tobj_rel_path))
else:
texture_section.props.append((tex_prop, texture_dict[tex_prop]))
if looks_count > 1:
lprint("W Texture of type %r on material %r with imported shader is not supported in Blender, "
"thus imported texture path from first look will be used on all of them!",
(tag_id_string, material_name))
else:
texture_section.props.append((tex_prop, texture_dict[tex_prop]))

Expand Down
4 changes: 2 additions & 2 deletions addon/io_scs_tools/imp/pix.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,8 @@ def load(context, filepath, name_suffix="", suppress_reports=False):
# FINAL FEEDBACK
bpy.context.window.cursor_modal_restore()
if suppress_reports:
lprint('\nI Import compleeted in %.3f sec.', time.time() - t)
lprint('\nI Import completed in %.3f sec.', time.time() - t)
else:
lprint('\nI Import compleeted in %.3f sec.', time.time() - t, report_errors=True, report_warnings=True)
lprint('\nI Import completed in %.3f sec.', time.time() - t, report_errors=True, report_warnings=True)

return True
6 changes: 3 additions & 3 deletions addon/io_scs_tools/internals/connections/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def exists(data_block):
# some kinda data integrity check
if len(cache[LOCATORS]) == len(refs[LOCATORS]):

if len(cache[LOCATORS]) == 0 or len(cache[LOCATORS].values()[0]) == 6:
if len(cache[LOCATORS]) == 0 or len(next(iter(cache[LOCATORS].values()))) == 6:

return True

Expand All @@ -116,7 +116,7 @@ def exists(data_block):
OBJS_COUNT: len(bpy.data.objects)
}

for loc_name in refs[LOCATORS].keys():
for loc_name in list(refs[LOCATORS].keys()):
__create_locator_entries__(data_block, bpy.data.objects[loc_name])

return True
Expand Down Expand Up @@ -730,7 +730,7 @@ def cleanup_check(data_block):
data[CACHE][OBJS_COUNT] = len(bpy.data.objects)

i = j = 0
for conn_key in conn_entries.keys():
for conn_key in list(conn_entries.keys()):

if conn_key in conn_entries:

Expand Down
2 changes: 1 addition & 1 deletion addon/io_scs_tools/internals/containers/sii.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def has_valid_unit_instance(container, unit_type, req_props=tuple(), one_of_prop

# invalid unit type
if unit_type != "" and container[unit_instance].type != unit_type:
lprint("D Validation failed: Invalid unit instance type!")
lprint("D Validation failed: Invalid unit instance type (wanted: %r actual: %r)!", (unit_type, container[unit_instance].type))
return False

for prop in req_props:
Expand Down
2 changes: 1 addition & 1 deletion addon/io_scs_tools/internals/icons/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def get_loaded_themes():
:return: random ordered theme names
:rtype: list[str]
"""
return _cache[PCOLLS].keys()
return list(_cache[PCOLLS].keys())


def has_loaded_themes():
Expand Down
20 changes: 12 additions & 8 deletions addon/io_scs_tools/internals/looks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
#
# ##### END GPL LICENSE BLOCK #####

# Copyright (C) 2015-2019: SCS Software
# Copyright (C) 2015-2022: SCS Software

from collections import Iterable
from collections.abc import Iterable
from io_scs_tools.consts import Look as _LOOK_consts
from io_scs_tools.utils import property as _property_utils
from io_scs_tools.utils.printout import lprint
Expand Down Expand Up @@ -145,7 +145,7 @@ def apply_active_look(root_obj, force_apply=False):
update_func(material)

# unset any unused
for prop in material.scs_props.keys():
for prop in list(material.scs_props.keys()):
valid_prefix = (prop.startswith("shader_attribute") or prop.startswith("shader_texture"))
is_not_ignored = not ((prop.startswith("shader_texture") and prop.endswith(_IGNORED_TEXTURE_PROPS)) or prop in _IGNORED_PROPS)
if prop not in mat_data and valid_prefix and is_not_ignored:
Expand Down Expand Up @@ -201,7 +201,7 @@ def update_look_from_material(root_obj, material, preset_change=False):

curr_mat = root_obj[_MAIN_DICT][look_id][mat_id_str]

for key in curr_mat:
for key in list(curr_mat.keys()):

if preset_change: # preset change write through

Expand Down Expand Up @@ -381,7 +381,8 @@ def add_materials(root_obj, mat_list):
if _MAIN_DICT not in root_obj or len(root_obj[_MAIN_DICT]) <= 0:
return

existing_mats_ids = root_obj[_MAIN_DICT][root_obj[_MAIN_DICT].keys()[0]].keys()
first_look_id = next(iter(root_obj[_MAIN_DICT].keys()))
existing_mats_ids = root_obj[_MAIN_DICT][first_look_id].keys()
new_mats_added = 0
for new_mat in mat_list:

Expand Down Expand Up @@ -412,7 +413,8 @@ def clean_unused(root_obj):
return

# create unused materials id list with removing used materials ids from exisiting
unused_mats_ids = list(root_obj[_MAIN_DICT][root_obj[_MAIN_DICT].keys()[0]].keys())
first_look_id = next(iter(root_obj[_MAIN_DICT].keys()))
unused_mats_ids = list(root_obj[_MAIN_DICT][first_look_id].keys())
for mat in __collect_materials__(root_obj):

mat_id_str = str(mat.scs_props.id)
Expand Down Expand Up @@ -451,7 +453,8 @@ def reassign_material(root_obj, new_mat, old_mat):
if _MAIN_DICT not in root_obj or len(root_obj[_MAIN_DICT]) <= 0:
return

existing_mats_ids = root_obj[_MAIN_DICT][root_obj[_MAIN_DICT].keys()[0]].keys()
first_look_id = next(iter(root_obj[_MAIN_DICT].keys()))
existing_mats_ids = root_obj[_MAIN_DICT][first_look_id].keys()

new_mat_id_str = str(new_mat.scs_props.id)
old_mat_id_str = str(old_mat.scs_props.id)
Expand Down Expand Up @@ -487,7 +490,8 @@ def get_material_entries(root_obj, material):
if _MAIN_DICT not in root_obj or len(root_obj[_MAIN_DICT]) <= 0:
return {}

existing_mats_ids = root_obj[_MAIN_DICT][root_obj[_MAIN_DICT].keys()[0]].keys()
first_look_id = next(iter(root_obj[_MAIN_DICT].keys()))
existing_mats_ids = root_obj[_MAIN_DICT][first_look_id].keys()

mat_id_str = str(material.scs_props.id)

Expand Down
4 changes: 2 additions & 2 deletions addon/io_scs_tools/internals/open_gl/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def cache_locations_2d(self, objs, region, region_3d):

# pop first element if we have too many of entries already
if len(cache) >= 10:
first_key = list(cache.keys())[0]
first_key = next(iter(cache.keys()))
del cache[first_key]

cache[persp_matrix_str] = {}
Expand All @@ -92,7 +92,7 @@ def cache_locations_2d(self, objs, region, region_3d):
continue

# calculate 2d location!
loc_2d = location_3d_to_region_2d(region, region_3d, loc_ws, None)
loc_2d = location_3d_to_region_2d(region, region_3d, loc_ws, default=None)

# if out of bounds, ignore it!
if not loc_2d or loc_2d.x < 0 or loc_2d.x > region.width or loc_2d.y < 0 or loc_2d.y > region.height:
Expand Down
15 changes: 14 additions & 1 deletion addon/io_scs_tools/internals/open_gl/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,20 @@ def fill_buffers(object_list):

for visib_obj in object_list:

if visib_obj.type != 'EMPTY' or visib_obj.scs_props.empty_object_type != 'Locator' or not visib_obj.visible_get():
# passed object reference got removed
try:
# do simple name access, to trigger possible reference error.
_ = visib_obj.name
except ReferenceError:
continue

if visib_obj.type != 'EMPTY':
continue

if visib_obj.scs_props.empty_object_type != 'Locator':
continue

if not visib_obj.visible_get():
continue

if visib_obj.scs_props.locator_type == 'Prefab':
Expand Down
8 changes: 6 additions & 2 deletions addon/io_scs_tools/operators/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,17 @@ def execute(self, context):
self.report({'WARNING'}, "Could not create convex mesh, selected object(s) seems to form a flat surface!")
return {'CANCELLED'}

# ensure we have active object
if not active_object:
active_object = objects[0]

parent = active_object.parent
paernt_inverse_mat = active_object.matrix_parent_inverse
parent_inverse_mat = active_object.matrix_parent_inverse
locator = _object_utils.create_collider_convex_locator(geom, convex_props, objects, self.delete_mesh_objects)
if locator:
locator.parent = parent
# make sure to apply parent inverse matrix so object is oriented as origin object
locator.matrix_parent_inverse = paernt_inverse_mat
locator.matrix_parent_inverse = parent_inverse_mat
_object_utils.make_objects_selected((locator,))
return {'FINISHED'}

Expand Down
Loading

0 comments on commit f68bf7f

Please sign in to comment.