diff --git a/Assets/Luneraria/Art.meta b/Assets/Luneraria/Art.meta new file mode 100644 index 0000000..10f304c --- /dev/null +++ b/Assets/Luneraria/Art.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 50ac3333ebb2c4d7a9f94a41495626b4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings.meta b/Assets/Luneraria/Art/Buildings.meta new file mode 100644 index 0000000..a206112 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f40c6a05032444fdbf7dd895f45db6f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/ancient.export.json b/Assets/Luneraria/Art/Buildings/ancient.export.json new file mode 100644 index 0000000..33aa7d2 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/ancient.export.json @@ -0,0 +1,1191 @@ +{ + "id": "ancient", + "group": "Buildings", + "source": "assets-source/luneraria/g2/ancient.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['Banner_L', 'Banner_R', 'Blade_0', 'Blade_1', 'Blade_2', 'Blade_3', 'Crest_A', 'Crest_B', 'Crown', 'Crystal', 'Dais', 'Fragment_0', 'Fragment_1', 'Fragment_2', 'Fragment_3', 'Fragment_4', 'Fragment_5', 'Pedestal', 'Ring_Inner', 'Ring_Outer', 'Ruin_Crystal', 'Ruin_Rubble', 'Satellite_0', 'Satellite_1', 'Satellite_2', 'Satellite_3', 'Satellite_4']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "triangles_match_godot", + "ok": true, + "detail": "19032 fbx / 19032 godot" + }, + { + "check": "mesh_names_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "materials_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_match_godot", + "ok": true, + "detail": "largest difference 0.00000 m" + }, + { + "check": "no_armature", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "19032 / 19032" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + } + ], + "source_sha256": "57524632f468641d63970c19493e4e8161e812093d29fb41beeadae17a2e4e9d", + "removed_modifiers": 0, + "kind": "static", + "fps": 30.0, + "objects": 27, + "meshes": { + "Dais": { + "mesh": "Dais", + "triangles": 1844, + "vertices": 1025, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Pale", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -4.0, + -0.06, + -4.0 + ], + "max": [ + 4.0, + 0.155, + 4.0 + ] + } + }, + "Pedestal": { + "mesh": "Pedestal", + "triangles": 4320, + "vertices": 2232, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team", + "LN_Metal_Iron", + "LN_Crystal_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -4.2035, + -0.05, + -3.3021 + ], + "max": [ + 4.2035, + 6.75, + 2.6721 + ] + } + }, + "Blade_0": { + "mesh": "Blade_0", + "triangles": 804, + "vertices": 408, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.7776, + 3.3728, + -0.2944 + ], + "max": [ + -0.4238, + 8.7139, + 0.2944 + ] + } + }, + "Blade_1": { + "mesh": "Blade_1", + "triangles": 804, + "vertices": 408, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2944, + 3.3728, + 0.4238 + ], + "max": [ + 0.2944, + 8.7139, + 2.7776 + ] + } + }, + "Blade_2": { + "mesh": "Blade_2", + "triangles": 804, + "vertices": 408, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.4238, + 3.3728, + -0.2944 + ], + "max": [ + 2.7776, + 8.7139, + 0.2944 + ] + } + }, + "Blade_3": { + "mesh": "Blade_3", + "triangles": 804, + "vertices": 408, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2944, + 3.3728, + -2.7776 + ], + "max": [ + 0.2944, + 8.7139, + -0.4238 + ] + } + }, + "Crown": { + "mesh": "Crown", + "triangles": 720, + "vertices": 400, + "ngons": 0, + "materials": [ + "LN_Metal_Team", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.71, + 8.51, + -0.71 + ], + "max": [ + 0.71, + 8.73, + 0.71 + ] + } + }, + "Crystal": { + "mesh": "Crystal", + "triangles": 366, + "vertices": 185, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.8693, + 0.0623, + -0.8297 + ], + "max": [ + 0.8227, + 3.6929, + 0.8668 + ] + } + }, + "Satellite_0": { + "mesh": "Satellite_0", + "triangles": 350, + "vertices": 177, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3285, + 1.0131, + -0.2995 + ], + "max": [ + 0.284, + 2.485, + 0.3444 + ] + } + }, + "Satellite_1": { + "mesh": "Satellite_1", + "triangles": 350, + "vertices": 177, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3192, + 1.0019, + -0.291 + ], + "max": [ + 0.2948, + 2.5016, + 0.3245 + ] + } + }, + "Satellite_2": { + "mesh": "Satellite_2", + "triangles": 350, + "vertices": 177, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3041, + 1.0088, + -0.3269 + ], + "max": [ + 0.3093, + 2.4967, + 0.2897 + ] + } + }, + "Satellite_3": { + "mesh": "Satellite_3", + "triangles": 350, + "vertices": 177, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3041, + 1.0088, + -0.3269 + ], + "max": [ + 0.3093, + 2.4967, + 0.2897 + ] + } + }, + "Satellite_4": { + "mesh": "Satellite_4", + "triangles": 350, + "vertices": 177, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3192, + 1.0019, + -0.291 + ], + "max": [ + 0.2948, + 2.5016, + 0.3245 + ] + } + }, + "Ring_Outer": { + "mesh": "Ring_Outer", + "triangles": 1008, + "vertices": 560, + "ngons": 0, + "materials": [ + "LN_Metal_Team", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.928, + -0.4324, + -1.8965 + ], + "max": [ + 1.928, + 0.4324, + 1.8965 + ] + } + }, + "Ring_Inner": { + "mesh": "Ring_Inner", + "triangles": 1008, + "vertices": 560, + "ngons": 0, + "materials": [ + "LN_Metal_Team", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.2809, + -0.9881, + -1.4781 + ], + "max": [ + 1.2809, + 0.9881, + 1.4781 + ] + } + }, + "Fragment_0": { + "mesh": "Fragment_0", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -3.1026, + 3.0077, + 0.7335 + ], + "max": [ + -2.6949, + 3.7223, + 1.0569 + ] + } + }, + "Fragment_1": { + "mesh": "Fragment_1", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.0624, + 3.9084, + 2.7577 + ], + "max": [ + -0.1185, + 4.4007, + 3.1904 + ] + } + }, + "Fragment_2": { + "mesh": "Fragment_2", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 2.0295, + 4.5758, + 1.9129 + ], + "max": [ + 2.5456, + 5.1245, + 2.2273 + ] + } + }, + "Fragment_3": { + "mesh": "Fragment_3", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 2.635, + 2.7535, + -1.1147 + ], + "max": [ + 3.1571, + 3.6783, + -0.6799 + ] + } + }, + "Fragment_4": { + "mesh": "Fragment_4", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.2453, + 3.884, + -3.127 + ], + "max": [ + 0.9747, + 4.2616, + -2.812 + ] + } + }, + "Fragment_5": { + "mesh": "Fragment_5", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.6379, + 4.6095, + -2.2876 + ], + "max": [ + -1.9684, + 5.3196, + -1.8621 + ] + } + }, + "Banner_L": { + "mesh": "Banner_L", + "triangles": 168, + "vertices": 105, + "ngons": 0, + "materials": [ + "LN_Cloth_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -4.1738, + 3.0, + -3.2133 + ], + "max": [ + -3.5049, + 5.9, + -2.2778 + ] + } + }, + "Banner_R": { + "mesh": "Banner_R", + "triangles": 168, + "vertices": 105, + "ngons": 0, + "materials": [ + "LN_Cloth_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 3.5049, + 3.0, + -3.2133 + ], + "max": [ + 4.1738, + 5.9, + -2.2778 + ] + } + }, + "Ruin_Crystal": { + "mesh": "Ruin_Crystal", + "triangles": 280, + "vertices": 168, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.7547, + -0.0345, + -2.8068 + ], + "max": [ + 2.3534, + 1.9235, + 2.3412 + ] + } + }, + "Ruin_Rubble": { + "mesh": "Ruin_Rubble", + "triangles": 600, + "vertices": 360, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -4.1598, + -0.0084, + -2.7989 + ], + "max": [ + 3.5162, + 3.7388, + 3.8217 + ] + } + }, + "Crest_A": { + "mesh": "Crest_A", + "triangles": 1296, + "vertices": 658, + "ngons": 0, + "materials": [ + "LN_Metal_Team", + "LN_Rune_Team", + "LN_Crystal_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.1289, + 8.6353, + -0.28 + ], + "max": [ + 1.1289, + 10.3668, + 0.28 + ] + } + }, + "Crest_B": { + "mesh": "Crest_B", + "triangles": 2168, + "vertices": 1104, + "ngons": 0, + "materials": [ + "LN_Metal_Team", + "LN_Crystal_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.3137, + 8.6731, + -1.1427 + ], + "max": [ + 1.2379, + 9.918, + 1.2954 + ] + } + } + }, + "armatures": {}, + "empties": {}, + "bounds_unity": { + "min": [ + -4.2035, + -0.9881, + -4.0 + ], + "max": [ + 4.2035, + 10.3668, + 4.0 + ] + }, + "clips": [], + "expected_from_godot": { + "triangles": 19032, + "bounds_godot": { + "min": [ + -4.2035, + -0.9881, + -4.0 + ], + "max": [ + 4.2035, + 10.3668, + 4.0 + ] + }, + "resource_path": "res://assets/luneraria/g2/ancient.glb" + }, + "meshes_without_uv": [ + "Crystal", + "Fragment_0", + "Fragment_1", + "Fragment_2", + "Fragment_3", + "Fragment_4", + "Fragment_5", + "Ruin_Crystal", + "Ruin_Rubble", + "Satellite_0", + "Satellite_1", + "Satellite_2", + "Satellite_3", + "Satellite_4" + ], + "triangles": 19032, + "fbx": "Assets/Luneraria/Art/Buildings/ancient.fbx", + "fbx_bytes": 1266572, + "ok": true +} diff --git a/Assets/Luneraria/Art/Buildings/ancient.export.json.meta b/Assets/Luneraria/Art/Buildings/ancient.export.json.meta new file mode 100644 index 0000000..f53e81b --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/ancient.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4a082f612d76242bd8aebf43e93aeca2 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/ancient.fbx b/Assets/Luneraria/Art/Buildings/ancient.fbx new file mode 100644 index 0000000..db75ade Binary files /dev/null and b/Assets/Luneraria/Art/Buildings/ancient.fbx differ diff --git a/Assets/Luneraria/Art/Buildings/ancient.fbx.meta b/Assets/Luneraria/Art/Buildings/ancient.fbx.meta new file mode 100644 index 0000000..8f9df77 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/ancient.fbx.meta @@ -0,0 +1,111 @@ +fileFormatVersion: 2 +guid: a0437d8104fe34013aacb4fb7c2a5a6c +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 0 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 0 + humanoidOversampling: 1 + avatarSetup: 0 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/bastion.export.json b/Assets/Luneraria/Art/Buildings/bastion.export.json new file mode 100644 index 0000000..388c985 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/bastion.export.json @@ -0,0 +1,602 @@ +{ + "id": "bastion", + "group": "Buildings", + "source": "assets-source/luneraria/g2/bastion.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['Crystal', 'Debris', 'Lower', 'Pennant', 'Ring', 'Ruin', 'Shard_0', 'Shard_1', 'Shard_2', 'Upper', 'Upper_Damaged']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "triangles_match_godot", + "ok": true, + "detail": "9364 fbx / 9364 godot" + }, + { + "check": "mesh_names_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "materials_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_match_godot", + "ok": true, + "detail": "largest difference 0.00000 m" + }, + { + "check": "no_armature", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "9364 / 9364" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + } + ], + "source_sha256": "5ac677fe95f3c65364fa4003b9cae694ad58734b157238f196f4d926de655d60", + "removed_modifiers": 0, + "kind": "static", + "fps": 30.0, + "objects": 11, + "meshes": { + "Lower": { + "mesh": "Lower", + "triangles": 658, + "vertices": 368, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Metal_Iron" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.7395, + 0.0, + -2.25 + ], + "max": [ + 1.7395, + 2.6655, + 1.6437 + ] + } + }, + "Upper": { + "mesh": "Upper", + "triangles": 3272, + "vertices": 1722, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team", + "LN_Stone_Dark", + "LN_Metal_Iron", + "LN_Wood" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.5347, + 2.4409, + -1.5347 + ], + "max": [ + 1.5347, + 7.1605, + 1.5347 + ] + } + }, + "Upper_Damaged": { + "mesh": "Upper_Damaged", + "triangles": 2948, + "vertices": 1554, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team", + "LN_Stone_Dark", + "LN_Metal_Iron", + "LN_Wood" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.5368, + 2.3209, + -1.5372 + ], + "max": [ + 1.4687, + 7.1605, + 1.5405 + ] + } + }, + "Debris": { + "mesh": "Debris", + "triangles": 316, + "vertices": 178, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.1156, + -0.3891, + -1.7064 + ], + "max": [ + 1.8813, + 0.54, + 1.9496 + ] + } + }, + "Crystal": { + "mesh": "Crystal", + "triangles": 24, + "vertices": 14, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.4934, + 5.54, + -0.4411 + ], + "max": [ + 0.4885, + 7.06, + 0.409 + ] + } + }, + "Ring": { + "mesh": "Ring", + "triangles": 640, + "vertices": 320, + "ngons": 0, + "materials": [ + "LN_Metal_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.865, + 6.15, + -0.865 + ], + "max": [ + 0.865, + 6.25, + 0.865 + ] + } + }, + "Shard_0": { + "mesh": "Shard_0", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.1308, + 6.17, + -0.106 + ], + "max": [ + -0.9277, + 6.61, + 0.1012 + ] + } + }, + "Shard_1": { + "mesh": "Shard_1", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.397, + 6.17, + 0.7782 + ], + "max": [ + 0.601, + 6.61, + 0.9923 + ] + } + }, + "Shard_2": { + "mesh": "Shard_2", + "triangles": 20, + "vertices": 12, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3992, + 6.17, + -0.9903 + ], + "max": [ + 0.6009, + 6.61, + -0.779 + ] + } + }, + "Pennant": { + "mesh": "Pennant", + "triangles": 64, + "vertices": 45, + "ngons": 0, + "materials": [ + "LN_Cloth_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.06, + 5.65, + -1.46 + ], + "max": [ + 0.76, + 6.8, + -1.46 + ] + } + }, + "Ruin": { + "mesh": "Ruin", + "triangles": 1382, + "vertices": 770, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Crystal_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.0369, + -0.3691, + -2.5389 + ], + "max": [ + 2.9008, + 2.6896, + 1.9476 + ] + } + } + }, + "armatures": {}, + "empties": {}, + "bounds_unity": { + "min": [ + -2.1156, + -0.3891, + -2.5389 + ], + "max": [ + 2.9008, + 7.1605, + 1.9496 + ] + }, + "clips": [], + "expected_from_godot": { + "triangles": 9364, + "bounds_godot": { + "min": [ + -1.7395, + 0.0, + -2.25 + ], + "max": [ + 1.7395, + 7.1605, + 1.6437 + ] + }, + "resource_path": "res://assets/luneraria/g2/bastion.glb" + }, + "meshes_without_uv": [ + "Crystal", + "Debris", + "Lower", + "Shard_0", + "Shard_1", + "Shard_2" + ], + "triangles": 9364, + "fbx": "Assets/Luneraria/Art/Buildings/bastion.fbx", + "fbx_bytes": 618812, + "ok": true +} diff --git a/Assets/Luneraria/Art/Buildings/bastion.export.json.meta b/Assets/Luneraria/Art/Buildings/bastion.export.json.meta new file mode 100644 index 0000000..a2d3359 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/bastion.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b6d3f51223b7f4f00b4ae9778a64127e +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/bastion.fbx b/Assets/Luneraria/Art/Buildings/bastion.fbx new file mode 100644 index 0000000..4941c12 Binary files /dev/null and b/Assets/Luneraria/Art/Buildings/bastion.fbx differ diff --git a/Assets/Luneraria/Art/Buildings/bastion.fbx.meta b/Assets/Luneraria/Art/Buildings/bastion.fbx.meta new file mode 100644 index 0000000..aeb6f8d --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/bastion.fbx.meta @@ -0,0 +1,111 @@ +fileFormatVersion: 2 +guid: 6633f0fd87c194e13a26c46c8a57a3a8 +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 0 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 0 + humanoidOversampling: 1 + avatarSetup: 0 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/bossgrotte.export.json b/Assets/Luneraria/Art/Buildings/bossgrotte.export.json new file mode 100644 index 0000000..35130eb --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/bossgrotte.export.json @@ -0,0 +1,632 @@ +{ + "id": "bossgrotte", + "group": "Buildings", + "source": "assets-source/luneraria/g2/bossgrotte.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['Altar', 'Cave', 'CaveGlow', 'Channel', 'Floor', 'Gate', 'PillarCrystals', 'Pillars', 'Platform', 'Rocks', 'Runes', 'Source']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "triangles_match_godot", + "ok": true, + "detail": "15182 fbx / 15182 godot" + }, + { + "check": "mesh_names_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "materials_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_match_godot", + "ok": true, + "detail": "largest difference 0.00000 m" + }, + { + "check": "no_armature", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "15182 / 15182" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + } + ], + "source_sha256": "c3a87a8e7b0b8e0778ba7f9f274584e98e5c70a8229bc1cbee7ed9fd6aba7d9e", + "removed_modifiers": 0, + "kind": "static", + "fps": 30.0, + "objects": 12, + "meshes": { + "Floor": { + "mesh": "Floor", + "triangles": 2108, + "vertices": 1097, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Grotto" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -7.7775, + -0.4, + -7.7874 + ], + "max": [ + 7.7755, + 0.26, + 7.7976 + ] + } + }, + "Runes": { + "mesh": "Runes", + "triangles": 1164, + "vertices": 712, + "ngons": 0, + "materials": [ + "LN_Rune_Grotto" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -4.72, + 0.104, + -7.9255 + ], + "max": [ + 7.9255, + 5.899, + 4.72 + ] + } + }, + "Platform": { + "mesh": "Platform", + "triangles": 808, + "vertices": 433, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Grotto" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.8, + -0.02, + -3.8 + ], + "max": [ + 3.8, + 0.125, + 0.8 + ] + } + }, + "Altar": { + "mesh": "Altar", + "triangles": 552, + "vertices": 280, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Grotto" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 1.7789, + -0.05, + -4.4738 + ], + "max": [ + 4.4738, + 3.45, + -1.7789 + ] + } + }, + "Source": { + "mesh": "Source", + "triangles": 192, + "vertices": 112, + "ngons": 0, + "materials": [ + "LN_Crystal_Grotto" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 2.64, + 0.5, + -3.4746 + ], + "max": [ + 3.6064, + 2.7, + -2.7716 + ] + } + }, + "Gate": { + "mesh": "Gate", + "triangles": 3944, + "vertices": 2016, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Grotto", + "LN_Metal_Bronze" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 3.2222, + -0.5, + -9.435 + ], + "max": [ + 9.435, + 7.499, + -3.2222 + ] + } + }, + "Cave": { + "mesh": "Cave", + "triangles": 424, + "vertices": 232, + "ngons": 0, + "materials": [ + "LN_Cave", + "LN_Stone_Dark" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 4.575, + -1.93, + -10.0692 + ], + "max": [ + 10.0692, + 3.7, + -4.575 + ] + } + }, + "CaveGlow": { + "mesh": "CaveGlow", + "triangles": 182, + "vertices": 117, + "ngons": 0, + "materials": [ + "LN_Water_Glow", + "LN_Crystal_Grotto" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 5.1204, + -0.97, + -9.4328 + ], + "max": [ + 9.5452, + 2.7, + -5.4993 + ] + } + }, + "Channel": { + "mesh": "Channel", + "triangles": 600, + "vertices": 304, + "ngons": 0, + "materials": [ + "LN_Water_Glow" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3712, + 0.26, + -7.0092 + ], + "max": [ + 7.0092, + 0.28, + 0.3712 + ] + } + }, + "Pillars": { + "mesh": "Pillars", + "triangles": 4328, + "vertices": 2280, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Grotto" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -7.7579, + -0.05, + -7.5321 + ], + "max": [ + 7.5454, + 5.961, + 7.7587 + ] + } + }, + "PillarCrystals": { + "mesh": "PillarCrystals", + "triangles": 80, + "vertices": 48, + "ngons": 0, + "materials": [ + "LN_Crystal_Grotto" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -6.4468, + 5.23, + -7.0317 + ], + "max": [ + 7.014, + 6.03, + 6.441 + ] + } + }, + "Rocks": { + "mesh": "Rocks", + "triangles": 800, + "vertices": 420, + "ngons": 0, + "materials": [ + "LN_Rock" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.9737, + -0.6391, + -10.4646 + ], + "max": [ + 10.5442, + 7.6927, + 2.8772 + ] + } + } + }, + "armatures": {}, + "empties": {}, + "bounds_unity": { + "min": [ + -7.7775, + -1.93, + -10.4646 + ], + "max": [ + 10.5442, + 7.6927, + 7.7976 + ] + }, + "clips": [], + "expected_from_godot": { + "triangles": 15182, + "bounds_godot": { + "min": [ + -10.5442, + -1.93, + -10.4646 + ], + "max": [ + 7.7775, + 7.6927, + 7.7976 + ] + }, + "resource_path": "res://assets/luneraria/g2/bossgrotte.glb" + }, + "meshes_without_uv": [ + "Cave", + "PillarCrystals", + "Rocks", + "Source" + ], + "triangles": 15182, + "fbx": "Assets/Luneraria/Art/Buildings/bossgrotte.fbx", + "fbx_bytes": 989708, + "ok": true +} diff --git a/Assets/Luneraria/Art/Buildings/bossgrotte.export.json.meta b/Assets/Luneraria/Art/Buildings/bossgrotte.export.json.meta new file mode 100644 index 0000000..61966bd --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/bossgrotte.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b3c1a5924044546adb0dba298c3ddc35 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/bossgrotte.fbx b/Assets/Luneraria/Art/Buildings/bossgrotte.fbx new file mode 100644 index 0000000..7e25661 Binary files /dev/null and b/Assets/Luneraria/Art/Buildings/bossgrotte.fbx differ diff --git a/Assets/Luneraria/Art/Buildings/bossgrotte.fbx.meta b/Assets/Luneraria/Art/Buildings/bossgrotte.fbx.meta new file mode 100644 index 0000000..439db90 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/bossgrotte.fbx.meta @@ -0,0 +1,111 @@ +fileFormatVersion: 2 +guid: 39a4b40e68ab84129824e427365b5868 +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 0 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 0 + humanoidOversampling: 1 + avatarSetup: 0 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/grenzwacht.export.json b/Assets/Luneraria/Art/Buildings/grenzwacht.export.json new file mode 100644 index 0000000..38a1175 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/grenzwacht.export.json @@ -0,0 +1,456 @@ +{ + "id": "grenzwacht", + "group": "Buildings", + "source": "assets-source/luneraria/g2/grenzwacht.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['Crystal', 'Debris', 'Lower', 'Pennant', 'Ruin', 'Upper', 'Upper_Damaged']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "triangles_match_godot", + "ok": true, + "detail": "6516 fbx / 6516 godot" + }, + { + "check": "mesh_names_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "materials_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_match_godot", + "ok": true, + "detail": "largest difference 0.00000 m" + }, + { + "check": "no_armature", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "6516 / 6516" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + } + ], + "source_sha256": "7067f4f3349918e412a3ee684651753bbb3ee958a46dd3775af6b93661d7e96f", + "removed_modifiers": 0, + "kind": "static", + "fps": 30.0, + "objects": 7, + "meshes": { + "Lower": { + "mesh": "Lower", + "triangles": 550, + "vertices": 296, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Pale", + "LN_Wood" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.3752, + 0.0, + -1.3735 + ], + "max": [ + 1.3717, + 2.3142, + 1.3678 + ] + } + }, + "Upper": { + "mesh": "Upper", + "triangles": 2536, + "vertices": 1336, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team", + "LN_Stone_Dark", + "LN_Metal_Iron", + "LN_Wood" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.1568, + 2.18, + -1.1568 + ], + "max": [ + 1.1568, + 6.0601, + 1.1568 + ] + } + }, + "Upper_Damaged": { + "mesh": "Upper_Damaged", + "triangles": 2164, + "vertices": 1136, + "ngons": 0, + "materials": [ + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Rune_Team", + "LN_Stone_Dark", + "LN_Wood", + "LN_Metal_Iron" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.1568, + 2.18, + -1.1569 + ], + "max": [ + 1.1606, + 6.0601, + 1.1364 + ] + } + }, + "Debris": { + "mesh": "Debris", + "triangles": 140, + "vertices": 84, + "ngons": 0, + "materials": [ + "LN_Stone_Pale" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.0393, + -0.0358, + -1.4479 + ], + "max": [ + 1.8685, + 0.2255, + 0.2742 + ] + } + }, + "Crystal": { + "mesh": "Crystal", + "triangles": 24, + "vertices": 14, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3468, + 4.7, + -0.3102 + ], + "max": [ + 0.345, + 5.84, + 0.3126 + ] + } + }, + "Pennant": { + "mesh": "Pennant", + "triangles": 64, + "vertices": 45, + "ngons": 0, + "materials": [ + "LN_Cloth_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.06, + 4.72, + -1.02 + ], + "max": [ + 0.68, + 5.72, + -1.02 + ] + } + }, + "Ruin": { + "mesh": "Ruin", + "triangles": 1038, + "vertices": 580, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Pale", + "LN_Metal_Team", + "LN_Crystal_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.2575, + -0.0653, + -2.5526 + ], + "max": [ + 1.9658, + 1.7462, + 1.3683 + ] + } + } + }, + "armatures": {}, + "empties": {}, + "bounds_unity": { + "min": [ + -2.2575, + -0.0653, + -2.5526 + ], + "max": [ + 1.9658, + 6.0601, + 1.3683 + ] + }, + "clips": [], + "expected_from_godot": { + "triangles": 6516, + "bounds_godot": { + "min": [ + -1.3717, + 0.0, + -1.3735 + ], + "max": [ + 1.3752, + 6.0601, + 1.3678 + ] + }, + "resource_path": "res://assets/luneraria/g2/grenzwacht.glb" + }, + "meshes_without_uv": [ + "Crystal", + "Debris" + ], + "triangles": 6516, + "fbx": "Assets/Luneraria/Art/Buildings/grenzwacht.fbx", + "fbx_bytes": 457404, + "ok": true +} diff --git a/Assets/Luneraria/Art/Buildings/grenzwacht.export.json.meta b/Assets/Luneraria/Art/Buildings/grenzwacht.export.json.meta new file mode 100644 index 0000000..9e34c26 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/grenzwacht.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 81cb37d5386d048999e1ca915d0cb88d +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/grenzwacht.fbx b/Assets/Luneraria/Art/Buildings/grenzwacht.fbx new file mode 100644 index 0000000..28f4d9e Binary files /dev/null and b/Assets/Luneraria/Art/Buildings/grenzwacht.fbx differ diff --git a/Assets/Luneraria/Art/Buildings/grenzwacht.fbx.meta b/Assets/Luneraria/Art/Buildings/grenzwacht.fbx.meta new file mode 100644 index 0000000..41b7961 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/grenzwacht.fbx.meta @@ -0,0 +1,111 @@ +fileFormatVersion: 2 +guid: 5b76880584cb448b5b6c8a5f93db8b54 +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 0 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 0 + humanoidOversampling: 1 + avatarSetup: 0 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/kernwacht.export.json b/Assets/Luneraria/Art/Buildings/kernwacht.export.json new file mode 100644 index 0000000..e094fb2 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/kernwacht.export.json @@ -0,0 +1,526 @@ +{ + "id": "kernwacht", + "group": "Buildings", + "source": "assets-source/luneraria/g2/kernwacht.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['Banner_L', 'Banner_R', 'Crystal', 'Debris', 'Lower', 'Ring', 'Ruin', 'Upper', 'Upper_Damaged']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "triangles_match_godot", + "ok": true, + "detail": "9224 fbx / 9224 godot" + }, + { + "check": "mesh_names_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "materials_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_match_godot", + "ok": true, + "detail": "largest difference 0.00000 m" + }, + { + "check": "no_armature", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "9224 / 9224" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + } + ], + "source_sha256": "2797f6f7b705a99333dbfdfce029a2f4894a74d2fb7939eb108ab2eaf7edd09e", + "removed_modifiers": 0, + "kind": "static", + "fps": 30.0, + "objects": 9, + "meshes": { + "Lower": { + "mesh": "Lower", + "triangles": 548, + "vertices": 304, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Pale", + "LN_Rune_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.8139, + 0.0, + -1.8017 + ], + "max": [ + 1.8045, + 2.76, + 1.806 + ] + } + }, + "Upper": { + "mesh": "Upper", + "triangles": 3280, + "vertices": 1660, + "ngons": 0, + "materials": [ + "LN_Metal_Team", + "LN_Crystal_Team", + "LN_Stone_Pale", + "LN_Metal_Iron" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.6442, + 2.5345, + -1.0915 + ], + "max": [ + 1.6442, + 8.33, + 1.734 + ] + } + }, + "Upper_Damaged": { + "mesh": "Upper_Damaged", + "triangles": 3280, + "vertices": 1660, + "ngons": 0, + "materials": [ + "LN_Metal_Team", + "LN_Crystal_Team", + "LN_Stone_Pale", + "LN_Metal_Iron" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.6442, + 2.5345, + -1.0915 + ], + "max": [ + 1.6442, + 8.33, + 1.734 + ] + } + }, + "Debris": { + "mesh": "Debris", + "triangles": 160, + "vertices": 96, + "ngons": 0, + "materials": [ + "LN_Stone_Pale" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.1991, + -0.0421, + -1.8567 + ], + "max": [ + 1.8296, + 0.2606, + 0.2916 + ] + } + }, + "Crystal": { + "mesh": "Crystal", + "triangles": 24, + "vertices": 14, + "ngons": 0, + "materials": [ + "LN_Crystal_Team" + ], + "uv_layers": [], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5554, + 4.51, + -0.4884 + ], + "max": [ + 0.5682, + 6.25, + 0.5124 + ] + } + }, + "Ring": { + "mesh": "Ring", + "triangles": 640, + "vertices": 320, + "ngons": 0, + "materials": [ + "LN_Metal_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.03, + 5.195, + -1.03 + ], + "max": [ + 1.03, + 5.305, + 1.03 + ] + } + }, + "Banner_L": { + "mesh": "Banner_L", + "triangles": 80, + "vertices": 55, + "ngons": 0, + "materials": [ + "LN_Cloth_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 1.5597, + 3.9, + -1.2585 + ], + "max": [ + 1.8697, + 5.5, + -0.7215 + ] + } + }, + "Banner_R": { + "mesh": "Banner_R", + "triangles": 80, + "vertices": 55, + "ngons": 0, + "materials": [ + "LN_Cloth_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.8697, + 3.9, + -1.2585 + ], + "max": [ + -1.5597, + 5.5, + -0.7215 + ] + } + }, + "Ruin": { + "mesh": "Ruin", + "triangles": 1132, + "vertices": 632, + "ngons": 0, + "materials": [ + "LN_Stone_Dark", + "LN_Stone_Pale", + "LN_Rune_Team", + "LN_Crystal_Team" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -6.0762, + -2.3959, + -2.1939 + ], + "max": [ + 2.3962, + 2.0939, + 1.8126 + ] + } + } + }, + "armatures": {}, + "empties": {}, + "bounds_unity": { + "min": [ + -6.0762, + -2.3959, + -2.1939 + ], + "max": [ + 2.3962, + 8.33, + 1.8126 + ] + }, + "clips": [], + "expected_from_godot": { + "triangles": 9224, + "bounds_godot": { + "min": [ + -1.8045, + 0.0, + -1.8017 + ], + "max": [ + 1.8139, + 8.33, + 1.806 + ] + }, + "resource_path": "res://assets/luneraria/g2/kernwacht.glb" + }, + "meshes_without_uv": [ + "Crystal", + "Debris" + ], + "triangles": 9224, + "fbx": "Assets/Luneraria/Art/Buildings/kernwacht.fbx", + "fbx_bytes": 732684, + "ok": true +} diff --git a/Assets/Luneraria/Art/Buildings/kernwacht.export.json.meta b/Assets/Luneraria/Art/Buildings/kernwacht.export.json.meta new file mode 100644 index 0000000..9a2f870 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/kernwacht.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5dc29c90a350446e480591bab7513b23 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Buildings/kernwacht.fbx b/Assets/Luneraria/Art/Buildings/kernwacht.fbx new file mode 100644 index 0000000..b828974 Binary files /dev/null and b/Assets/Luneraria/Art/Buildings/kernwacht.fbx differ diff --git a/Assets/Luneraria/Art/Buildings/kernwacht.fbx.meta b/Assets/Luneraria/Art/Buildings/kernwacht.fbx.meta new file mode 100644 index 0000000..0b512b7 --- /dev/null +++ b/Assets/Luneraria/Art/Buildings/kernwacht.fbx.meta @@ -0,0 +1,111 @@ +fileFormatVersion: 2 +guid: 2d354ddf8728c467da524d4c540efccd +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 0 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 0 + humanoidOversampling: 1 + avatarSetup: 0 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Characters.meta b/Assets/Luneraria/Art/Characters.meta new file mode 100644 index 0000000..4297995 --- /dev/null +++ b/Assets/Luneraria/Art/Characters.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f870578f70b3a45ccbfa68cceccd2579 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Characters/funkenlanze.export.json b/Assets/Luneraria/Art/Characters/funkenlanze.export.json new file mode 100644 index 0000000..c757004 --- /dev/null +++ b/Assets/Luneraria/Art/Characters/funkenlanze.export.json @@ -0,0 +1,405 @@ +{ + "id": "funkenlanze", + "group": "Characters", + "source": "assets-source/phase18/funkenlanze.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['FunkenBody']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "triangles_match_godot", + "ok": true, + "detail": "24036 fbx / 24036 godot" + }, + { + "check": "mesh_names_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_match_godot", + "ok": true, + "detail": "largest difference 0.00005 m" + }, + { + "check": "one_armature", + "ok": true, + "detail": "['FunkenRig']" + }, + { + "check": "single_root_bone", + "ok": true, + "detail": "['Root']" + }, + { + "check": "root_bone_name", + "ok": true, + "detail": "['Root']" + }, + { + "check": "bone_count_match_godot", + "ok": true, + "detail": "26 / 26" + }, + { + "check": "bone_names_portable", + "ok": true, + "detail": "[]" + }, + { + "check": "skinned_meshes_present", + "ok": true, + "detail": "" + }, + { + "check": "clips_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "required_clips_present", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "24036 / 24036" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_bones", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_clips", + "ok": true, + "detail": "['ability', 'attack_a', 'attack_b', 'death', 'hit', 'idle', 'start', 'stop', 'walk']" + } + ], + "source_sha256": "e21714e04a93f6266aae2edbf7db69c25d33b00429ebf62c01c6f832e18a771f", + "removed_modifiers": 0, + "joined_parts": 104, + "kind": "skinned", + "fps": 30.0, + "objects": 2, + "meshes": { + "FunkenBody": { + "mesh": "FunkenBody", + "triangles": 24036, + "vertices": 12226, + "ngons": 0, + "materials": [ + "FL_Basalt", + "FL_BurnishedBronze", + "FL_Obsidian", + "FL_Ember", + "FL_Joint", + "FL_BronzeEdge", + "FL_Iron", + "FL_Crystal" + ], + "uv_layers": [ + "UVMap" + ], + "color_attributes": [ + "SurfaceColor" + ], + "active_color": "SurfaceColor", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": true, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5652, + -0.0104, + -0.2945 + ], + "max": [ + 0.43, + 2.0212, + 1.435 + ] + } + } + }, + "armatures": { + "FunkenRig": { + "bones": [ + "Root", + "Pelvis", + "Spine", + "Chest", + "Neck", + "Head", + "Clavicle.L", + "UpperArm.L", + "Forearm.L", + "Hand.L", + "Index.L", + "Clavicle.R", + "UpperArm.R", + "Forearm.R", + "Hand.R", + "Index.R", + "Weapon", + "Bolt", + "Crystal", + "Chamber", + "Thigh.L", + "Shin.L", + "Foot.L", + "Thigh.R", + "Shin.R", + "Foot.R" + ], + "roots": [ + "Root" + ] + } + }, + "empties": {}, + "bounds_unity": { + "min": [ + -0.5652, + -0.0104, + -0.2945 + ], + "max": [ + 0.43, + 2.0212, + 1.435 + ] + }, + "clips": [ + { + "name": "ability", + "frames": [ + 0.0, + 39.0 + ], + "seconds": 1.3, + "loop": false, + "contact_seconds": 0.9 + }, + { + "name": "attack_a", + "frames": [ + 0.0, + 39.0 + ], + "seconds": 1.3, + "loop": false, + "contact_seconds": 0.9 + }, + { + "name": "attack_b", + "frames": [ + 0.0, + 39.0 + ], + "seconds": 1.3, + "loop": false, + "contact_seconds": 0.9 + }, + { + "name": "death", + "frames": [ + 0.0, + 60.0 + ], + "seconds": 2.0, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "hit", + "frames": [ + 0.0, + 15.0 + ], + "seconds": 0.5, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "idle", + "frames": [ + 0.0, + 90.0 + ], + "seconds": 3.0, + "loop": true, + "contact_seconds": -1.0 + }, + { + "name": "start", + "frames": [ + 0.0, + 12.0 + ], + "seconds": 0.4, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "stop", + "frames": [ + 0.0, + 12.0 + ], + "seconds": 0.4, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "walk", + "frames": [ + 0.0, + 36.0 + ], + "seconds": 1.2, + "loop": true, + "contact_seconds": -1.0 + } + ], + "expected_from_godot": { + "triangles": 24036, + "bounds_godot": { + "min": [ + -0.4300000071525574, + -0.010409347712993622, + -0.2945486903190613 + ], + "max": [ + 0.5651692152023315, + 2.021195411682129, + 1.4350000619888306 + ] + }, + "bones": 26, + "clips": [ + "idle", + "start", + "walk", + "stop", + "attack_a", + "attack_b", + "hit", + "ability", + "death" + ], + "resource_path": "res://assets/characters/funkenlanze.glb" + }, + "meshes_without_uv": [], + "triangles": 24036, + "fbx": "Assets/Luneraria/Art/Characters/funkenlanze.fbx", + "fbx_bytes": 3675308, + "ok": true +} diff --git a/Assets/Luneraria/Art/Characters/funkenlanze.export.json.meta b/Assets/Luneraria/Art/Characters/funkenlanze.export.json.meta new file mode 100644 index 0000000..cfd8e1d --- /dev/null +++ b/Assets/Luneraria/Art/Characters/funkenlanze.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 373bb56c33f234adeac31c870ede9072 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Characters/funkenlanze.fbx b/Assets/Luneraria/Art/Characters/funkenlanze.fbx new file mode 100644 index 0000000..0179b07 Binary files /dev/null and b/Assets/Luneraria/Art/Characters/funkenlanze.fbx differ diff --git a/Assets/Luneraria/Art/Characters/funkenlanze.fbx.meta b/Assets/Luneraria/Art/Characters/funkenlanze.fbx.meta new file mode 100644 index 0000000..6cd96b0 --- /dev/null +++ b/Assets/Luneraria/Art/Characters/funkenlanze.fbx.meta @@ -0,0 +1,393 @@ +fileFormatVersion: 2 +guid: 652ee682a82c34ff99c2eb11cd218f5e +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: + - serializedVersion: 16 + name: ability + takeName: FunkenRig|ability + internalID: -1787258805998246360 + firstFrame: 0 + lastFrame: 39 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: + - time: 0.6923077 + functionName: OnLuneContact + data: + objectReferenceParameter: {instanceID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: attack_a + takeName: FunkenRig|attack_a + internalID: -6628820121952251911 + firstFrame: 0 + lastFrame: 39 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: + - time: 0.6923077 + functionName: OnLuneContact + data: + objectReferenceParameter: {instanceID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: attack_b + takeName: FunkenRig|attack_b + internalID: -2963360793056117044 + firstFrame: 0 + lastFrame: 39 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: + - time: 0.6923077 + functionName: OnLuneContact + data: + objectReferenceParameter: {instanceID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: death + takeName: FunkenRig|death + internalID: 9159963757730041032 + firstFrame: 0 + lastFrame: 60 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: hit + takeName: FunkenRig|hit + internalID: -4707179913997139171 + firstFrame: 0 + lastFrame: 15 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: idle + takeName: FunkenRig|idle + internalID: -1348917559068937310 + firstFrame: 0 + lastFrame: 90 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 1 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: start + takeName: FunkenRig|start + internalID: 6150794267048699607 + firstFrame: 0 + lastFrame: 12 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: stop + takeName: FunkenRig|stop + internalID: 637536857275861776 + firstFrame: 0 + lastFrame: 12 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: walk + takeName: FunkenRig|walk + internalID: 7607972658950073716 + firstFrame: 0 + lastFrame: 36 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 1 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 1 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 2 + humanoidOversampling: 1 + avatarSetup: 1 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Characters/schlundkrone.export.json b/Assets/Luneraria/Art/Characters/schlundkrone.export.json new file mode 100644 index 0000000..e4d4ae1 --- /dev/null +++ b/Assets/Luneraria/Art/Characters/schlundkrone.export.json @@ -0,0 +1,431 @@ +{ + "id": "schlundkrone", + "group": "Characters", + "source": "assets-source/luneraria/g2/schlundkrone.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['SchlundkroneBody']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "triangles_match_godot", + "ok": true, + "detail": "5712 fbx / 5712 godot" + }, + { + "check": "materials_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_match_godot", + "ok": true, + "detail": "largest difference 0.00000 m" + }, + { + "check": "one_armature", + "ok": true, + "detail": "['SchlundkroneRig']" + }, + { + "check": "single_root_bone", + "ok": true, + "detail": "['Root']" + }, + { + "check": "root_bone_name", + "ok": true, + "detail": "['Root']" + }, + { + "check": "bone_names_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "bone_count_match_godot", + "ok": true, + "detail": "24 / 24" + }, + { + "check": "bone_names_portable", + "ok": true, + "detail": "[]" + }, + { + "check": "skinned_meshes_present", + "ok": true, + "detail": "" + }, + { + "check": "clips_match_godot", + "ok": true, + "detail": "[]" + }, + { + "check": "required_clips_present", + "ok": true, + "detail": "[]" + }, + { + "check": "clip_lengths_match_godot", + "ok": true, + "detail": "largest difference 0.0000 s" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "5712 / 5712" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_bones", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_clips", + "ok": true, + "detail": "['ability', 'attack_a', 'attack_b', 'death', 'hit', 'idle', 'roar', 'start', 'stop', 'victory', 'walk']" + } + ], + "source_sha256": "21f116f3ccf293b7f4c86bd23c07f86a41bd5d29c032f28bdb5c44043e9c6d7b", + "removed_modifiers": 0, + "kind": "skinned", + "fps": 30.0, + "objects": 2, + "meshes": { + "SchlundkroneBody": { + "mesh": "SchlundkroneBody", + "triangles": 5712, + "vertices": 3048, + "ngons": 0, + "materials": [ + "LN_Boss_Hide", + "LN_Boss_Bone", + "LN_Crystal_Boss", + "LN_Boss_Bronze" + ], + "uv_layers": [ + "UVMap", + "UVRest" + ], + "color_attributes": [ + "Col" + ], + "active_color": "Col", + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": true, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.3273, + 0.0053, + -0.5532 + ], + "max": [ + 1.2307, + 3.3182, + 0.9253 + ] + } + } + }, + "armatures": { + "SchlundkroneRig": { + "bones": [ + "Root", + "Hips", + "Spine", + "Chest", + "Neck", + "Head", + "Jaw", + "Crown", + "Maw.L", + "Shoulder.L", + "UpperArm.L", + "Forearm.L", + "Hand.L", + "Maw.R", + "Shoulder.R", + "UpperArm.R", + "Forearm.R", + "Hand.R", + "Thigh.L", + "Shin.L", + "Foot.L", + "Thigh.R", + "Shin.R", + "Foot.R" + ], + "roots": [ + "Root" + ] + } + }, + "empties": {}, + "bounds_unity": { + "min": [ + -1.3273, + 0.0053, + -0.5532 + ], + "max": [ + 1.2307, + 3.3182, + 0.9253 + ] + }, + "clips": [ + { + "name": "ability", + "frames": [ + 0.0, + 39.0 + ], + "seconds": 1.3, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "attack_a", + "frames": [ + 0.0, + 39.0 + ], + "seconds": 1.3, + "loop": false, + "contact_seconds": 0.9 + }, + { + "name": "attack_b", + "frames": [ + 0.0, + 39.0 + ], + "seconds": 1.3, + "loop": false, + "contact_seconds": 0.9 + }, + { + "name": "death", + "frames": [ + 0.0, + 66.0 + ], + "seconds": 2.2, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "hit", + "frames": [ + 0.0, + 15.0 + ], + "seconds": 0.5, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "idle", + "frames": [ + 0.0, + 90.0 + ], + "seconds": 3.0, + "loop": true, + "contact_seconds": -1.0 + }, + { + "name": "roar", + "frames": [ + 0.0, + 60.0 + ], + "seconds": 2.0, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "start", + "frames": [ + 0.0, + 12.0 + ], + "seconds": 0.4, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "stop", + "frames": [ + 0.0, + 12.0 + ], + "seconds": 0.4, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "victory", + "frames": [ + 0.0, + 60.0 + ], + "seconds": 2.0, + "loop": false, + "contact_seconds": -1.0 + }, + { + "name": "walk", + "frames": [ + 0.0, + 48.0 + ], + "seconds": 1.6, + "loop": true, + "contact_seconds": -1.0 + } + ], + "expected_from_godot": { + "triangles": 5712, + "bounds_godot": { + "min": [ + -1.2307, + 0.0053, + -0.5532 + ], + "max": [ + 1.3273, + 3.3182, + 0.9253 + ] + }, + "bones": 24, + "clips": [ + "ability", + "attack_a", + "attack_b", + "death", + "hit", + "idle", + "roar", + "start", + "stop", + "victory", + "walk" + ], + "resource_path": "res://assets/luneraria/g2/schlundkrone.glb" + }, + "meshes_without_uv": [], + "triangles": 5712, + "fbx": "Assets/Luneraria/Art/Characters/schlundkrone.fbx", + "fbx_bytes": 2838956, + "ok": true +} diff --git a/Assets/Luneraria/Art/Characters/schlundkrone.export.json.meta b/Assets/Luneraria/Art/Characters/schlundkrone.export.json.meta new file mode 100644 index 0000000..90df0b1 --- /dev/null +++ b/Assets/Luneraria/Art/Characters/schlundkrone.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 96a195571f91340e5b420cd273a91231 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Characters/schlundkrone.fbx b/Assets/Luneraria/Art/Characters/schlundkrone.fbx new file mode 100644 index 0000000..d61b17e Binary files /dev/null and b/Assets/Luneraria/Art/Characters/schlundkrone.fbx differ diff --git a/Assets/Luneraria/Art/Characters/schlundkrone.fbx.meta b/Assets/Luneraria/Art/Characters/schlundkrone.fbx.meta new file mode 100644 index 0000000..db29389 --- /dev/null +++ b/Assets/Luneraria/Art/Characters/schlundkrone.fbx.meta @@ -0,0 +1,444 @@ +fileFormatVersion: 2 +guid: b2dd57798499c4b7b8698ee56e676c45 +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: + - serializedVersion: 16 + name: ability + takeName: SchlundkroneRig|ability + internalID: 8816013596772264376 + firstFrame: 0 + lastFrame: 39 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: attack_a + takeName: SchlundkroneRig|attack_a + internalID: -3581854836903996656 + firstFrame: 0 + lastFrame: 39 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: + - time: 0.6923077 + functionName: OnLuneContact + data: + objectReferenceParameter: {instanceID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: attack_b + takeName: SchlundkroneRig|attack_b + internalID: 7137080732755112609 + firstFrame: 0 + lastFrame: 39 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: + - time: 0.6923077 + functionName: OnLuneContact + data: + objectReferenceParameter: {instanceID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: death + takeName: SchlundkroneRig|death + internalID: 3223440528613674463 + firstFrame: 0 + lastFrame: 66 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: hit + takeName: SchlundkroneRig|hit + internalID: -1153443838369333364 + firstFrame: 0 + lastFrame: 15 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: idle + takeName: SchlundkroneRig|idle + internalID: 2159908019584541609 + firstFrame: 0 + lastFrame: 90 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 1 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: roar + takeName: SchlundkroneRig|roar + internalID: 1662885906025357955 + firstFrame: 0 + lastFrame: 60 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: start + takeName: SchlundkroneRig|start + internalID: -8546801627699338383 + firstFrame: 0 + lastFrame: 12 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: stop + takeName: SchlundkroneRig|stop + internalID: 8440139490132052637 + firstFrame: 0 + lastFrame: 12 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: victory + takeName: SchlundkroneRig|victory + internalID: 7279649719363434968 + firstFrame: 0 + lastFrame: 60 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + - serializedVersion: 16 + name: walk + takeName: SchlundkroneRig|walk + internalID: -395723189595340628 + firstFrame: 0 + lastFrame: 48 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 1 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 1 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 2 + humanoidOversampling: 1 + avatarSetup: 1 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Environment.meta b/Assets/Luneraria/Art/Environment.meta new file mode 100644 index 0000000..2f4ad10 --- /dev/null +++ b/Assets/Luneraria/Art/Environment.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2cf6ff2112f7d4fd5bcff4710800659a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Environment/map_props.export.json b/Assets/Luneraria/Art/Environment/map_props.export.json new file mode 100644 index 0000000..50b038f --- /dev/null +++ b/Assets/Luneraria/Art/Environment/map_props.export.json @@ -0,0 +1,684 @@ +{ + "id": "map_props", + "group": "Environment", + "source": "assets-source/luneraria/map_props.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['Banner', 'Bridge', 'Curb', 'EdgeCliff', 'Oak_0', 'Oak_1', 'Oak_2', 'Pine_0', 'Pine_1', 'Pine_2', 'Rock_0', 'Rock_1', 'Rock_2', 'Shrub_0', 'Shrub_1']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "no_armature", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "7338 / 7338" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + } + ], + "source_sha256": "e2e723fc53da0d4bb686800ddba36ebebe7708e0944c32a81fd6d9c159e30e68", + "removed_modifiers": 0, + "kind": "static", + "fps": 24.0, + "objects": 15, + "meshes": { + "Bridge": { + "mesh": "Deck_0", + "triangles": 1088, + "vertices": 656, + "ngons": 0, + "materials": [ + "ENV_paving", + "ENV_limestone", + "ENV_brass" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -5.515, + -1.3, + -3.9 + ], + "max": [ + 5.515, + 1.46, + 3.9 + ] + } + }, + "Curb": { + "mesh": "Curb", + "triangles": 12, + "vertices": 8, + "ngons": 0, + "materials": [ + "ENV_limestone" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.65, + -0.01, + -0.21 + ], + "max": [ + 0.65, + 0.25, + 0.21 + ] + } + }, + "Pine_0": { + "mesh": "Trunk", + "triangles": 358, + "vertices": 191, + "ngons": 0, + "materials": [ + "ENV_bark", + "ENV_leaf_dark", + "ENV_leaf_mid" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.411, + 0.0, + -1.3761 + ], + "max": [ + 1.2882, + 4.332, + 1.3462 + ] + } + }, + "Pine_1": { + "mesh": "Trunk.001", + "triangles": 358, + "vertices": 191, + "ngons": 0, + "materials": [ + "ENV_bark", + "ENV_leaf_dark", + "ENV_leaf_mid" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.4442, + 0.0, + -1.4865 + ], + "max": [ + 1.434, + 5.244, + 1.3943 + ] + } + }, + "Pine_2": { + "mesh": "Trunk.002", + "triangles": 358, + "vertices": 191, + "ngons": 0, + "materials": [ + "ENV_bark", + "ENV_leaf_dark", + "ENV_leaf_mid" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.5452, + 0.0, + -1.5182 + ], + "max": [ + 1.4493, + 3.648, + 1.5733 + ] + } + }, + "Oak_0": { + "mesh": "Trunk.003", + "triangles": 1270, + "vertices": 669, + "ngons": 0, + "materials": [ + "ENV_bark", + "ENV_leaf_mid", + "ENV_leaf_light", + "ENV_leaf_dark" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.7039, + -0.0306, + -1.8912 + ], + "max": [ + 1.373, + 4.02, + 1.5742 + ] + } + }, + "Oak_1": { + "mesh": "Trunk.004", + "triangles": 1270, + "vertices": 669, + "ngons": 0, + "materials": [ + "ENV_bark", + "ENV_leaf_mid", + "ENV_leaf_light", + "ENV_leaf_dark" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.7964, + -0.0255, + -1.5792 + ], + "max": [ + 1.5389, + 4.6442, + 1.6028 + ] + } + }, + "Oak_2": { + "mesh": "Trunk.005", + "triangles": 1270, + "vertices": 669, + "ngons": 0, + "materials": [ + "ENV_bark", + "ENV_leaf_mid", + "ENV_leaf_light", + "ENV_leaf_dark" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.7448, + -0.0387, + -1.4185 + ], + "max": [ + 1.6053, + 3.4947, + 1.7902 + ] + } + }, + "Rock_0": { + "mesh": "Rock", + "triangles": 140, + "vertices": 78, + "ngons": 0, + "materials": [ + "ENV_cliff", + "ENV_leaf_dark", + "ENV_limestone" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.7155, + -0.04, + -1.0953 + ], + "max": [ + 1.0683, + 1.0416, + 1.0294 + ] + } + }, + "Rock_1": { + "mesh": "Rock.001", + "triangles": 140, + "vertices": 78, + "ngons": 0, + "materials": [ + "ENV_cliff", + "ENV_leaf_dark", + "ENV_limestone" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -2.4291, + -0.055, + -1.4554 + ], + "max": [ + 1.8589, + 1.5017, + 1.32 + ] + } + }, + "Rock_2": { + "mesh": "Rock.002", + "triangles": 140, + "vertices": 78, + "ngons": 0, + "materials": [ + "ENV_cliff", + "ENV_leaf_dark", + "ENV_limestone" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.2032, + -0.025, + -0.7362 + ], + "max": [ + 0.776, + 0.6172, + 0.7375 + ] + } + }, + "Shrub_0": { + "mesh": "Shrub", + "triangles": 80, + "vertices": 42, + "ngons": 0, + "materials": [ + "ENV_leaf_mid" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.813, + 0.135, + -0.8861 + ], + "max": [ + 0.7211, + 0.8205, + 0.7093 + ] + } + }, + "Shrub_1": { + "mesh": "Shrub.001", + "triangles": 80, + "vertices": 42, + "ngons": 0, + "materials": [ + "ENV_leaf_dark" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.0772, + 0.135, + -0.8513 + ], + "max": [ + 0.9518, + 0.9641, + 0.8895 + ] + } + }, + "Banner": { + "mesh": "Pole", + "triangles": 74, + "vertices": 48, + "ngons": 0, + "materials": [ + "ENV_brass", + "PR_Banner" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -1.13, + 0.0, + -0.0866 + ], + "max": [ + 0.1, + 4.5, + 0.0866 + ] + } + }, + "EdgeCliff": { + "mesh": "Block_0", + "triangles": 700, + "vertices": 378, + "ngons": 0, + "materials": [ + "ENV_cliff", + "ENV_leaf_mid" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": false, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -7.3684, + 0.4308, + -2.0375 + ], + "max": [ + 7.4555, + 4.1121, + 1.9761 + ] + } + } + }, + "armatures": {}, + "empties": {}, + "bounds_unity": { + "min": [ + -7.3684, + -1.3, + -3.9 + ], + "max": [ + 7.4555, + 5.244, + 3.9 + ] + }, + "clips": [], + "expected_from_godot": {}, + "meshes_without_uv": [ + "Banner", + "Bridge", + "Curb", + "EdgeCliff", + "Oak_0", + "Oak_1", + "Oak_2", + "Pine_0", + "Pine_1", + "Pine_2", + "Rock_0", + "Rock_1", + "Rock_2", + "Shrub_0", + "Shrub_1" + ], + "triangles": 7338, + "fbx": "Assets/Luneraria/Art/Environment/map_props.fbx", + "fbx_bytes": 236284, + "ok": true +} diff --git a/Assets/Luneraria/Art/Environment/map_props.export.json.meta b/Assets/Luneraria/Art/Environment/map_props.export.json.meta new file mode 100644 index 0000000..a05398e --- /dev/null +++ b/Assets/Luneraria/Art/Environment/map_props.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 712d173cb82314d19a6d0689762cb0ef +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Environment/map_props.fbx b/Assets/Luneraria/Art/Environment/map_props.fbx new file mode 100644 index 0000000..9d10bb2 Binary files /dev/null and b/Assets/Luneraria/Art/Environment/map_props.fbx differ diff --git a/Assets/Luneraria/Art/Environment/map_props.fbx.meta b/Assets/Luneraria/Art/Environment/map_props.fbx.meta new file mode 100644 index 0000000..a02ef2c --- /dev/null +++ b/Assets/Luneraria/Art/Environment/map_props.fbx.meta @@ -0,0 +1,111 @@ +fileFormatVersion: 2 +guid: 9a6862867d0c9498892d42d256fbe886 +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 0 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 0 + humanoidOversampling: 1 + avatarSetup: 0 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Units.meta b/Assets/Luneraria/Art/Units.meta new file mode 100644 index 0000000..f565e1c --- /dev/null +++ b/Assets/Luneraria/Art/Units.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 01c1714cee0714bbe9b65e1e6009cd0c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Units/g01.export.json b/Assets/Luneraria/Art/Units/g01.export.json new file mode 100644 index 0000000..58c8cd9 --- /dev/null +++ b/Assets/Luneraria/Art/Units/g01.export.json @@ -0,0 +1,4747 @@ +{ + "id": "g01", + "group": "Units", + "source": "assets-source/phase4/blend/g01.blend", + "exporter_version": 5, + "blender": "5.2.2 LTS", + "fbx_settings": { + "use_selection": true, + "use_visible": false, + "use_active_collection": false, + "global_scale": 1.0, + "apply_unit_scale": true, + "apply_scale_options": "FBX_SCALE_UNITS", + "axis_forward": "Y", + "axis_up": "Z", + "bake_space_transform": false, + "object_types": [ + "ARMATURE", + "EMPTY", + "MESH" + ], + "use_mesh_modifiers": true, + "use_mesh_modifiers_render": true, + "mesh_smooth_type": "OFF", + "use_subsurf": false, + "use_mesh_edges": false, + "use_tspace": true, + "use_triangles": false, + "colors_type": "LINEAR", + "prioritize_active_color": true, + "use_custom_props": false, + "add_leaf_bones": false, + "primary_bone_axis": "Y", + "secondary_bone_axis": "X", + "use_armature_deform_only": true, + "armature_nodetype": "NULL", + "bake_anim": true, + "bake_anim_use_all_bones": true, + "bake_anim_use_nla_strips": false, + "bake_anim_use_all_actions": true, + "bake_anim_force_startend_keying": true, + "bake_anim_step": 1.0, + "bake_anim_simplify_factor": 0.0, + "path_mode": "STRIP", + "embed_textures": false, + "batch_mode": "OFF" + }, + "checks": [ + { + "check": "logical_names_unique", + "ok": true, + "detail": "[]" + }, + { + "check": "turn_applied", + "ok": true, + "detail": "[]" + }, + { + "check": "units_metric", + "ok": true, + "detail": "METRIC" + }, + { + "check": "unit_scale_1", + "ok": true, + "detail": "1.0" + }, + { + "check": "no_negative_scale", + "ok": true, + "detail": "{}" + }, + { + "check": "object_scale_1", + "ok": true, + "detail": "{}" + }, + { + "check": "mesh_names_unique", + "ok": true, + "detail": "['ArmL_Elbow', 'ArmL_ForearmArmor', 'ArmL_ForearmCore', 'ArmL_Knuckle0_Head', 'ArmL_Knuckle0_Seat', 'ArmL_Knuckle1_Head', 'ArmL_Knuckle1_Seat', 'ArmL_Knuckle2_Head', 'ArmL_Knuckle2_Seat', 'ArmL_Palm', 'ArmL_Shoulder', 'ArmL_ShoulderJoint', 'ArmL_ShoulderTrim', 'ArmL_UpperArmor', 'ArmL_UpperBand', 'ArmL_UpperBandRivet_Head', 'ArmL_UpperBandRivet_Seat', 'ArmL_UpperCore', 'ArmL_WristBand', 'ArmL_WristBandRivet_Head', 'ArmL_WristBandRivet_Seat', 'ArmR_Elbow', 'ArmR_ForearmArmor', 'ArmR_ForearmCore', 'ArmR_Knuckle0_Head', 'ArmR_Knuckle0_Seat', 'ArmR_Knuckle1_Head', 'ArmR_Knuckle1_Seat', 'ArmR_Knuckle2_Head', 'ArmR_Knuckle2_Seat', 'ArmR_Palm', 'ArmR_Shoulder', 'ArmR_ShoulderJoint', 'ArmR_ShoulderTrim', 'ArmR_UpperArmor', 'ArmR_UpperBand', 'ArmR_UpperBandRivet_Head', 'ArmR_UpperBandRivet_Seat', 'ArmR_UpperCore', 'ArmR_WristBand', 'ArmR_WristBandRivet_Head', 'ArmR_WristBandRivet_Seat', 'Body_DorsalSpine0', 'Body_DorsalSpine1', 'Body_DorsalSpine2', 'Body_LavaCore', 'Body_Shell0_0', 'Body_Shell0_1', 'Body_Shell0_2', 'Body_Shell0_3', 'Body_Shell1_0', 'Body_Shell1_1', 'Body_Shell1_2', 'Body_Shell1_3', 'Body_Shell2_0', 'Body_Shell2_1', 'Body_Shell2_2', 'Body_Shell2_3', 'Head_BrowL', 'Head_BrowR', 'Head_CheekL', 'Head_CheekR', 'Head_Chin', 'Head_EyeL', 'Head_EyeR', 'Head_JawCavity', 'Head_LowerToothL0', 'Head_LowerToothL1', 'Head_LowerToothL2', 'Head_LowerToothL3', 'Head_LowerToothR0', 'Head_LowerToothR1', 'Head_LowerToothR2', 'Head_LowerToothR3', 'Head_MouthEmber', 'Head_UpperToothL0', 'Head_UpperToothL1', 'Head_UpperToothL2', 'Head_UpperToothL3', 'Head_UpperToothR0', 'Head_UpperToothR1', 'Head_UpperToothR2', 'Head_UpperToothR3', 'LegL_AnkleCuff', 'LegL_AnklePin', 'LegL_AnklePivot', 'LegL_AnkleRim', 'LegL_HipPin', 'LegL_HipPivot', 'LegL_HipRim', 'LegL_InnerShin', 'LegL_InnerThigh', 'LegL_KneeGuard', 'LegL_KneePin', 'LegL_KneePivot', 'LegL_KneeRim', 'LegL_ShinArmor', 'LegL_ThighArmor', 'LegL_Toe0', 'LegL_Toe1', 'LegL_Toe2', 'LegL_ToeCap0', 'LegL_ToeCap1', 'LegL_ToeCap2', 'LegR_AnkleCuff', 'LegR_AnklePin', 'LegR_AnklePivot', 'LegR_AnkleRim', 'LegR_HipPin', 'LegR_HipPivot', 'LegR_HipRim', 'LegR_InnerShin', 'LegR_InnerThigh', 'LegR_KneeGuard', 'LegR_KneePin', 'LegR_KneePivot', 'LegR_KneeRim', 'LegR_ShinArmor', 'LegR_ThighArmor', 'LegR_Toe0', 'LegR_Toe1', 'LegR_Toe2', 'LegR_ToeCap0', 'LegR_ToeCap1', 'LegR_ToeCap2', 'WeaponL_Claw0', 'WeaponL_Claw1', 'WeaponL_Claw2', 'WeaponR_Claw0', 'WeaponR_Claw1', 'WeaponR_Claw2']" + }, + { + "check": "material_slots_filled", + "ok": true, + "detail": "{}" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangent_prerequisites", + "ok": true, + "detail": "{}" + }, + { + "check": "no_blend_shapes", + "ok": true, + "detail": "{}" + }, + { + "check": "triangles_match_godot", + "ok": true, + "detail": "79780 fbx / 79780 godot" + }, + { + "check": "bounds_match_godot", + "ok": true, + "detail": "largest difference 0.00004 m" + }, + { + "check": "no_armature", + "ok": true, + "detail": "[]" + }, + { + "check": "forward_marker_unity_plus_z", + "ok": true, + "detail": "[0.0, 0.0, 0.75]" + }, + { + "check": "roundtrip_mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "roundtrip_triangles", + "ok": true, + "detail": "79780 / 79780" + }, + { + "check": "roundtrip_materials", + "ok": true, + "detail": "[]" + } + ], + "source_sha256": "79baa9e4adfdf91730cdb7a79b0c8417e57ade2b546c49e0220a2999b4f3720e", + "removed_modifiers": 36, + "logical_names": { + "objects": 133, + "materials": 7, + "merged_materials": 0 + }, + "kind": "rigid", + "fps": 24.0, + "objects": 133, + "meshes": { + "LegL_InnerThigh": { + "mesh": "LegL_InnerThigh_Mesh.003", + "triangles": 236, + "vertices": 120, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1175, + 0.1604, + -0.1951 + ], + "max": [ + 0.3158, + 0.3757, + -0.0312 + ] + } + }, + "LegL_InnerShin": { + "mesh": "LegL_InnerShin_Mesh.003", + "triangles": 236, + "vertices": 120, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1606, + 0.0464, + -0.1631 + ], + "max": [ + 0.3209, + 0.2393, + 0.0235 + ] + } + }, + "LegL_ThighArmor": { + "mesh": "LegL_ThighArmor_Mesh.003", + "triangles": 598, + "vertices": 301, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.0676, + 0.1766, + -0.2207 + ], + "max": [ + 0.3693, + 0.3551, + -0.0019 + ] + } + }, + "LegL_ShinArmor": { + "mesh": "LegL_ShinArmor_Mesh.003", + "triangles": 566, + "vertices": 285, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.11, + 0.0595, + -0.1872 + ], + "max": [ + 0.3733, + 0.2269, + 0.0512 + ] + } + }, + "LegL_HipPivot": { + "mesh": "LegL_HipPivot_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1025, + 0.2662, + -0.0371 + ], + "max": [ + 0.2827, + 0.4464, + 0.0159 + ] + } + }, + "LegL_HipPin": { + "mesh": "LegL_HipPin_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1475, + 0.3112, + 0.0189 + ], + "max": [ + 0.2377, + 0.4014, + 0.0401 + ] + } + }, + "LegL_HipRim": { + "mesh": "LegL_HipRim_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1726, + 0.3363, + 0.0362 + ], + "max": [ + 0.2126, + 0.3763, + 0.0603 + ] + } + }, + "LegL_KneePivot": { + "mesh": "LegL_KneePivot_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1506, + 0.0897, + -0.0419 + ], + "max": [ + 0.3309, + 0.2699, + 0.0111 + ] + } + }, + "LegL_KneePin": { + "mesh": "LegL_KneePin_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1957, + 0.1347, + 0.0141 + ], + "max": [ + 0.2858, + 0.2248, + 0.0353 + ] + } + }, + "LegL_KneeRim": { + "mesh": "LegL_KneeRim_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.2207, + 0.1598, + 0.0314 + ], + "max": [ + 0.2608, + 0.1998, + 0.0555 + ] + } + }, + "LegL_AnklePivot": { + "mesh": "LegL_AnklePivot_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1506, + 0.0158, + 0.0496 + ], + "max": [ + 0.3309, + 0.1961, + 0.1026 + ] + } + }, + "LegL_AnklePin": { + "mesh": "LegL_AnklePin_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1957, + 0.0609, + 0.1056 + ], + "max": [ + 0.2858, + 0.151, + 0.1267 + ] + } + }, + "LegL_AnkleRim": { + "mesh": "LegL_AnkleRim_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.2207, + 0.0859, + 0.1229 + ], + "max": [ + 0.2608, + 0.126, + 0.147 + ] + } + }, + "LegL_Toe0": { + "mesh": "LegL_Toe0_Mesh.003", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.2798, + 0.0, + -0.0529 + ], + "max": [ + 0.3772, + 0.1254, + 0.1974 + ] + } + }, + "LegL_ToeCap0": { + "mesh": "LegL_ToeCap0_Mesh.003", + "triangles": 188, + "vertices": 96, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.2896, + 0.0299, + 0.1372 + ], + "max": [ + 0.3672, + 0.0761, + 0.1806 + ] + } + }, + "LegL_Toe1": { + "mesh": "LegL_Toe1_Mesh.003", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1922, + 0.0, + -0.0529 + ], + "max": [ + 0.2896, + 0.1254, + 0.1974 + ] + } + }, + "LegL_ToeCap1": { + "mesh": "LegL_ToeCap1_Mesh.003", + "triangles": 188, + "vertices": 96, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.2019, + 0.0299, + 0.1372 + ], + "max": [ + 0.2795, + 0.0761, + 0.1806 + ] + } + }, + "LegL_Toe2": { + "mesh": "LegL_Toe2_Mesh.003", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1046, + 0.0, + -0.0529 + ], + "max": [ + 0.2019, + 0.1254, + 0.1974 + ] + } + }, + "LegL_ToeCap2": { + "mesh": "LegL_ToeCap2_Mesh.003", + "triangles": 188, + "vertices": 96, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1143, + 0.0299, + 0.1372 + ], + "max": [ + 0.1919, + 0.0761, + 0.1806 + ] + } + }, + "LegL_AnkleCuff": { + "mesh": "LegL_AnkleCuff_Mesh.003", + "triangles": 188, + "vertices": 96, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.0749, + 0.1324, + -0.1155 + ], + "max": [ + 0.4066, + 0.195, + 0.0963 + ] + } + }, + "LegL_KneeGuard": { + "mesh": "LegL_KneeGuard_Mesh.002", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1456, + 0.0407, + 0.0053 + ], + "max": [ + 0.3358, + 0.2664, + 0.0775 + ] + } + }, + "LegR_InnerThigh": { + "mesh": "LegR_InnerThigh_Mesh.003", + "triangles": 236, + "vertices": 120, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3158, + 0.1604, + -0.1951 + ], + "max": [ + -0.1175, + 0.3757, + -0.0312 + ] + } + }, + "LegR_InnerShin": { + "mesh": "LegR_InnerShin_Mesh.003", + "triangles": 236, + "vertices": 120, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3209, + 0.0464, + -0.1631 + ], + "max": [ + -0.1606, + 0.2393, + 0.0235 + ] + } + }, + "LegR_ThighArmor": { + "mesh": "LegR_ThighArmor_Mesh.003", + "triangles": 608, + "vertices": 306, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3644, + 0.1794, + -0.2205 + ], + "max": [ + -0.07, + 0.3584, + -0.0068 + ] + } + }, + "LegR_ShinArmor": { + "mesh": "LegR_ShinArmor_Mesh.003", + "triangles": 604, + "vertices": 304, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.373, + 0.0566, + -0.1925 + ], + "max": [ + -0.1141, + 0.2247, + 0.0502 + ] + } + }, + "LegR_HipPivot": { + "mesh": "LegR_HipPivot_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2827, + 0.2662, + -0.0371 + ], + "max": [ + -0.1025, + 0.4464, + 0.0159 + ] + } + }, + "LegR_HipPin": { + "mesh": "LegR_HipPin_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2377, + 0.3112, + 0.0189 + ], + "max": [ + -0.1475, + 0.4014, + 0.0401 + ] + } + }, + "LegR_HipRim": { + "mesh": "LegR_HipRim_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2126, + 0.3363, + 0.0362 + ], + "max": [ + -0.1726, + 0.3763, + 0.0603 + ] + } + }, + "LegR_KneePivot": { + "mesh": "LegR_KneePivot_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3309, + 0.0897, + -0.0419 + ], + "max": [ + -0.1506, + 0.2699, + 0.0111 + ] + } + }, + "LegR_KneePin": { + "mesh": "LegR_KneePin_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2858, + 0.1347, + 0.0141 + ], + "max": [ + -0.1957, + 0.2248, + 0.0353 + ] + } + }, + "LegR_KneeRim": { + "mesh": "LegR_KneeRim_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2608, + 0.1598, + 0.0314 + ], + "max": [ + -0.2207, + 0.1998, + 0.0555 + ] + } + }, + "LegR_AnklePivot": { + "mesh": "LegR_AnklePivot_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3309, + 0.0158, + 0.0496 + ], + "max": [ + -0.1506, + 0.1961, + 0.1026 + ] + } + }, + "LegR_AnklePin": { + "mesh": "LegR_AnklePin_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2858, + 0.0609, + 0.1056 + ], + "max": [ + -0.1957, + 0.151, + 0.1267 + ] + } + }, + "LegR_AnkleRim": { + "mesh": "LegR_AnkleRim_Mesh.003", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2608, + 0.0859, + 0.1229 + ], + "max": [ + -0.2207, + 0.126, + 0.147 + ] + } + }, + "LegR_Toe0": { + "mesh": "LegR_Toe0_Mesh.003", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2016, + 0.0, + -0.0529 + ], + "max": [ + -0.1043, + 0.1254, + 0.1974 + ] + } + }, + "LegR_ToeCap0": { + "mesh": "LegR_ToeCap0_Mesh.003", + "triangles": 188, + "vertices": 96, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.1919, + 0.0299, + 0.1372 + ], + "max": [ + -0.1143, + 0.0761, + 0.1806 + ] + } + }, + "LegR_Toe1": { + "mesh": "LegR_Toe1_Mesh.003", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2893, + 0.0, + -0.0529 + ], + "max": [ + -0.1919, + 0.1254, + 0.1974 + ] + } + }, + "LegR_ToeCap1": { + "mesh": "LegR_ToeCap1_Mesh.003", + "triangles": 188, + "vertices": 96, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2795, + 0.0299, + 0.1372 + ], + "max": [ + -0.2019, + 0.0761, + 0.1806 + ] + } + }, + "LegR_Toe2": { + "mesh": "LegR_Toe2_Mesh.003", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3769, + 0.0, + -0.0529 + ], + "max": [ + -0.2795, + 0.1254, + 0.1974 + ] + } + }, + "LegR_ToeCap2": { + "mesh": "LegR_ToeCap2_Mesh.003", + "triangles": 188, + "vertices": 96, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3672, + 0.0299, + 0.1372 + ], + "max": [ + -0.2896, + 0.0761, + 0.1806 + ] + } + }, + "LegR_AnkleCuff": { + "mesh": "LegR_AnkleCuff_Mesh.003", + "triangles": 188, + "vertices": 96, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.4066, + 0.1324, + -0.1155 + ], + "max": [ + -0.0749, + 0.195, + 0.0963 + ] + } + }, + "LegR_KneeGuard": { + "mesh": "LegR_KneeGuard_Mesh.002", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3358, + 0.0407, + 0.0053 + ], + "max": [ + -0.1456, + 0.2664, + 0.0775 + ] + } + }, + "Body_LavaCore": { + "mesh": "Body_LavaCore_Mesh", + "triangles": 640, + "vertices": 322, + "ngons": 0, + "materials": [ + "SW_HD_ember" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3376, + 0.3469, + -0.3505 + ], + "max": [ + 0.3281, + 1.0792, + 0.1897 + ] + } + }, + "Body_Shell0_0": { + "mesh": "Body_Shell0_0_Mesh", + "triangles": 2102, + "vertices": 1053, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.496, + 0.3031, + -0.1857 + ], + "max": [ + -0.1452, + 0.6916, + 0.0664 + ] + } + }, + "Body_Shell0_1": { + "mesh": "Body_Shell0_1_Mesh", + "triangles": 2176, + "vertices": 1090, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3731, + 0.2946, + -0.3651 + ], + "max": [ + -0.0208, + 0.6829, + -0.1119 + ] + } + }, + "Body_Shell0_2": { + "mesh": "Body_Shell0_2_Mesh", + "triangles": 2240, + "vertices": 1122, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.0973, + 0.3007, + -0.421 + ], + "max": [ + 0.2432, + 0.6863, + -0.1458 + ] + } + }, + "Body_Shell0_3": { + "mesh": "Body_Shell0_3_Mesh", + "triangles": 572, + "vertices": 288, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1161, + 0.3095, + -0.2937 + ], + "max": [ + 0.4615, + 0.6787, + -0.0165 + ] + } + }, + "Body_Shell1_0": { + "mesh": "Body_Shell1_0_Mesh", + "triangles": 2400, + "vertices": 1202, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.4744, + 0.573, + -0.2493 + ], + "max": [ + -0.1448, + 0.9433, + 0.0411 + ] + } + }, + "Body_Shell1_1": { + "mesh": "Body_Shell1_1_Mesh", + "triangles": 2326, + "vertices": 1165, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3133, + 0.5835, + -0.412 + ], + "max": [ + 0.0207, + 0.9536, + -0.1224 + ] + } + }, + "Body_Shell1_2": { + "mesh": "Body_Shell1_2_Mesh", + "triangles": 2208, + "vertices": 1106, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.0395, + 0.5714, + -0.4174 + ], + "max": [ + 0.2917, + 0.9417, + -0.1248 + ] + } + }, + "Body_Shell1_3": { + "mesh": "Body_Shell1_3_Mesh", + "triangles": 2380, + "vertices": 1192, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1472, + 0.5796, + -0.2727 + ], + "max": [ + 0.4645, + 0.944, + 0.0397 + ] + } + }, + "Body_Shell2_0": { + "mesh": "Body_Shell2_0_Mesh", + "triangles": 536, + "vertices": 270, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.4753, + 0.8382, + -0.2121 + ], + "max": [ + -0.1601, + 1.1819, + 0.092 + ] + } + }, + "Body_Shell2_1": { + "mesh": "Body_Shell2_1_Mesh", + "triangles": 2296, + "vertices": 1150, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3569, + 0.8428, + -0.396 + ], + "max": [ + -0.0312, + 1.1824, + -0.078 + ] + } + }, + "Body_Shell2_2": { + "mesh": "Body_Shell2_2_Mesh", + "triangles": 2416, + "vertices": 1210, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.0943, + 0.8338, + -0.4473 + ], + "max": [ + 0.2269, + 1.1833, + -0.1234 + ] + } + }, + "Body_Shell2_3": { + "mesh": "Body_Shell2_3_Mesh", + "triangles": 2386, + "vertices": 1195, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1274, + 0.8394, + -0.3285 + ], + "max": [ + 0.4408, + 1.1802, + 0.0062 + ] + } + }, + "Head_JawCavity": { + "mesh": "Head_JawCavity_Mesh", + "triangles": 524, + "vertices": 264, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.3477, + 0.5094, + 0.0401 + ], + "max": [ + 0.3305, + 0.9505, + 0.3214 + ] + } + }, + "Head_MouthEmber": { + "mesh": "Head_MouthEmber_Mesh", + "triangles": 382, + "vertices": 193, + "ngons": 0, + "materials": [ + "SW_HD_ember" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2865, + 0.5888, + 0.261 + ], + "max": [ + 0.2865, + 0.8268, + 0.2879 + ] + } + }, + "Head_BrowL": { + "mesh": "Head_BrowL_Mesh", + "triangles": 2246, + "vertices": 1125, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.0105, + 0.8302, + 0.0358 + ], + "max": [ + 0.387, + 1.106, + 0.3514 + ] + } + }, + "Head_EyeL": { + "mesh": "Head_EyeL_Mesh.005", + "triangles": 108, + "vertices": 56, + "ngons": 0, + "materials": [ + "SW_HD_hot" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.0844, + 0.9082, + 0.3334 + ], + "max": [ + 0.2827, + 0.9741, + 0.3775 + ] + } + }, + "Head_CheekL": { + "mesh": "Head_CheekL_Mesh", + "triangles": 1936, + "vertices": 970, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1763, + 0.5808, + 0.0229 + ], + "max": [ + 0.4361, + 0.9661, + 0.3229 + ] + } + }, + "Head_UpperToothL0": { + "mesh": "Head_UpperToothL0_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.0193, + 0.7511, + 0.2092 + ], + "max": [ + 0.0867, + 0.9385, + 0.3587 + ] + } + }, + "Head_LowerToothL0": { + "mesh": "Head_LowerToothL0_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.0212, + 0.4668, + 0.1688 + ], + "max": [ + 0.0886, + 0.6741, + 0.3368 + ] + } + }, + "Head_UpperToothL1": { + "mesh": "Head_UpperToothL1_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.0481, + 0.7395, + 0.2091 + ], + "max": [ + 0.1541, + 0.923, + 0.3586 + ] + } + }, + "Head_LowerToothL1": { + "mesh": "Head_LowerToothL1_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.0462, + 0.4843, + 0.1702 + ], + "max": [ + 0.156, + 0.6837, + 0.3368 + ] + } + }, + "Head_UpperToothL2": { + "mesh": "Head_UpperToothL2_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1156, + 0.728, + 0.2091 + ], + "max": [ + 0.2215, + 0.9075, + 0.3585 + ] + } + }, + "Head_LowerToothL2": { + "mesh": "Head_LowerToothL2_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.1136, + 0.5017, + 0.1719 + ], + "max": [ + 0.2234, + 0.6933, + 0.3368 + ] + } + }, + "Head_UpperToothL3": { + "mesh": "Head_UpperToothL3_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.183, + 0.7164, + 0.209 + ], + "max": [ + 0.2889, + 0.892, + 0.3584 + ] + } + }, + "Head_LowerToothL3": { + "mesh": "Head_LowerToothL3_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.181, + 0.5189, + 0.1738 + ], + "max": [ + 0.2908, + 0.703, + 0.3368 + ] + } + }, + "ArmL_UpperCore": { + "mesh": "ArmL_UpperCore_Mesh.006", + "triangles": 236, + "vertices": 120, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3562, + 0.6473, + -0.1599 + ], + "max": [ + 0.5875, + 0.9512, + 0.0299 + ] + } + }, + "ArmL_ForearmCore": { + "mesh": "ArmL_ForearmCore_Mesh.006", + "triangles": 236, + "vertices": 120, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.4361, + 0.4329, + -0.1105 + ], + "max": [ + 0.6328, + 0.7226, + 0.1635 + ] + } + }, + "ArmL_Elbow": { + "mesh": "ArmL_Elbow_Mesh.006", + "triangles": 636, + "vertices": 320, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.4033, + 0.5551, + -0.1601 + ], + "max": [ + 0.6358, + 0.7902, + 0.0711 + ] + } + }, + "ArmL_UpperArmor": { + "mesh": "ArmL_UpperArmor_Mesh.006", + "triangles": 582, + "vertices": 293, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3357, + 0.6599, + -0.1808 + ], + "max": [ + 0.6069, + 0.937, + 0.0465 + ] + } + }, + "ArmL_ForearmArmor": { + "mesh": "ArmL_ForearmArmor_Mesh.006", + "triangles": 614, + "vertices": 309, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3821, + 0.4145, + -0.1098 + ], + "max": [ + 0.6842, + 0.734, + 0.1638 + ] + } + }, + "ArmL_Shoulder": { + "mesh": "ArmL_Shoulder_Mesh.006", + "triangles": 2546, + "vertices": 1275, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.2404, + 0.7736, + -0.2501 + ], + "max": [ + 0.607, + 1.0761, + 0.0816 + ] + } + }, + "ArmL_ShoulderJoint": { + "mesh": "ArmL_ShoulderJoint_Mesh.006", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3347, + 0.8355, + 0.0029 + ], + "max": [ + 0.5127, + 1.0134, + 0.053 + ] + } + }, + "ArmL_UpperBand": { + "mesh": "ArmL_UpperBand_Mesh.006", + "triangles": 284, + "vertices": 144, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3638, + 0.4323, + -0.1211 + ], + "max": [ + 0.7097, + 0.6924, + 0.1965 + ] + } + }, + "ArmL_UpperBandRivet_Seat": { + "mesh": "ArmL_UpperBandRivet_Seat_Mesh.006", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.5107, + 0.5364, + 0.2019 + ], + "max": [ + 0.5627, + 0.5884, + 0.2105 + ] + } + }, + "ArmL_UpperBandRivet_Head": { + "mesh": "ArmL_UpperBandRivet_Head_Mesh.006", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.5194, + 0.545, + 0.2062 + ], + "max": [ + 0.5541, + 0.5797, + 0.2235 + ] + } + }, + "ArmL_WristBand": { + "mesh": "ArmL_WristBand_Mesh.006", + "triangles": 284, + "vertices": 144, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3716, + 0.3803, + -0.0834 + ], + "max": [ + 0.7175, + 0.6404, + 0.2342 + ] + } + }, + "ArmL_WristBandRivet_Seat": { + "mesh": "ArmL_WristBandRivet_Seat_Mesh.006", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.5185, + 0.4844, + 0.2396 + ], + "max": [ + 0.5705, + 0.5364, + 0.2482 + ] + } + }, + "ArmL_WristBandRivet_Head": { + "mesh": "ArmL_WristBandRivet_Head_Mesh.006", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.5272, + 0.493, + 0.2439 + ], + "max": [ + 0.5619, + 0.5277, + 0.2612 + ] + } + }, + "ArmL_Palm": { + "mesh": "ArmL_Palm_Mesh.006", + "triangles": 558, + "vertices": 281, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.415, + 0.3443, + -0.0299 + ], + "max": [ + 0.6838, + 0.6169, + 0.2193 + ] + } + }, + "WeaponL_Claw0": { + "mesh": "WeaponL_Claw0_Mesh", + "triangles": 574, + "vertices": 289, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.6225, + 0.1541, + 0.0951 + ], + "max": [ + 0.7924, + 0.6199, + 0.4473 + ] + } + }, + "ArmL_Knuckle0_Seat": { + "mesh": "ArmL_Knuckle0_Seat_Mesh", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.663, + 0.5571, + 0.1979 + ], + "max": [ + 0.7237, + 0.6177, + 0.2066 + ] + } + }, + "ArmL_Knuckle0_Head": { + "mesh": "ArmL_Knuckle0_Head_Mesh", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.6731, + 0.5672, + 0.2022 + ], + "max": [ + 0.7135, + 0.6076, + 0.2196 + ] + } + }, + "WeaponL_Claw1": { + "mesh": "WeaponL_Claw1_Mesh", + "triangles": 574, + "vertices": 289, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.4877, + 0.1541, + 0.0951 + ], + "max": [ + 0.6576, + 0.6199, + 0.4473 + ] + } + }, + "ArmL_Knuckle1_Seat": { + "mesh": "ArmL_Knuckle1_Seat_Mesh", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.5282, + 0.5571, + 0.1979 + ], + "max": [ + 0.5888, + 0.6177, + 0.2066 + ] + } + }, + "ArmL_Knuckle1_Head": { + "mesh": "ArmL_Knuckle1_Head_Mesh", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.5383, + 0.5672, + 0.2022 + ], + "max": [ + 0.5787, + 0.6076, + 0.2196 + ] + } + }, + "WeaponL_Claw2": { + "mesh": "WeaponL_Claw2_Mesh", + "triangles": 574, + "vertices": 289, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3529, + 0.1541, + 0.0951 + ], + "max": [ + 0.5228, + 0.6199, + 0.4473 + ] + } + }, + "ArmL_Knuckle2_Seat": { + "mesh": "ArmL_Knuckle2_Seat_Mesh", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3934, + 0.5571, + 0.1979 + ], + "max": [ + 0.454, + 0.6177, + 0.2066 + ] + } + }, + "ArmL_Knuckle2_Head": { + "mesh": "ArmL_Knuckle2_Head_Mesh", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.4035, + 0.5672, + 0.2022 + ], + "max": [ + 0.4439, + 0.6076, + 0.2196 + ] + } + }, + "ArmL_ShoulderTrim": { + "mesh": "ArmL_ShoulderTrim_Mesh", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.3094, + 0.9119, + 0.0434 + ], + "max": [ + 0.4995, + 1.0641, + 0.0819 + ] + } + }, + "Head_BrowR": { + "mesh": "Head_BrowR_Mesh", + "triangles": 2302, + "vertices": 1153, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.381, + 0.8241, + 0.0243 + ], + "max": [ + 0.0183, + 1.1115, + 0.3586 + ] + } + }, + "Head_EyeR": { + "mesh": "Head_EyeR_Mesh.005", + "triangles": 108, + "vertices": 56, + "ngons": 0, + "materials": [ + "SW_HD_hot" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2827, + 0.9082, + 0.3334 + ], + "max": [ + -0.0844, + 0.9741, + 0.3775 + ] + } + }, + "Head_CheekR": { + "mesh": "Head_CheekR_Mesh", + "triangles": 2426, + "vertices": 1215, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.4589, + 0.5769, + 0.0446 + ], + "max": [ + -0.1508, + 0.9503, + 0.2989 + ] + } + }, + "Head_UpperToothR0": { + "mesh": "Head_UpperToothR0_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.0867, + 0.7511, + 0.2092 + ], + "max": [ + 0.0193, + 0.9385, + 0.3587 + ] + } + }, + "Head_LowerToothR0": { + "mesh": "Head_LowerToothR0_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.0886, + 0.4668, + 0.1688 + ], + "max": [ + 0.0212, + 0.6741, + 0.3368 + ] + } + }, + "Head_UpperToothR1": { + "mesh": "Head_UpperToothR1_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.1541, + 0.7395, + 0.2091 + ], + "max": [ + -0.0481, + 0.923, + 0.3586 + ] + } + }, + "Head_LowerToothR1": { + "mesh": "Head_LowerToothR1_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.156, + 0.4843, + 0.1702 + ], + "max": [ + -0.0462, + 0.6837, + 0.3368 + ] + } + }, + "Head_UpperToothR2": { + "mesh": "Head_UpperToothR2_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2215, + 0.728, + 0.2091 + ], + "max": [ + -0.1156, + 0.9075, + 0.3585 + ] + } + }, + "Head_LowerToothR2": { + "mesh": "Head_LowerToothR2_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2234, + 0.5017, + 0.1719 + ], + "max": [ + -0.1136, + 0.6933, + 0.3368 + ] + } + }, + "Head_UpperToothR3": { + "mesh": "Head_UpperToothR3_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_edge" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2889, + 0.7164, + 0.209 + ], + "max": [ + -0.183, + 0.892, + 0.3584 + ] + } + }, + "Head_LowerToothR3": { + "mesh": "Head_LowerToothR3_Mesh", + "triangles": 94, + "vertices": 49, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2908, + 0.5189, + 0.1738 + ], + "max": [ + -0.181, + 0.703, + 0.3368 + ] + } + }, + "ArmR_UpperCore": { + "mesh": "ArmR_UpperCore_Mesh.006", + "triangles": 236, + "vertices": 120, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5875, + 0.6473, + -0.1599 + ], + "max": [ + -0.3562, + 0.9512, + 0.0299 + ] + } + }, + "ArmR_ForearmCore": { + "mesh": "ArmR_ForearmCore_Mesh.006", + "triangles": 236, + "vertices": 120, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.6328, + 0.4329, + -0.1105 + ], + "max": [ + -0.4361, + 0.7226, + 0.1635 + ] + } + }, + "ArmR_Elbow": { + "mesh": "ArmR_Elbow_Mesh.006", + "triangles": 570, + "vertices": 287, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.6355, + 0.5591, + -0.1548 + ], + "max": [ + -0.4031, + 0.7881, + 0.074 + ] + } + }, + "ArmR_UpperArmor": { + "mesh": "ArmR_UpperArmor_Mesh.006", + "triangles": 664, + "vertices": 334, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.6124, + 0.6611, + -0.1776 + ], + "max": [ + -0.3317, + 0.9359, + 0.052 + ] + } + }, + "ArmR_ForearmArmor": { + "mesh": "ArmR_ForearmArmor_Mesh.006", + "triangles": 638, + "vertices": 321, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.6853, + 0.414, + -0.113 + ], + "max": [ + -0.3891, + 0.732, + 0.1643 + ] + } + }, + "ArmR_Shoulder": { + "mesh": "ArmR_Shoulder_Mesh.006", + "triangles": 608, + "vertices": 306, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.6036, + 0.7671, + -0.2565 + ], + "max": [ + -0.2408, + 1.0741, + 0.0735 + ] + } + }, + "ArmR_ShoulderJoint": { + "mesh": "ArmR_ShoulderJoint_Mesh.006", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5127, + 0.8355, + 0.0029 + ], + "max": [ + -0.3347, + 1.0134, + 0.053 + ] + } + }, + "ArmR_UpperBand": { + "mesh": "ArmR_UpperBand_Mesh.006", + "triangles": 284, + "vertices": 144, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.7097, + 0.4323, + -0.1211 + ], + "max": [ + -0.3638, + 0.6924, + 0.1965 + ] + } + }, + "ArmR_UpperBandRivet_Seat": { + "mesh": "ArmR_UpperBandRivet_Seat_Mesh.006", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5627, + 0.5364, + 0.2019 + ], + "max": [ + -0.5107, + 0.5884, + 0.2105 + ] + } + }, + "ArmR_UpperBandRivet_Head": { + "mesh": "ArmR_UpperBandRivet_Head_Mesh.006", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5541, + 0.545, + 0.2062 + ], + "max": [ + -0.5194, + 0.5797, + 0.2235 + ] + } + }, + "ArmR_WristBand": { + "mesh": "ArmR_WristBand_Mesh.006", + "triangles": 284, + "vertices": 144, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.7175, + 0.3803, + -0.0834 + ], + "max": [ + -0.3716, + 0.6404, + 0.2342 + ] + } + }, + "ArmR_WristBandRivet_Seat": { + "mesh": "ArmR_WristBandRivet_Seat_Mesh.006", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5705, + 0.4844, + 0.2396 + ], + "max": [ + -0.5185, + 0.5364, + 0.2482 + ] + } + }, + "ArmR_WristBandRivet_Head": { + "mesh": "ArmR_WristBandRivet_Head_Mesh.006", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5619, + 0.493, + 0.2439 + ], + "max": [ + -0.5272, + 0.5277, + 0.2612 + ] + } + }, + "ArmR_Palm": { + "mesh": "ArmR_Palm_Mesh.006", + "triangles": 604, + "vertices": 304, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.6905, + 0.3482, + -0.0262 + ], + "max": [ + -0.4111, + 0.6225, + 0.2176 + ] + } + }, + "WeaponR_Claw0": { + "mesh": "WeaponR_Claw0_Mesh", + "triangles": 574, + "vertices": 289, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5228, + 0.1541, + 0.0951 + ], + "max": [ + -0.3529, + 0.6199, + 0.4473 + ] + } + }, + "ArmR_Knuckle0_Seat": { + "mesh": "ArmR_Knuckle0_Seat_Mesh", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.454, + 0.5571, + 0.1979 + ], + "max": [ + -0.3934, + 0.6177, + 0.2066 + ] + } + }, + "ArmR_Knuckle0_Head": { + "mesh": "ArmR_Knuckle0_Head_Mesh", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.4439, + 0.5672, + 0.2022 + ], + "max": [ + -0.4035, + 0.6076, + 0.2196 + ] + } + }, + "WeaponR_Claw1": { + "mesh": "WeaponR_Claw1_Mesh", + "triangles": 574, + "vertices": 289, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.6576, + 0.1541, + 0.0951 + ], + "max": [ + -0.4877, + 0.6199, + 0.4473 + ] + } + }, + "ArmR_Knuckle1_Seat": { + "mesh": "ArmR_Knuckle1_Seat_Mesh", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5888, + 0.5571, + 0.1979 + ], + "max": [ + -0.5282, + 0.6177, + 0.2066 + ] + } + }, + "ArmR_Knuckle1_Head": { + "mesh": "ArmR_Knuckle1_Head_Mesh", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.5787, + 0.5672, + 0.2022 + ], + "max": [ + -0.5383, + 0.6076, + 0.2196 + ] + } + }, + "WeaponR_Claw2": { + "mesh": "WeaponR_Claw2_Mesh", + "triangles": 574, + "vertices": 289, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.7924, + 0.1541, + 0.0951 + ], + "max": [ + -0.6225, + 0.6199, + 0.4473 + ] + } + }, + "ArmR_Knuckle2_Seat": { + "mesh": "ArmR_Knuckle2_Seat_Mesh", + "triangles": 444, + "vertices": 224, + "ngons": 0, + "materials": [ + "SW_HD_dark" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.7237, + 0.5571, + 0.1979 + ], + "max": [ + -0.663, + 0.6177, + 0.2066 + ] + } + }, + "ArmR_Knuckle2_Head": { + "mesh": "ArmR_Knuckle2_Head_Mesh", + "triangles": 508, + "vertices": 256, + "ngons": 0, + "materials": [ + "SW_HD_gold_light" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.7135, + 0.5672, + 0.2022 + ], + "max": [ + -0.6731, + 0.6076, + 0.2196 + ] + } + }, + "ArmR_ShoulderTrim": { + "mesh": "ArmR_ShoulderTrim_Mesh", + "triangles": 238, + "vertices": 121, + "ngons": 0, + "materials": [ + "SW_HD_gold" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.4995, + 0.9119, + 0.0434 + ], + "max": [ + -0.3094, + 1.0641, + 0.0819 + ] + } + }, + "Body_DorsalSpine0": { + "mesh": "Body_DorsalSpine0_Mesh", + "triangles": 412, + "vertices": 208, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + 0.0298, + 0.9534, + -0.2918 + ], + "max": [ + 0.2646, + 1.35, + -0.0555 + ] + } + }, + "Body_DorsalSpine1": { + "mesh": "Body_DorsalSpine1_Mesh", + "triangles": 106, + "vertices": 55, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.1185, + 0.9558, + -0.2935 + ], + "max": [ + 0.1185, + 1.2615, + -0.0604 + ] + } + }, + "Body_DorsalSpine2": { + "mesh": "Body_DorsalSpine2_Mesh", + "triangles": 412, + "vertices": 208, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.2583, + 0.9538, + -0.2918 + ], + "max": [ + -0.0249, + 1.3485, + -0.0556 + ] + } + }, + "Head_Chin": { + "mesh": "Head_Chin_Mesh", + "triangles": 2208, + "vertices": 1106, + "ngons": 0, + "materials": [ + "SW_HD_basalt" + ], + "uv_layers": [ + "UV-Map" + ], + "color_attributes": [], + "active_color": null, + "custom_normals": true, + "normals_unit_length": true, + "shape_keys": 0, + "skinned": false, + "scale": [ + 1.0, + 1.0, + 1.0 + ], + "bounds_unity": { + "min": [ + -0.1651, + 0.3329, + -0.0585 + ], + "max": [ + 0.1774, + 0.6532, + 0.3289 + ] + } + } + }, + "armatures": {}, + "empties": { + "Model_g01": [ + 0.0, + 0.0, + 0.0 + ], + "Forward": [ + 0.0, + 0.0, + 0.75 + ] + }, + "bounds_unity": { + "min": [ + -0.7924, + 0.0, + -0.4473 + ], + "max": [ + 0.7924, + 1.35, + 0.4473 + ] + }, + "clips": [], + "expected_from_godot": { + "triangles": 79780, + "bounds_godot": { + "min": [ + -0.7924438118934631, + 0.0, + -0.44730144739151 + ], + "max": [ + 0.7924438118934631, + 1.350000023841858, + 0.4473014771938324 + ] + }, + "resource_path": "res://assets/models/unit_g01.glb" + }, + "meshes_without_uv": [ + "ArmL_ShoulderTrim", + "ArmR_ShoulderTrim", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Head_EyeL", + "Head_EyeR", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_KneeGuard", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR_KneeGuard", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ], + "triangles": 79780, + "fbx": "Assets/Luneraria/Art/Units/g01.fbx", + "fbx_bytes": 5752668, + "ok": true +} diff --git a/Assets/Luneraria/Art/Units/g01.export.json.meta b/Assets/Luneraria/Art/Units/g01.export.json.meta new file mode 100644 index 0000000..b34c62a --- /dev/null +++ b/Assets/Luneraria/Art/Units/g01.export.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d7a4fb253a9584d0ba79fa033c20eb6b +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Art/Units/g01.fbx b/Assets/Luneraria/Art/Units/g01.fbx new file mode 100644 index 0000000..a966bb0 Binary files /dev/null and b/Assets/Luneraria/Art/Units/g01.fbx differ diff --git a/Assets/Luneraria/Art/Units/g01.fbx.meta b/Assets/Luneraria/Art/Units/g01.fbx.meta new file mode 100644 index 0000000..b1f7e5e --- /dev/null +++ b/Assets/Luneraria/Art/Units/g01.fbx.meta @@ -0,0 +1,111 @@ +fileFormatVersion: 2 +guid: 416c29115e263420dbef5a876b74571c +ModelImporter: + serializedVersion: 24300 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 0 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 0 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 0 + importBlendShapes: 0 + importCameras: 0 + importLights: 0 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 0 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 0 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 0 + humanoidOversampling: 1 + avatarSetup: 0 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Editor.meta b/Assets/Luneraria/Editor.meta new file mode 100644 index 0000000..c0157b6 --- /dev/null +++ b/Assets/Luneraria/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4460d353d8e864b71bbfb46336516b2d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Editor/Art.meta b/Assets/Luneraria/Editor/Art.meta new file mode 100644 index 0000000..4c06659 --- /dev/null +++ b/Assets/Luneraria/Editor/Art.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 793ae230624f046acb4639e9b27fa0be +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Editor/Art/ExportReport.cs b/Assets/Luneraria/Editor/Art/ExportReport.cs new file mode 100644 index 0000000..111a810 --- /dev/null +++ b/Assets/Luneraria/Editor/Art/ExportReport.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.IO; +using Newtonsoft.Json.Linq; + +namespace Luneraria.EditorTools +{ + /// + /// The facts and checks that tools/blender/lune_fbx_export.py writes next to every FBX + /// (<id>.export.json). The importer reads the clip data from it; the verifier compares + /// the imported model with the Blender side. + /// + public sealed class ExportReport + { + public readonly string Path; + public readonly JObject Data; + + ExportReport(string path, JObject data) + { + Path = path; + Data = data; + } + + public string Id { get { return (string)Data["id"]; } } + public string Kind { get { return (string)Data["kind"]; } } + public bool Skinned { get { return Kind == "skinned"; } } + public bool BlenderOk { get { return (bool)Data["ok"]; } } + public JObject Meshes { get { return (JObject)Data["meshes"]; } } + public JArray Clips { get { return (JArray)Data["clips"] ?? new JArray(); } } + + /// Report of an FBX asset path, or null if the model was not exported by the pipeline. + public static ExportReport ForModel(string modelPath) + { + string path = System.IO.Path.ChangeExtension(modelPath, ".export.json"); + if (!File.Exists(path)) + return null; + return new ExportReport(path, JObject.Parse(File.ReadAllText(path))); + } + + public static IEnumerable AllModels(string root) + { + foreach (string path in Directory.GetFiles(root, "*.export.json", SearchOption.AllDirectories)) + yield return path.Replace('\\', '/').Replace(".export.json", ".fbx"); + } + } +} diff --git a/Assets/Luneraria/Editor/Art/ExportReport.cs.meta b/Assets/Luneraria/Editor/Art/ExportReport.cs.meta new file mode 100644 index 0000000..23c4d8d --- /dev/null +++ b/Assets/Luneraria/Editor/Art/ExportReport.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2ea3ae2e05fa54b17a8ef5eed98cad51 \ No newline at end of file diff --git a/Assets/Luneraria/Editor/Art/LuneAssetPreview.cs b/Assets/Luneraria/Editor/Art/LuneAssetPreview.cs new file mode 100644 index 0000000..b5bb98f --- /dev/null +++ b/Assets/Luneraria/Editor/Art/LuneAssetPreview.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.Rendering; + +namespace Luneraria.EditorTools +{ + /// + /// Renders every pipeline asset in a neutral preview scene (URP, one sun, 3/4 front view) to + /// docs/port/screenshots/u2a/. Buildings show their intact state; the tower also its ruin; + /// rigged figures their bind pose and the hit frame of attack_a. + /// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneAssetPreview.RenderAll + /// + public static class LuneAssetPreview + { + const int Width = 1600; + const int Height = 1000; + + public static void RenderAll() + { + int code = 0; + try + { + string folder = Path.Combine(Path.GetDirectoryName(Application.dataPath), "docs/port/screenshots/u2a"); + Directory.CreateDirectory(folder); + EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); + var sun = new GameObject("Sun").AddComponent(); + sun.type = LightType.Directional; + sun.intensity = 1.6f; + sun.color = new Color(1f, .89f, .74f); + sun.shadows = LightShadows.Soft; + sun.transform.rotation = Quaternion.Euler(48f, 150f, 0f); + RenderSettings.ambientMode = AmbientMode.Trilight; + RenderSettings.ambientSkyColor = new Color(.55f, .6f, .68f); + RenderSettings.ambientEquatorColor = new Color(.42f, .42f, .44f); + RenderSettings.ambientGroundColor = new Color(.2f, .19f, .18f); + var ground = GameObject.CreatePrimitive(PrimitiveType.Plane); + ground.transform.localScale = new Vector3(20f, 1f, 20f); + var camera = new GameObject("PreviewCamera").AddComponent(); + camera.clearFlags = CameraClearFlags.SolidColor; + camera.backgroundColor = new Color(.16f, .18f, .21f); + camera.fieldOfView = 30f; + foreach (string model in ExportReport.AllModels("Assets/Luneraria/Art").OrderBy(p => p, StringComparer.Ordinal)) + { + ExportReport report = ExportReport.ForModel(model); + var prefab = AssetDatabase.LoadAssetAtPath(model); + foreach (var shot in Shots(report)) + { + var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab); + shot.Value(instance); + Render(camera, instance, Path.Combine(folder, report.Id + shot.Key + ".png")); + UnityEngine.Object.DestroyImmediate(instance); + } + } + } + catch (Exception error) + { + Debug.LogError("LUNE_PREVIEW failed: " + error); + code = 1; + } + EditorApplication.Exit(code); + } + + static IEnumerable>> Shots(ExportReport report) + { + string group = (string)report.Data["group"]; + if (group == "Buildings") + { + yield return Shot("", go => Show(go, n => !n.StartsWith("Upper_Damaged") && !n.StartsWith("Debris") && !n.StartsWith("Ruin"))); + if (report.Id == "grenzwacht") + yield return Shot("-ruin", go => Show(go, n => n.StartsWith("Ruin"))); + } + else if (group == "Environment") + { + yield return Shot("", Row); + } + else if (report.Skinned) + { + yield return Shot("", go => Sample(go, "idle", 0f)); + yield return Shot("-attack_a", go => Sample(go, "attack_a", .9f)); + } + else + { + yield return Shot("", go => { }); + } + } + + static KeyValuePair> Shot(string suffix, Action prepare) + { + return new KeyValuePair>(suffix, prepare); + } + + static void Show(GameObject root, Func visible) + { + foreach (Renderer renderer in root.GetComponentsInChildren(true)) + renderer.enabled = visible(renderer.gameObject.name); + } + + /// The prop library keeps every prop at the origin; the preview sets them out in a grid. + static void Row(GameObject root) + { + const int columns = 5; + const float cell = 7.5f; + int index = 0; + foreach (Transform child in root.transform.Cast().OrderBy(t => t.name, StringComparer.Ordinal).ToList()) + { + var renderer = child.GetComponent(); + if (renderer == null) + continue; + Vector3 center = renderer.bounds.center; + var slot = new Vector3((index % columns) * cell, 0f, -(index / columns) * cell); + child.position += slot - new Vector3(center.x, 0f, center.z); + index++; + } + } + + static void Sample(GameObject root, string clipName, float seconds) + { + string path = AssetDatabase.GetAssetPath(PrefabUtility.GetCorrespondingObjectFromSource(root)); + AnimationClip clip = AssetDatabase.LoadAllAssetsAtPath(path).OfType().FirstOrDefault(c => c.name == clipName); + if (clip != null) + clip.SampleAnimation(root, seconds); + } + + static void Render(Camera camera, GameObject root, string file) + { + var renderers = root.GetComponentsInChildren().Where(r => r.enabled).ToList(); + Bounds bounds = renderers[0].bounds; + foreach (Renderer renderer in renderers) + bounds.Encapsulate(renderer.bounds); + // 3/4 front view: the models face +Z, the camera stands in front, to the right, above. + Vector3 direction = new Vector3(.62f, .42f, 1f).normalized; + float radius = bounds.extents.magnitude; + float distance = radius / Mathf.Sin(camera.fieldOfView * .5f * Mathf.Deg2Rad) * .92f; + camera.aspect = (float)Width / Height; + camera.transform.position = bounds.center + direction * distance; + camera.transform.LookAt(bounds.center); + camera.nearClipPlane = Mathf.Max(.01f, distance - radius * 2f); + camera.farClipPlane = distance + radius * 4f; + var target = new RenderTexture(Width, Height, 24, RenderTextureFormat.ARGB32) { antiAliasing = 8 }; + camera.targetTexture = target; + camera.Render(); + RenderTexture.active = target; + var image = new Texture2D(Width, Height, TextureFormat.RGB24, false); + image.ReadPixels(new Rect(0, 0, Width, Height), 0, 0); + image.Apply(); + File.WriteAllBytes(file, image.EncodeToPNG()); + RenderTexture.active = null; + camera.targetTexture = null; + UnityEngine.Object.DestroyImmediate(target); + UnityEngine.Object.DestroyImmediate(image); + Debug.Log("LUNE_PREVIEW wrote " + file); + } + } +} diff --git a/Assets/Luneraria/Editor/Art/LuneAssetPreview.cs.meta b/Assets/Luneraria/Editor/Art/LuneAssetPreview.cs.meta new file mode 100644 index 0000000..b85f3c0 --- /dev/null +++ b/Assets/Luneraria/Editor/Art/LuneAssetPreview.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 50634406ba3e34d398502bba3379f6af \ No newline at end of file diff --git a/Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs b/Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs new file mode 100644 index 0000000..d2a6164 --- /dev/null +++ b/Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs @@ -0,0 +1,262 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Newtonsoft.Json.Linq; +using UnityEditor; +using UnityEngine; + +namespace Luneraria.EditorTools +{ + /// + /// Checks every imported FBX of the Blender pipeline against the facts Blender wrote next to it + /// (U2A): transforms free of axis rotations, mesh names, triangles, bounds, material slots, + /// normals, tangents, UVs, vertex colours, root bone and bone names, clips with loop flags and + /// contact events, forward direction. Batch entry: + /// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneAssetVerifier.VerifyAll + /// Result: docs/port/logs/u2a/unity-verify.json; exit code 0 only if every check passed. + /// + public static class LuneAssetVerifier + { + const string Root = "Assets/Luneraria/Art"; + const float BoundsTolerance = 0.002f; + + /// Re-imports every pipeline model (after import rules or the render pipeline changed). + public static void ReimportArt() + { + AssetDatabase.ImportAsset(Root, ImportAssetOptions.ImportRecursive | ImportAssetOptions.ForceUpdate | ImportAssetOptions.ForceSynchronousImport); + Debug.Log("LUNE_VERIFY reimported " + Root); + EditorApplication.Exit(0); + } + + public static void VerifyAll() + { + int code = 1; + try + { + AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); + var results = new JArray(); + bool all = true; + foreach (string model in ExportReport.AllModels(Root).OrderBy(p => p, StringComparer.Ordinal)) + { + JObject result = Verify(model); + results.Add(result); + all &= (bool)result["ok"]; + var failed = ((JArray)result["checks"]).Where(c => !(bool)c["ok"]).ToList(); + Debug.Log(string.Format("LUNE_VERIFY {0} {1}: {2} checks, {3} failed{4}", failed.Count == 0 ? "OK" : "FAIL", result["id"], + ((JArray)result["checks"]).Count, failed.Count, string.Concat(failed.Select(c => "\n FAIL " + c["check"] + ": " + c["detail"])))); + } + string logs = Path.Combine(Path.GetDirectoryName(Application.dataPath), "docs/port/logs/u2a"); + Directory.CreateDirectory(logs); + var summary = new JObject { ["unity"] = Application.unityVersion, ["ok"] = all, ["assets"] = results }; + File.WriteAllText(Path.Combine(logs, "unity-verify.json"), summary.ToString() + "\n"); + code = all ? 0 : 2; + } + catch (Exception error) + { + Debug.LogError("LUNE_VERIFY crashed: " + error); + } + EditorApplication.Exit(code); + } + + sealed class Checks + { + public readonly JArray List = new JArray(); + + public void Add(string name, bool ok, object detail = null) + { + List.Add(new JObject { ["check"] = name, ["ok"] = ok, ["detail"] = detail == null ? "" : JToken.FromObject(detail).ToString(Newtonsoft.Json.Formatting.None) }); + } + + public bool Ok { get { return List.All(c => (bool)c["ok"]); } } + } + + public static JObject Verify(string modelPath) + { + ExportReport report = ExportReport.ForModel(modelPath); + var checks = new Checks(); + var facts = new JObject(); + var root = AssetDatabase.LoadAssetAtPath(modelPath); + checks.Add("blender_checks_passed", report.BlenderOk); + checks.Add("imported", root != null, modelPath); + if (root == null) + return Result(report, checks, facts); + var importer = (ModelImporter)AssetImporter.GetAtPath(modelPath); + checks.Add("import_rules_applied", importer.globalScale == 1f && importer.useFileScale && importer.bakeAxisConversion + && importer.importNormals == ModelImporterNormals.Import && importer.importTangents == ModelImporterTangents.Import); + checks.Add("root_transform_identity", IsIdentity(root.transform), Describe(root.transform)); + var bones = new HashSet(); + foreach (var skinned in root.GetComponentsInChildren(true)) + foreach (Transform bone in skinned.bones) + bones.Add(bone); + // Blender objects carry no rotation or scale; after the axis bake every node that is not + // a bone must be clean, otherwise the conversion ended up in the hierarchy. + var rotated = root.GetComponentsInChildren(true).Where(t => t != root.transform && !bones.Contains(t) && !IsClean(t)).Select(Describe).ToList(); + checks.Add("node_transforms_axis_clean", rotated.Count == 0, rotated.Take(8).ToList()); + + var renderers = root.GetComponentsInChildren(true).Where(r => r is MeshRenderer || r is SkinnedMeshRenderer).ToList(); + var names = renderers.Select(r => r.gameObject.name).OrderBy(n => n, StringComparer.Ordinal).ToList(); + var expectedNames = report.Meshes.Properties().Select(p => p.Name).OrderBy(n => n, StringComparer.Ordinal).ToList(); + checks.Add("mesh_names", names.SequenceEqual(expectedNames), names.Except(expectedNames).Concat(expectedNames.Except(names)).Take(12).ToList()); + + int triangles = 0; + var wrongTriangles = new List(); + var wrongMaterials = new List(); + var badNormals = new List(); + var badTangents = new List(); + var missingUv = new List(); + var missingColors = new List(); + var low = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); + var high = new Vector3(float.MinValue, float.MinValue, float.MinValue); + int withoutTangents = 0; + foreach (Renderer renderer in renderers) + { + Mesh mesh = renderer is SkinnedMeshRenderer skinned ? skinned.sharedMesh : renderer.GetComponent().sharedMesh; + string name = renderer.gameObject.name; + var blender = (JObject)report.Meshes[name]; + int count = mesh.triangles.Length / 3; + triangles += count; + if (blender != null && (int)blender["triangles"] != count) + wrongTriangles.Add(name + " " + count + "/" + blender["triangles"]); + if (blender != null) + { + var want = ((JArray)blender["materials"]).Select(m => (string)m).OrderBy(m => m, StringComparer.Ordinal).ToList(); + var got = renderer.sharedMaterials.Select(m => m != null ? m.name : "").OrderBy(m => m, StringComparer.Ordinal).ToList(); + if (!want.SequenceEqual(got)) + wrongMaterials.Add(name + ": " + string.Join(",", got) + " / " + string.Join(",", want)); + bool hasUv = ((JArray)blender["uv_layers"]).Count > 0; + if (hasUv && mesh.uv.Length != mesh.vertexCount) + missingUv.Add(name); + if (((JArray)blender["color_attributes"]).Count > 0 && mesh.colors.Length != mesh.vertexCount) + missingColors.Add(name); + Vector4[] tangents = mesh.tangents; + if (hasUv) + { + if (tangents.Length != mesh.vertexCount || tangents.Any(t => Mathf.Abs(Mathf.Abs(t.w) - 1f) > 1e-3f)) + badTangents.Add(name); + } + else if (tangents.Length == 0) + { + withoutTangents++; + } + } + Vector3[] normals = mesh.normals; + if (normals.Length != mesh.vertexCount || normals.Any(n => Mathf.Abs(n.magnitude - 1f) > 1e-3f)) + badNormals.Add(name); + Matrix4x4 toRoot = root.transform.worldToLocalMatrix * renderer.transform.localToWorldMatrix; + foreach (Vector3 vertex in mesh.vertices) + { + Vector3 p = toRoot.MultiplyPoint3x4(vertex); + low = Vector3.Min(low, p); + high = Vector3.Max(high, p); + } + } + facts["triangles"] = triangles; + facts["renderers"] = renderers.Count; + facts["meshes_without_uv_and_tangents"] = withoutTangents; + checks.Add("triangles", triangles == (int)report.Data["triangles"] && wrongTriangles.Count == 0, triangles + " unity / " + report.Data["triangles"] + " blender " + string.Join("; ", wrongTriangles.Take(5))); + checks.Add("material_slots", wrongMaterials.Count == 0, wrongMaterials.Take(5).ToList()); + checks.Add("normals_unit_length", badNormals.Count == 0, badNormals.Take(8).ToList()); + checks.Add("tangents_where_uv", badTangents.Count == 0, badTangents.Take(8).ToList()); + checks.Add("uvs_where_blender_has_uv", missingUv.Count == 0, missingUv.Take(8).ToList()); + checks.Add("vertex_colors", missingColors.Count == 0, missingColors.Take(8).ToList()); + + var bounds = (JObject)report.Data["bounds_unity"]; + if (bounds != null) + { + var wantLow = ToVector((JArray)bounds["min"]); + var wantHigh = ToVector((JArray)bounds["max"]); + float worst = Mathf.Max(MaxAbs(low - wantLow), MaxAbs(high - wantHigh)); + facts["bounds_min"] = new JArray(low.x, low.y, low.z); + facts["bounds_max"] = new JArray(high.x, high.y, high.z); + checks.Add("bounds_axes_scale", worst < BoundsTolerance, string.Format("largest difference {0:0.00000} m; unity {1} {2}", worst, low.ToString("F3"), high.ToString("F3"))); + } + + JObject empties = (JObject)report.Data["empties"]; + JProperty forward = empties?.Properties().FirstOrDefault(p => p.Name.StartsWith("Forward")); + if (forward != null) + { + Transform marker = root.GetComponentsInChildren(true).FirstOrDefault(t => t.name.StartsWith("Forward")); + Vector3 at = marker != null ? root.transform.InverseTransformPoint(marker.position) : Vector3.zero; + checks.Add("forward_is_plus_z", marker != null && at.z > 0.1f && Mathf.Abs(at.x) < 1e-3f, at.ToString("F3")); + } + + if (report.Skinned) + VerifyRig(modelPath, report, root, checks, facts); + return Result(report, checks, facts); + } + + static void VerifyRig(string modelPath, ExportReport report, GameObject root, Checks checks, JObject facts) + { + var skinned = root.GetComponentsInChildren(true); + checks.Add("skinned_mesh", skinned.Length >= 1, skinned.Length); + var armature = (JObject)((JObject)report.Data["armatures"]).Properties().First().Value; + var wantBones = ((JArray)armature["bones"]).Select(b => (string)b).OrderBy(b => b, StringComparer.Ordinal).ToList(); + string wantRoot = (string)((JArray)armature["roots"])[0]; + foreach (SkinnedMeshRenderer renderer in skinned) + { + var got = renderer.bones.Select(b => b.name).Distinct().OrderBy(b => b, StringComparer.Ordinal).ToList(); + checks.Add("bone_names " + renderer.name, got.SequenceEqual(wantBones), got.Except(wantBones).Concat(wantBones.Except(got)).ToList()); + checks.Add("root_bone " + renderer.name, renderer.rootBone != null && renderer.rootBone.name == wantRoot, renderer.rootBone != null ? renderer.rootBone.name : "none"); + } + UnityEngine.Object[] assets = AssetDatabase.LoadAllAssetsAtPath(modelPath); + var avatar = assets.OfType().FirstOrDefault(); + checks.Add("generic_avatar", avatar != null && avatar.isValid && !avatar.isHuman, avatar != null ? avatar.name : "none"); + var clips = assets.OfType().Where(c => !c.name.StartsWith("__preview__")).ToDictionary(c => c.name, c => c); + var wrong = new List(); + foreach (JToken clip in report.Clips) + { + string name = (string)clip["name"]; + if (!clips.TryGetValue(name, out AnimationClip unity)) + { + wrong.Add(name + " missing"); + continue; + } + float seconds = (float)clip["seconds"]; + float frame = 1f / (float)report.Data["fps"]; + if (Mathf.Abs(unity.length - seconds) > frame * 0.5f) + wrong.Add(string.Format("{0} length {1:0.000}/{2:0.000}", name, unity.length, seconds)); + if (unity.isLooping != (bool)clip["loop"]) + wrong.Add(name + " loop " + unity.isLooping); + double contact = (double)clip["contact_seconds"]; + AnimationEvent[] events = AnimationUtility.GetAnimationEvents(unity); + bool hasContact = events.Any(e => e.functionName == LuneModelPostprocessor.ContactEvent && Mathf.Abs(e.time - (float)contact) < frame); + if (contact > 0 && !hasContact) + wrong.Add(name + " contact event"); + } + var extra = clips.Keys.Except(report.Clips.Select(c => (string)c["name"])).ToList(); + checks.Add("clips", wrong.Count == 0 && extra.Count == 0, wrong.Concat(extra.Select(e => e + " unexpected")).ToList()); + facts["clips"] = new JArray(clips.Values.OrderBy(c => c.name).Select(c => new JObject { ["name"] = c.name, ["length"] = c.length, ["loop"] = c.isLooping, ["events"] = AnimationUtility.GetAnimationEvents(c).Length })); + } + + static JObject Result(ExportReport report, Checks checks, JObject facts) + { + return new JObject { ["id"] = report.Id, ["kind"] = report.Kind, ["ok"] = checks.Ok, ["checks"] = checks.List, ["facts"] = facts }; + } + + static bool IsIdentity(Transform t) + { + return t.localPosition.sqrMagnitude < 1e-10f && IsClean(t); + } + + static bool IsClean(Transform t) + { + return Quaternion.Angle(t.localRotation, Quaternion.identity) < 0.01f && (t.localScale - Vector3.one).sqrMagnitude < 1e-8f; + } + + static string Describe(Transform t) + { + return string.Format("{0} pos {1} rot {2} scale {3}", t.name, t.localPosition.ToString("F4"), t.localEulerAngles.ToString("F2"), t.localScale.ToString("F4")); + } + + static Vector3 ToVector(JArray values) + { + return new Vector3((float)values[0], (float)values[1], (float)values[2]); + } + + static float MaxAbs(Vector3 v) + { + return Mathf.Max(Mathf.Abs(v.x), Mathf.Max(Mathf.Abs(v.y), Mathf.Abs(v.z))); + } + } +} diff --git a/Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs.meta b/Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs.meta new file mode 100644 index 0000000..b793b59 --- /dev/null +++ b/Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 588d50b5a3531448691e7370abd8dc6e \ No newline at end of file diff --git a/Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs b/Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs new file mode 100644 index 0000000..9c80917 --- /dev/null +++ b/Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace Luneraria.EditorTools +{ + /// + /// Import rules for every FBX of the Blender pipeline under Assets/Luneraria/Art (U2A). + /// Metres stay metres, Blender's Z-up axes are converted by baking (no root rotation), + /// normals and tangents come from the file, rigs are generic with the Blender bone names, + /// and clips get their Blender action names, loop flags and contact events. + /// + public sealed class LuneModelPostprocessor : AssetPostprocessor + { + public const string ArtRoot = "Assets/Luneraria/Art/"; + /// Raised on the figure at the hit frame of attack and ability clips. + public const string ContactEvent = "OnLuneContact"; + + public override uint GetVersion() { return 3; } + + void OnPreprocessModel() + { + if (!assetPath.StartsWith(ArtRoot) || !assetPath.EndsWith(".fbx")) + return; + ExportReport report = ExportReport.ForModel(assetPath); + var importer = (ModelImporter)assetImporter; + importer.globalScale = 1f; + importer.useFileScale = true; + importer.bakeAxisConversion = true; + importer.importCameras = false; + importer.importLights = false; + importer.importVisibility = false; + importer.importBlendShapes = false; + importer.importNormals = ModelImporterNormals.Import; + importer.importTangents = ModelImporterTangents.Import; + importer.meshCompression = ModelImporterMeshCompression.Off; + importer.isReadable = true; + importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription; + importer.materialLocation = ModelImporterMaterialLocation.InPrefab; + bool skinned = report != null && report.Skinned; + importer.animationType = skinned ? ModelImporterAnimationType.Generic : ModelImporterAnimationType.None; + importer.avatarSetup = skinned ? ModelImporterAvatarSetup.CreateFromThisModel : ModelImporterAvatarSetup.NoAvatar; + importer.importAnimation = skinned; + importer.optimizeGameObjects = false; + importer.animationCompression = ModelImporterAnimationCompression.Off; + importer.resampleCurves = false; + } + + void OnPreprocessAnimation() + { + if (!assetPath.StartsWith(ArtRoot) || !assetPath.EndsWith(".fbx")) + return; + ExportReport report = ExportReport.ForModel(assetPath); + if (report == null || !report.Skinned) + return; + var importer = (ModelImporter)assetImporter; + var blender = report.Clips.ToDictionary(c => (string)c["name"], c => c); + var clips = new List(); + foreach (ModelImporterClipAnimation clip in importer.defaultClipAnimations) + { + // Blender names takes "|"; Unity keeps the action name. + string name = clip.takeName.Contains("|") ? clip.takeName.Substring(clip.takeName.LastIndexOf('|') + 1) : clip.takeName; + clip.name = name; + if (blender.TryGetValue(name, out var facts)) + { + clip.loopTime = (bool)facts["loop"]; + double contact = (double)facts["contact_seconds"]; + double seconds = (double)facts["seconds"]; + if (contact > 0.0 && seconds > 0.0) + clip.events = new[] { new AnimationEvent { functionName = ContactEvent, time = (float)(contact / seconds) } }; + } + clips.Add(clip); + } + importer.clipAnimations = clips.ToArray(); + } + } +} diff --git a/Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs.meta b/Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs.meta new file mode 100644 index 0000000..7a19b10 --- /dev/null +++ b/Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3eb06f326c30446a4a9e3e2be3aee948 \ No newline at end of file diff --git a/Assets/Luneraria/Editor/Luneraria.Editor.asmdef b/Assets/Luneraria/Editor/Luneraria.Editor.asmdef new file mode 100644 index 0000000..d7b05c4 --- /dev/null +++ b/Assets/Luneraria/Editor/Luneraria.Editor.asmdef @@ -0,0 +1,22 @@ +{ + "name": "Luneraria.Editor", + "rootNamespace": "Luneraria.EditorTools", + "references": [ + "Luneraria.Core", + "Unity.RenderPipelines.Core.Runtime", + "Unity.RenderPipelines.Universal.Runtime" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "Newtonsoft.Json.dll" + ], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Assets/Luneraria/Editor/Luneraria.Editor.asmdef.meta b/Assets/Luneraria/Editor/Luneraria.Editor.asmdef.meta new file mode 100644 index 0000000..89a0ce0 --- /dev/null +++ b/Assets/Luneraria/Editor/Luneraria.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f6cff9d287b764627a17a7e3c7b99a6b +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Editor/Setup.meta b/Assets/Luneraria/Editor/Setup.meta new file mode 100644 index 0000000..094d697 --- /dev/null +++ b/Assets/Luneraria/Editor/Setup.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 695e40eeb3cef4a898659650d64902e2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Editor/Setup/LuneProjectSetup.cs b/Assets/Luneraria/Editor/Setup/LuneProjectSetup.cs new file mode 100644 index 0000000..401bfd0 --- /dev/null +++ b/Assets/Luneraria/Editor/Setup/LuneProjectSetup.cs @@ -0,0 +1,80 @@ +using System.IO; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace Luneraria.EditorTools +{ + /// + /// Rendering setup of the project (URP asset and renderer, linear colour space), idempotent. + /// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneProjectSetup.ConfigureRendering + /// + public static class LuneProjectSetup + { + public const string SettingsFolder = "Assets/Luneraria/Settings/Rendering"; + public const string PipelinePath = SettingsFolder + "/Luneraria_URP.asset"; + public const string RendererPath = SettingsFolder + "/Luneraria_URP_Renderer.asset"; + + public static void ConfigureRendering() + { + int code = 0; + try + { + Configure(); + } + catch (System.Exception error) + { + Debug.LogError("LUNE_SETUP failed: " + error); + code = 1; + } + EditorApplication.Exit(code); + } + + public static UniversalRenderPipelineAsset Configure() + { + Directory.CreateDirectory(SettingsFolder); + AssetDatabase.Refresh(); + var asset = AssetDatabase.LoadAssetAtPath(PipelinePath); + if (asset == null) + { + var renderer = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(renderer, RendererPath); + ResourceReloader.ReloadAllNullIn(renderer, UniversalRenderPipelineAsset.packagePath); + asset = UniversalRenderPipelineAsset.Create(renderer); + AssetDatabase.CreateAsset(asset, PipelinePath); + } + // The Godot sun reaches 190 m with four splits (scripts/luneraria/view/lune_world.gd). + asset.shadowDistance = 190f; + asset.shadowCascadeCount = 4; + asset.supportsHDR = true; + asset.msaaSampleCount = 4; + asset.useSRPBatcher = true; + EditorUtility.SetDirty(asset); + GraphicsSettings.defaultRenderPipeline = asset; + int current = QualitySettings.GetQualityLevel(); + for (int level = 0; level < QualitySettings.names.Length; level++) + { + QualitySettings.SetQualityLevel(level, false); + QualitySettings.renderPipeline = asset; + } + QualitySettings.SetQualityLevel(current, false); + PlayerSettings.colorSpace = ColorSpace.Linear; + MoveInto("Assets/UniversalRenderPipelineGlobalSettings.asset", SettingsFolder + "/UniversalRenderPipelineGlobalSettings.asset"); + MoveInto("Assets/DefaultVolumeProfile.asset", SettingsFolder + "/DefaultVolumeProfile.asset"); + AssetDatabase.SaveAssets(); + Debug.Log("LUNE_SETUP rendering: " + PipelinePath + ", colour space " + PlayerSettings.colorSpace); + return asset; + } + + static void MoveInto(string from, string to) + { + if (File.Exists(from) && !File.Exists(to)) + { + string error = AssetDatabase.MoveAsset(from, to); + if (!string.IsNullOrEmpty(error)) + Debug.LogWarning("LUNE_SETUP move " + from + ": " + error); + } + } + } +} diff --git a/Assets/Luneraria/Editor/Setup/LuneProjectSetup.cs.meta b/Assets/Luneraria/Editor/Setup/LuneProjectSetup.cs.meta new file mode 100644 index 0000000..5c7f7fb --- /dev/null +++ b/Assets/Luneraria/Editor/Setup/LuneProjectSetup.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e7bff4280437a4ab7bbe7bcaef5cf486 \ No newline at end of file diff --git a/Assets/Luneraria/Settings.meta b/Assets/Luneraria/Settings.meta new file mode 100644 index 0000000..146be7d --- /dev/null +++ b/Assets/Luneraria/Settings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9ca8da48623284af8ad6bdfdb0af7a1a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Settings/Rendering.meta b/Assets/Luneraria/Settings/Rendering.meta new file mode 100644 index 0000000..9cb1330 --- /dev/null +++ b/Assets/Luneraria/Settings/Rendering.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d08bc5b72ee04727bf259d3ad7f45e0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/DefaultVolumeProfile.asset b/Assets/Luneraria/Settings/Rendering/DefaultVolumeProfile.asset similarity index 100% rename from Assets/DefaultVolumeProfile.asset rename to Assets/Luneraria/Settings/Rendering/DefaultVolumeProfile.asset diff --git a/Assets/DefaultVolumeProfile.asset.meta b/Assets/Luneraria/Settings/Rendering/DefaultVolumeProfile.asset.meta similarity index 100% rename from Assets/DefaultVolumeProfile.asset.meta rename to Assets/Luneraria/Settings/Rendering/DefaultVolumeProfile.asset.meta diff --git a/Assets/Luneraria/Settings/Rendering/Luneraria_URP.asset b/Assets/Luneraria/Settings/Rendering/Luneraria_URP.asset new file mode 100644 index 0000000..3386d2f --- /dev/null +++ b/Assets/Luneraria/Settings/Rendering/Luneraria_URP.asset @@ -0,0 +1,143 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: Luneraria_URP + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset + k_AssetVersion: 13 + k_AssetPreviousVersion: 13 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: 4f1d1577e34314798a12f2f2556faaec, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsTerrainHoles: 1 + m_SupportsHDR: 1 + m_HDRColorBufferPrecision: 0 + m_MSAA: 4 + m_RenderScale: 1 + m_UpscalingFilter: 0 + m_FsrOverrideSharpness: 0 + m_FsrSharpness: 0.92 + m_EnableLODCrossFade: 1 + m_LODCrossFadeDitheringType: 1 + m_ShEvalMode: 0 + m_LightProbeSystem: 0 + m_ProbeVolumeMemoryBudget: 1024 + m_ProbeVolumeBlendingMemoryBudget: 256 + m_SupportProbeVolumeGPUStreaming: 0 + m_SupportProbeVolumeDiskStreaming: 0 + m_SupportProbeVolumeScenarios: 0 + m_SupportProbeVolumeScenarioBlending: 0 + m_ProbeVolumeSHBands: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 2048 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 2048 + m_AdditionalLightsShadowResolutionTierLow: 256 + m_AdditionalLightsShadowResolutionTierMedium: 512 + m_AdditionalLightsShadowResolutionTierHigh: 1024 + m_ReflectionProbeBlending: 0 + m_ReflectionProbeBoxProjection: 0 + m_ReflectionProbeAtlas: 1 + m_ShadowDistance: 190 + m_ShadowCascadeCount: 4 + m_Cascade2Split: 0.25 + m_Cascade3Split: {x: 0.1, y: 0.3} + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_CascadeBorder: 0.2 + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_AnyShadowsSupported: 1 + m_SoftShadowsSupported: 0 + m_ConservativeEnclosingSphere: 1 + m_NumIterationsEnclosingSphere: 64 + m_SoftShadowQuality: 2 + m_AdditionalLightsCookieResolution: 2048 + m_AdditionalLightsCookieFormat: 3 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_SupportsLightCookies: 1 + m_SupportsLightLayers: 0 + m_DebugLevel: 0 + m_StoreActionsOptimization: 0 + m_UseAdaptivePerformance: 1 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_AllowPostProcessAlphaOutput: 0 + m_UseFastSRGBLinearConversion: 0 + m_SupportDataDrivenLensFlare: 1 + m_SupportScreenSpaceLensFlare: 1 + m_GPUResidentDrawerMode: 0 + m_SmallMeshScreenPercentage: 0 + m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_VolumeFrameworkUpdateMode: 0 + m_VolumeProfile: {fileID: 0} + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + m_PrefilteringModeMainLightShadows: 1 + m_PrefilteringModeAdditionalLight: 4 + m_PrefilteringModeAdditionalLightShadows: 1 + m_PrefilterXRKeywords: 0 + m_PrefilteringModeForwardPlus: 1 + m_PrefilteringModeDeferredRendering: 1 + m_PrefilteringModeScreenSpaceOcclusion: 1 + m_PrefilterDebugKeywords: 0 + m_PrefilterWriteRenderingLayers: 0 + m_PrefilterHDROutput: 0 + m_PrefilterAlphaOutput: 0 + m_PrefilterSSAODepthNormals: 0 + m_PrefilterSSAOSourceDepthLow: 0 + m_PrefilterSSAOSourceDepthMedium: 0 + m_PrefilterSSAOSourceDepthHigh: 0 + m_PrefilterSSAOInterleaved: 0 + m_PrefilterSSAOBlueNoise: 0 + m_PrefilterSSAOSampleCountLow: 0 + m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOSampleCountHigh: 0 + m_PrefilterDBufferMRT1: 0 + m_PrefilterDBufferMRT2: 0 + m_PrefilterDBufferMRT3: 0 + m_PrefilterSoftShadowsQualityLow: 0 + m_PrefilterSoftShadowsQualityMedium: 0 + m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterSoftShadows: 0 + m_PrefilterScreenCoord: 0 + m_PrefilterScreenSpaceIrradiance: 0 + m_PrefilterNativeRenderPass: 0 + m_PrefilterUseLegacyLightmaps: 0 + m_PrefilterBicubicLightmapSampling: 0 + m_PrefilterReflectionProbeRotation: 0 + m_PrefilterReflectionProbeBlending: 0 + m_PrefilterReflectionProbeBoxProjection: 0 + m_PrefilterReflectionProbeAtlas: 0 + m_ShaderVariantLogLevel: 0 + m_ShadowCascades: 0 + m_Textures: + blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} diff --git a/Assets/Luneraria/Settings/Rendering/Luneraria_URP.asset.meta b/Assets/Luneraria/Settings/Rendering/Luneraria_URP.asset.meta new file mode 100644 index 0000000..822b85d --- /dev/null +++ b/Assets/Luneraria/Settings/Rendering/Luneraria_URP.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 88b2e99a809584b278f95d7e2a3dc890 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Luneraria/Settings/Rendering/Luneraria_URP_Renderer.asset b/Assets/Luneraria/Settings/Rendering/Luneraria_URP_Renderer.asset new file mode 100644 index 0000000..b5df8a8 --- /dev/null +++ b/Assets/Luneraria/Settings/Rendering/Luneraria_URP_Renderer.asset @@ -0,0 +1,55 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: Luneraria_URP_Renderer + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalRendererData + debugShaders: + debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3} + hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3} + probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3} + probeVolumeResources: + probeVolumeDebugShader: {fileID: 0} + probeVolumeFragmentationDebugShader: {fileID: 0} + probeVolumeOffsetDebugShader: {fileID: 0} + probeVolumeSamplingDebugShader: {fileID: 0} + probeSamplingDebugMesh: {fileID: 0} + probeSamplingDebugTexture: {fileID: 0} + probeVolumeBlendStatesCS: {fileID: 0} + m_RendererFeatures: [] + m_RendererFeatureMap: + m_UseNativeRenderPass: 0 + postProcessData: {fileID: 0} + m_AssetVersion: 3 + m_PrepassLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 2 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 1 + m_RenderingMode: 0 + m_DepthPrimingMode: 0 + m_CopyDepthMode: 1 + m_DepthAttachmentFormat: 0 + m_DepthTextureFormat: 0 + m_AccurateGbufferNormals: 0 + m_IntermediateTextureMode: 1 diff --git a/Assets/Luneraria/Settings/Rendering/Luneraria_URP_Renderer.asset.meta b/Assets/Luneraria/Settings/Rendering/Luneraria_URP_Renderer.asset.meta new file mode 100644 index 0000000..e1b6661 --- /dev/null +++ b/Assets/Luneraria/Settings/Rendering/Luneraria_URP_Renderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f1d1577e34314798a12f2f2556faaec +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniversalRenderPipelineGlobalSettings.asset b/Assets/Luneraria/Settings/Rendering/UniversalRenderPipelineGlobalSettings.asset similarity index 100% rename from Assets/UniversalRenderPipelineGlobalSettings.asset rename to Assets/Luneraria/Settings/Rendering/UniversalRenderPipelineGlobalSettings.asset diff --git a/Assets/UniversalRenderPipelineGlobalSettings.asset.meta b/Assets/Luneraria/Settings/Rendering/UniversalRenderPipelineGlobalSettings.asset.meta similarity index 100% rename from Assets/UniversalRenderPipelineGlobalSettings.asset.meta rename to Assets/Luneraria/Settings/Rendering/UniversalRenderPipelineGlobalSettings.asset.meta diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index 0a98754..a1b69c2 100644 --- a/ProjectSettings/GraphicsSettings.asset +++ b/ProjectSettings/GraphicsSettings.asset @@ -37,7 +37,7 @@ GraphicsSettings: m_PreloadedShaders: [] m_PreloadShadersBatchTimeLimit: -1 m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} - m_CustomRenderPipeline: {fileID: 0} + m_CustomRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2} m_TransparencySortMode: 0 m_TransparencySortAxis: {x: 0, y: 0, z: 1} m_DefaultRenderingPath: 1 @@ -61,8 +61,8 @@ GraphicsSettings: UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 6f0ce73cdc8074fc283478fba3d0ede7, type: 2} m_ShaderBuildSettings: keywordDeclarationOverrides: [] - m_LightsUseLinearIntensity: 0 - m_LightsUseColorTemperature: 0 + m_LightsUseLinearIntensity: 1 + m_LightsUseColorTemperature: 1 m_LogWhenShaderIsCompiled: 0 m_LightProbeOutsideHullStrategy: 1 m_CameraRelativeLightCulling: 0 diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index f9d9de5..5d65bdf 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -47,7 +47,7 @@ PlayerSettings: defaultScreenWidthWeb: 960 defaultScreenHeightWeb: 600 m_StereoRenderingPath: 0 - m_ActiveColorSpace: 0 + m_ActiveColorSpace: 1 unsupportedMSAAFallback: 0 m_SpriteBatchMaxVertexCount: 65535 m_SpriteBatchVertexThreshold: 300 @@ -160,14 +160,18 @@ PlayerSettings: useHDRDisplay: 0 hdrBitDepth: 0 m_ColorGamuts: 00000000 - targetPixelDensity: 0 + targetPixelDensity: 30 resolutionScalingMode: 0 resetResolutionOnWindowResize: 0 androidSupportedAspectRatio: 1 androidMaxAspectRatio: 2.4 androidMinAspectRatio: 1 applicationIdentifier: {} - buildNumber: {} + buildNumber: + Standalone: 0 + VisionOS: 0 + iPhone: 0 + tvOS: 0 overrideDefaultApplicationIdentifier: 0 AndroidBundleVersionCode: 1 AndroidMinSdkVersion: 25 @@ -188,13 +192,13 @@ PlayerSettings: VertexChannelCompressionMask: 4054 iPhoneSdkVersion: 988 iOSSimulatorArchitecture: 0 - iOSTargetOSVersionString: + iOSTargetOSVersionString: 15.0 tvOSSdkVersion: 0 tvOSSimulatorArchitecture: 0 tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: + tvOSTargetOSVersionString: 15.0 VisionOSSdkVersion: 0 - VisionOSTargetOSVersionString: + VisionOSTargetOSVersionString: 1.0 uIPrerenderedIcon: 0 uIRequiresPersistentWiFi: 0 uIRequiresFullScreen: 1 @@ -326,7 +330,7 @@ PlayerSettings: locationUsageDescription: microphoneUsageDescription: bluetoothUsageDescription: - macOSTargetOSVersion: + macOSTargetOSVersion: 12.0 switchNMETAOverride: switchNetLibKey: switchSocketMemoryPoolSize: 6144 diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset index 64f8aba..1257f4b 100644 --- a/ProjectSettings/QualitySettings.asset +++ b/ProjectSettings/QualitySettings.asset @@ -48,7 +48,7 @@ QualitySettings: asyncUploadBufferSize: 16 asyncUploadPersistentBuffer: 1 resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 0} + customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2} terrainQualityOverrides: 0 terrainPixelError: 1 terrainDetailDensityScale: 1 @@ -101,7 +101,7 @@ QualitySettings: asyncUploadBufferSize: 16 asyncUploadPersistentBuffer: 1 resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 0} + customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2} terrainQualityOverrides: 0 terrainPixelError: 1 terrainDetailDensityScale: 1 @@ -154,7 +154,7 @@ QualitySettings: asyncUploadBufferSize: 16 asyncUploadPersistentBuffer: 1 resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 0} + customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2} terrainQualityOverrides: 0 terrainPixelError: 1 terrainDetailDensityScale: 1 @@ -207,7 +207,7 @@ QualitySettings: asyncUploadBufferSize: 16 asyncUploadPersistentBuffer: 1 resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 0} + customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2} terrainQualityOverrides: 0 terrainPixelError: 1 terrainDetailDensityScale: 1 @@ -260,7 +260,7 @@ QualitySettings: asyncUploadBufferSize: 16 asyncUploadPersistentBuffer: 1 resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 0} + customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2} terrainQualityOverrides: 0 terrainPixelError: 1 terrainDetailDensityScale: 1 @@ -287,7 +287,7 @@ QualitySettings: globalTextureMipmapLimit: 0 textureMipmapLimitSettings: [] anisotropicTextures: 2 - antiAliasing: 2 + antiAliasing: 4 softParticles: 1 softVegetation: 1 realtimeReflectionProbes: 1 @@ -313,7 +313,7 @@ QualitySettings: asyncUploadBufferSize: 16 asyncUploadPersistentBuffer: 1 resolutionScalingFixedDPIFactor: 1 - customRenderPipeline: {fileID: 0} + customRenderPipeline: {fileID: 11400000, guid: 88b2e99a809584b278f95d7e2a3dc890, type: 2} terrainQualityOverrides: 0 terrainPixelError: 1 terrainDetailDensityScale: 1 diff --git a/docs/port/U2-WORLD.md b/docs/port/U2-WORLD.md index 6e0e031..4051f55 100644 --- a/docs/port/U2-WORLD.md +++ b/docs/port/U2-WORLD.md @@ -1,12 +1,19 @@ # U2 · Unity-Spielwelt -Stand: 30. September 2026 · **nicht begonnen**. +Stand: 30. September 2026. -Voraussetzungen: U1 grün (erfüllt außerhalb von Unity) und aktive Unity-Lizenz (fehlt). +| Teil | Inhalt | Zustand | +| --- | --- | --- | +| U2A | Blender→FBX-Pipeline, sechs repräsentative Assets vollständig geprüft | **fertig** | +| U2B | Weltgeometrie (G1-Karte, Türme, Ancients, Grotte, Aufstellungsbereiche), Materialsystem | offen | +| U2C | Simulation/Darstellung: fester Takt, Interpolation, Bildraten-Unabhängigkeit | offen | +| U2D | spielbare Unity-Partie, Vertical Function Test | offen | + +Voraussetzung U1.5 ist erfüllt ([U1.5-UNITY.md](U1.5-UNITY.md)). ## Ziel -Die bestehende Partie läuft sichtbar in Unity (URP). Das ist noch keine grafische Neugestaltung. +Die bestehende Partie läuft sichtbar in Unity (URP). Das ist noch keine grafische Neugestaltung; die kommt erst mit U5. Zuerst kommen: - die G1-Drei-Lane-Karte, @@ -17,35 +24,127 @@ Zuerst kommen: ## Vorgaben -- **Adapter:** Unity treibt `LuneMatch` im festen Takt (0,05 s) über einen Akkumulator, unabhängig von der Bildrate. Ansichten lesen nur; sie schreiben nie in die Regeln. -- **Gemeinsames Materialsystem** (URP, Shader Graph oder HLSL): Stein, Metall, Holz, Vegetation, Kristall, Runen, Wasser. Die G2-Shader aus Godot (stone, metal, crystal, rune, cloth, vein, water_glow, hide) dienen als fachliche Vorlage. Automatische Materialkonvertierungen werden nicht ungeprüft übernommen. -- **Assets:** Quelle sind die Blender-Dateien und Generatoren im Referenz-Repository. Ein zentraler, reproduzierbarer Blender-Export erzeugt FBX für Unity; GLB nur, wo keine bearbeitbare Quelle existiert. +- **Adapter:** Unity treibt `LuneMatch` im festen Takt (0,05 s) über einen Akkumulator, unabhängig von der Bildrate. Ansichten lesen nur; sie schreiben nie in die Regeln. Beispiel: `Gebäude-HP = 0` führt zu Einsturz und Ruine, nie umgekehrt eine Animation zu einer Regelwirkung. +- **Gemeinsames Materialsystem** (URP): Stein, Metall, Holz, Vegetation, Kristall, Runen, Wasser. Die G2-Shader aus Godot (stone, metal, crystal, rune, cloth, vein, water_glow, hide) dienen als fachliche Vorlage. +- **Assets:** Quelle sind die Blender-Dateien und Generatoren im Referenz-Repository. Ein zentraler, reproduzierbarer Blender-Export erzeugt FBX; GLB nur, wo keine bearbeitbare Quelle existiert. +- **Reihenfolge:** Erst sechs repräsentative Assets vollständig prüfen, dann die Welt und eine vollständige Bot-Partie. Den Batchlauf über alle Assets gibt es erst nach dem Vertical Function Test. -## Bestand an Quellen (Godot-Referenz) +## U2A · Blender→FBX-Pipeline -| Gruppe | GLB | Blender-Quelle | -| --- | ---: | --- | -| Truppen, Monster, Sendungen (`assets/models`) | 59 | `assets-source/phase4/blend` (59 `.blend`) | -| Figuren mit Skelett (`assets/characters`) | 6 | `assets-source/phase10`–`phase19` (je ein `.blend` plus Generator) | -| G2-Bauwerke, Grotte, Schlundkrone (`assets/luneraria/g2`) | 6 | `assets-source/luneraria/g2` (`.blend` plus Generatoren) | -| Völker (`assets/luneraria/peoples`) | 7 | `assets-source/luneraria/peoples` | -| Umgebung, Vergleich, übrige | 11 | teilweise; wird im Exportinventar geklärt | +### Aufbau -## Prüfpunkte der Pipeline +| Datei | Aufgabe | +| --- | --- | +| `tools/blender/export_manifest.json` | Asset-Liste: Blender-Quelle, Art (statisch, starre Teile, Skelett), Exportregeln und Verweis auf den Godot-Manifesteintrag des GLB, das die Referenz benutzt | +| `tools/blender/lune_fbx_export.py` | Blender im Hintergrund: Quelle öffnen, Regeln anwenden, prüfen, FBX schreiben, FBX wieder einlesen und erneut prüfen | +| `tools/blender/export_fbx.sh` | Einstieg; macht die FBX-Dateien byteidentisch reproduzierbar | +| `Assets/Luneraria/Art//.fbx` und `.export.json` | Ergebnis: Modell und Protokoll (Blender-Fakten und Prüfungen) | +| `Assets/Luneraria/Editor/Art/LuneModelPostprocessor.cs` | Importregeln in Unity | +| `Assets/Luneraria/Editor/Art/LuneAssetVerifier.cs` | Unity-Prüfung jedes importierten Modells gegen das Blender-Protokoll | +| `Assets/Luneraria/Editor/Art/LuneAssetPreview.cs` | Vorschaubilder in URP | -- Maßstab (1 Einheit = 1 m) und Achsen (Godot Y-oben/−Z-vorn gegenüber Unity Y-oben/+Z-vorn). -- Root Bone und Bone-Namen. -- Clip-Namen: idle, walk, attack_a, attack_b, hit, ability, death, roar, victory. -- Animation Events. -- Materialslots. -- Normalen und Tangenten. -- Blend Shapes, sofern vorhanden. +```bash +sh tools/blender/export_fbx.sh +``` -## Abnahme +```bash +/Applications/Unity/Hub/Editor/6000.3.20f1/Unity.app/Contents/MacOS/Unity -batchmode -projectPath "$PWD" -executeMethod Luneraria.EditorTools.LuneAssetVerifier.VerifyAll -logFile - +``` + +Weitere Einstiege: `LuneAssetVerifier.ReimportArt` (nach geänderten Importregeln) und `LuneAssetPreview.RenderAll`. + +### Exportregeln + +Die Regeln wiederholen, was die Godot-Pipeline beim GLB-Export getan hat. Sonst entstünde ein anderes Modell: + +- **Phase-4-Einheiten:** Die Modifikatoren „HIGH RES“ (Unterteilung und Mikrorelief) kamen erst *nach* dem Laufzeitexport in die `.blend`-Datei. Sie werden nicht angewendet (bei `g01`: 36 Stück). +- **Logische Namen:** Die Namen stammen aus den Eigenschaften `part_name` und `material_name`; Blender hatte teils Suffixe wie `.004` ergänzt. +- **Figuren mit Skelett:** Die `.blend`-Datei ist vor dem Zusammenfügen gespeichert. Der Export fügt die Teile wie in Godot zu einem Skin-Mesh zusammen (Funkenlanze: 104 Teile → `FunkenBody`). +- **Achsen:** Die FBX-Datei behält Blenders Z-oben-Achsen; Unity rechnet sie beim Import mit „Bake Axis Conversion“ um, also ohne Wurzelrotation. Blender (x, y, z) wird dabei Unity (x, z, y); die Vorderseite (Blender −Y) läge auf Unity −Z. + - Deshalb dreht der Export jedes Asset vorher um 180° um die Hochachse und wendet die Drehung an. Danach gilt Unity = (−x, y, z) der Godot-/glTF-Koordinaten, und die Vorderseite liegt auf +Z wie in Godot. + - Blenders „Apply Transform“ ist für Skelette als fehlerhaft dokumentiert und wird nicht benutzt. +- **Maßstab und Inhalt:** 1 Blender-Einheit = 1 m; Normalen, Tangenten (MikkTSpace, wo UVs existieren), lineare Vertexfarben; nur Deform-Bones, keine Leaf-Bones; jede Action wird ein Clip. +- **Reproduzierbarkeit:** Blenders FBX-Schreiber stempelt die Uhrzeit ein und leitet Objekt-IDs aus Pythons String-Hash ab. Der Export fixiert beides (feste Uhrzeit, `PYTHONHASHSEED=0` mit `--python-use-system-env`). Zwei Läufe liefern byteidentische FBX-Dateien und identische Protokolle. + +### Prüfungen + +Blender-Seite, vor und nach dem Schreiben (Rundreise durch einen FBX-Import): + +| Prüfpunkt | Wie | +| --- | --- | +| Einheiten, Maßstab | metrisch, `scale_length` 1, keine Objektskalierung, keine negative Skalierung | +| Achsen, Vorderseite | Drehung angewendet; Vorwärtsmarker (Phase 4: Empty `Forward`) liegt in Unity auf +Z | +| Mesh-Namen | eindeutig; gleich den Knoten des Godot-GLB | +| Dreiecke | gleich dem Godot-GLB, auch nach dem Wiedereinlesen | +| Materialslots | keine leeren Slots; Materialien gleich dem Godot-GLB | +| Normalen | Einheitslänge an allen Ecken | +| Tangenten | Voraussetzungen (UVs, keine N-Ecke); Meshes ohne UVs sind vermerkt und werden triplanar oder unbeleuchtet schattiert | +| Maße | Ruhelage gleich den `bounds_godot` des Godot-Manifests (Türme und Ancient: ohne Schadens- und Ruinenteile, wie dort gemessen) | +| Skelett | genau eine Armature, ein Root Bone `Root`, Bone-Namen und -Anzahl wie im Godot-GLB, portable Namen | +| Clips | Namen und Längen wie im Godot-GLB; Pflichtclips vorhanden; Loop-Flag und Kontaktzeit aus den Action-Eigenschaften | +| Blend Shapes | keine in den Quellen | + +Unity-Seite (`LuneAssetVerifier`, gegen das Blender-Protokoll): + +| Prüfpunkt | Wie | +| --- | --- | +| Importregeln | Maßstab 1, Dateieinheiten, Achsen-Bake, Normalen und Tangenten aus der Datei | +| Achsen | Wurzel und alle Nicht-Bone-Knoten ohne Rotation und Skalierung | +| Mesh-Namen, Dreiecke | Menge und Anzahl je Mesh gleich | +| Maße | aus den Vertices berechnet, Abweichung höchstens 2 mm; gemessen höchstens 0,05 mm | +| Materialslots | Namen je Renderer gleich den Blender-Slots | +| Normalen, Tangenten, UVs, Vertexfarben | vorhanden und gültig, wo Blender sie hat; Tangenten mit w = ±1 | +| Vorderseite | Vorwärtsmarker auf +Z | +| Skelett | Root Bone, Bone-Namen, gültiger Generic-Avatar | +| Clips | Namen, Längen (auf einen halben Frame genau), Loop-Flags, Kontakt-Events (`OnLuneContact`) | + +### Ergebnis: sechs repräsentative Assets und drei Szenenbauten + +| Asset | vertritt | Dreiecke (= Godot-GLB) | Blender-Prüfungen | Unity-Prüfungen | +| --- | --- | ---: | --- | --- | +| `g01` Kohlenbeißer | normale Einheit, 131 benannte Teile | 79.780 | 18/18 | 14/14 | +| `funkenlanze` | Einheit mit Skelett (Held), 26 Bones, 9 Clips | 24.036 | 26/26 | 18/18 | +| `grenzwacht` | Turm (mit Schadens- und Ruinenteilen) | 6.516 | 18/18 | 13/13 | +| `ancient` Mondherz | Ancient | 19.032 | 18/18 | 13/13 | +| `schlundkrone` | Schlundkrone (Boss), 24 Bones, 11 Clips | 5.712 | 28/28 | 18/18 | +| `map_props` | Vegetation und Kartenrequisiten (Eichen, Kiefern, Sträucher, Felsen, Brücke, Randsteine) | 7.338 | 14/14 | 13/13 | +| `bastion`, `kernwacht`, `bossgrotte` | für die Szene in U2B (Innen- und Basisturm, Mondschlund) | 9.364, 9.224, 15.182 | je 18/18 | je 13/13 | + +Summe: 176 Blender-Prüfungen und 128 Unity-Prüfungen, alle bestanden. Protokolle: +- `Assets/Luneraria/Art/*/*.export.json` (Blender). +- `docs/port/logs/u2a/unity-verify.json` (Unity). + +Bilder unter `docs/port/screenshots/u2a/`: +- je Asset eine Ansicht von vorn-rechts, +- die Grenzwacht zusätzlich als Ruine, +- Funkenlanze und Schlundkrone zusätzlich im Kontaktframe von `attack_a` (Clips laufen). + +### Bekannte Grenzen + +- **Materialien:** Die Vorschau benutzt URP-Lit-Materialien, die Unity aus den FBX-Materialbeschreibungen erzeugt (Blender-Palettenfarben). Das eigentliche Materialsystem (Stein, Metall, Kristall, Runen, Stoff, Wasser; Teamfarben; Vertex-AO) folgt in U2B. + - Stoff (Wimpel, Banner) ist einseitig modelliert und braucht dort doppelseitiges Rendern; in der Vorschau fehlt er deshalb. +- **Ohne UVs:** Diese Meshes haben keine Tangenten (Unity meldet das beim Import): Kristalle, Trümmer, Felsen, Kartenrequisiten und einige Phase-4-Kleinteile. Sie brauchen triplanare oder unbeleuchtete Materialien. +- **Starre Einheiten:** Die Phase-4-Einheiten werden in Godot aus benannten Teilen prozedural animiert. Die Teile kommen mit, die Animation folgt mit den Einheitenansichten. +- **Größe:** Die FBX-Dateien liegen direkt im Repository (9 Dateien, 16 MB). Für den Batchlauf über alle Assets ist Git LFS zu erwägen. + +### Batchlauf (nach dem Vertical Function Test) + +Das Manifest enthält bisher die 9 Assets der Szene. Die übrigen Assets kommen erst nach U2D in das Manifest und werden dann mit denselben Regeln und Prüfungen exportiert: +- 58 weitere Phase-4-Modelle. +- 5 Figuren mit Skelett. +- 7 Völker-Modelle. Für Zwerg und Troll fehlt die `.blend`-Datei im Referenz-Repository; sie entsteht aus dem Generator `build_peoples.py`. + +Bauten aus einer GLB ohne Quelle folgen nur nach Einzelfallprüfung. + +## U2B bis U2D + +Folgen in diesem Dokument. + +## Abnahme (gesamt) - Die Partie läuft sichtbar. - Die Kamera entspricht der Godot-Kamera. - Screenshots neben den Godot-G2-Bildern mit vergleichbarer Kamera. - Leistung gemessen, einschließlich Mono-Simulationszeit. - Bekannte Unterschiede dokumentiert. -- Commit auf `luneraria/u2`. +- Commits U2A bis U2D auf `luneraria/u2`. diff --git a/docs/port/logs/u2a/unity-verify.json b/docs/port/logs/u2a/unity-verify.json new file mode 100644 index 0000000..921e009 --- /dev/null +++ b/docs/port/logs/u2a/unity-verify.json @@ -0,0 +1,968 @@ +{ + "unity": "6000.3.20f1", + "ok": true, + "assets": [ + { + "id": "ancient", + "kind": "static", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Buildings/ancient.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"ancient pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"19032 unity / 19032 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00005 m; unity (-4.204, -0.988, -4.000) (4.204, 10.367, 4.000)\"" + } + ], + "facts": { + "triangles": 19032, + "renderers": 27, + "meshes_without_uv_and_tangents": 14, + "bounds_min": [ + -4.20353031, + -0.9881463, + -4.0 + ], + "bounds_max": [ + 4.20352936, + 10.3668232, + 4.0 + ] + } + }, + { + "id": "bastion", + "kind": "static", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Buildings/bastion.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"bastion pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"9364 unity / 9364 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00005 m; unity (-2.116, -0.389, -2.539) (2.901, 7.161, 1.950)\"" + } + ], + "facts": { + "triangles": 9364, + "renderers": 11, + "meshes_without_uv_and_tangents": 6, + "bounds_min": [ + -2.11555481, + -0.3890798, + -2.538877 + ], + "bounds_max": [ + 2.90077925, + 7.160508, + 1.94963574 + ] + } + }, + { + "id": "bossgrotte", + "kind": "static", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Buildings/bossgrotte.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"bossgrotte pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"15182 unity / 15182 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00004 m; unity (-7.777, -1.930, -10.465) (10.544, 7.693, 7.798)\"" + } + ], + "facts": { + "triangles": 15182, + "renderers": 12, + "meshes_without_uv_and_tangents": 4, + "bounds_min": [ + -7.77746248, + -1.93, + -10.4646072 + ], + "bounds_max": [ + 10.5441828, + 7.69265556, + 7.79764366 + ] + } + }, + { + "id": "grenzwacht", + "kind": "static", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Buildings/grenzwacht.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"grenzwacht pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"6516 unity / 6516 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00005 m; unity (-2.258, -0.065, -2.553) (1.966, 6.060, 1.368)\"" + } + ], + "facts": { + "triangles": 6516, + "renderers": 7, + "meshes_without_uv_and_tangents": 2, + "bounds_min": [ + -2.25751829, + -0.06533188, + -2.55256557 + ], + "bounds_max": [ + 1.96584618, + 6.060136, + 1.36833835 + ] + } + }, + { + "id": "kernwacht", + "kind": "static", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Buildings/kernwacht.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"kernwacht pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"9224 unity / 9224 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00004 m; unity (-6.076, -2.396, -2.194) (2.396, 8.330, 1.813)\"" + } + ], + "facts": { + "triangles": 9224, + "renderers": 9, + "meshes_without_uv_and_tangents": 2, + "bounds_min": [ + -6.07622528, + -2.39588761, + -2.19388914 + ], + "bounds_max": [ + 2.39623713, + 8.33, + 1.81258774 + ] + } + }, + { + "id": "funkenlanze", + "kind": "skinned", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Characters/funkenlanze.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"funkenlanze pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"24036 unity / 24036 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00005 m; unity (-0.565, -0.010, -0.295) (0.430, 2.021, 1.435)\"" + }, + { + "check": "skinned_mesh", + "ok": true, + "detail": "1" + }, + { + "check": "bone_names FunkenBody", + "ok": true, + "detail": "[]" + }, + { + "check": "root_bone FunkenBody", + "ok": true, + "detail": "\"Root\"" + }, + { + "check": "generic_avatar", + "ok": true, + "detail": "\"funkenlanzeAvatar\"" + }, + { + "check": "clips", + "ok": true, + "detail": "[]" + } + ], + "facts": { + "triangles": 24036, + "renderers": 1, + "meshes_without_uv_and_tangents": 0, + "bounds_min": [ + -0.5651692, + -0.0104093477, + -0.2945487 + ], + "bounds_max": [ + 0.43, + 2.02119541, + 1.43500006 + ], + "clips": [ + { + "name": "ability", + "length": 1.3, + "loop": false, + "events": 1 + }, + { + "name": "attack_a", + "length": 1.3, + "loop": false, + "events": 1 + }, + { + "name": "attack_b", + "length": 1.3, + "loop": false, + "events": 1 + }, + { + "name": "death", + "length": 2.0, + "loop": false, + "events": 0 + }, + { + "name": "hit", + "length": 0.5, + "loop": false, + "events": 0 + }, + { + "name": "idle", + "length": 3.0, + "loop": true, + "events": 0 + }, + { + "name": "start", + "length": 0.4, + "loop": false, + "events": 0 + }, + { + "name": "stop", + "length": 0.4, + "loop": false, + "events": 0 + }, + { + "name": "walk", + "length": 1.2, + "loop": true, + "events": 0 + } + ] + } + }, + { + "id": "schlundkrone", + "kind": "skinned", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Characters/schlundkrone.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"schlundkrone pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"5712 unity / 5712 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00005 m; unity (-1.327, 0.005, -0.553) (1.231, 3.318, 0.925)\"" + }, + { + "check": "skinned_mesh", + "ok": true, + "detail": "1" + }, + { + "check": "bone_names SchlundkroneBody", + "ok": true, + "detail": "[]" + }, + { + "check": "root_bone SchlundkroneBody", + "ok": true, + "detail": "\"Root\"" + }, + { + "check": "generic_avatar", + "ok": true, + "detail": "\"schlundkroneAvatar\"" + }, + { + "check": "clips", + "ok": true, + "detail": "[]" + } + ], + "facts": { + "triangles": 5712, + "renderers": 1, + "meshes_without_uv_and_tangents": 0, + "bounds_min": [ + -1.32726932, + 0.00534708425, + -0.5531612 + ], + "bounds_max": [ + 1.23073983, + 3.31821656, + 0.9253263 + ], + "clips": [ + { + "name": "ability", + "length": 1.3, + "loop": false, + "events": 0 + }, + { + "name": "attack_a", + "length": 1.3, + "loop": false, + "events": 1 + }, + { + "name": "attack_b", + "length": 1.3, + "loop": false, + "events": 1 + }, + { + "name": "death", + "length": 2.2, + "loop": false, + "events": 0 + }, + { + "name": "hit", + "length": 0.5, + "loop": false, + "events": 0 + }, + { + "name": "idle", + "length": 3.0, + "loop": true, + "events": 0 + }, + { + "name": "roar", + "length": 2.0, + "loop": false, + "events": 0 + }, + { + "name": "start", + "length": 0.4, + "loop": false, + "events": 0 + }, + { + "name": "stop", + "length": 0.4, + "loop": false, + "events": 0 + }, + { + "name": "victory", + "length": 2.0, + "loop": false, + "events": 0 + }, + { + "name": "walk", + "length": 1.6, + "loop": true, + "events": 0 + } + ] + } + }, + { + "id": "map_props", + "kind": "static", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Environment/map_props.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"map_props pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"7338 unity / 7338 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00002 m; unity (-7.368, -1.300, -3.900) (7.455, 5.244, 3.900)\"" + } + ], + "facts": { + "triangles": 7338, + "renderers": 15, + "meshes_without_uv_and_tangents": 15, + "bounds_min": [ + -7.368419, + -1.3, + -3.90000057 + ], + "bounds_max": [ + 7.455483, + 5.244, + 3.90000057 + ] + } + }, + { + "id": "g01", + "kind": "rigid", + "ok": true, + "checks": [ + { + "check": "blender_checks_passed", + "ok": true, + "detail": "" + }, + { + "check": "imported", + "ok": true, + "detail": "\"Assets/Luneraria/Art/Units/g01.fbx\"" + }, + { + "check": "import_rules_applied", + "ok": true, + "detail": "" + }, + { + "check": "root_transform_identity", + "ok": true, + "detail": "\"g01 pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\"" + }, + { + "check": "node_transforms_axis_clean", + "ok": true, + "detail": "[]" + }, + { + "check": "mesh_names", + "ok": true, + "detail": "[]" + }, + { + "check": "triangles", + "ok": true, + "detail": "\"79780 unity / 79780 blender \"" + }, + { + "check": "material_slots", + "ok": true, + "detail": "[]" + }, + { + "check": "normals_unit_length", + "ok": true, + "detail": "[]" + }, + { + "check": "tangents_where_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "uvs_where_blender_has_uv", + "ok": true, + "detail": "[]" + }, + { + "check": "vertex_colors", + "ok": true, + "detail": "[]" + }, + { + "check": "bounds_axes_scale", + "ok": true, + "detail": "\"largest difference 0.00004 m; unity (-0.792, 0.000, -0.447) (0.792, 1.350, 0.447)\"" + }, + { + "check": "forward_is_plus_z", + "ok": true, + "detail": "\"(0.000, 0.000, 0.750)\"" + } + ], + "facts": { + "triangles": 79780, + "renderers": 131, + "meshes_without_uv_and_tangents": 38, + "bounds_min": [ + -0.792443752, + 0.0, + -0.447301447 + ], + "bounds_max": [ + 0.7924438, + 1.35, + 0.447301567 + ] + } + } + ] +} diff --git a/docs/port/screenshots/u2a/ancient.png b/docs/port/screenshots/u2a/ancient.png new file mode 100644 index 0000000..83ecd5a Binary files /dev/null and b/docs/port/screenshots/u2a/ancient.png differ diff --git a/docs/port/screenshots/u2a/bastion.png b/docs/port/screenshots/u2a/bastion.png new file mode 100644 index 0000000..55e7a25 Binary files /dev/null and b/docs/port/screenshots/u2a/bastion.png differ diff --git a/docs/port/screenshots/u2a/bossgrotte.png b/docs/port/screenshots/u2a/bossgrotte.png new file mode 100644 index 0000000..9ef89dd Binary files /dev/null and b/docs/port/screenshots/u2a/bossgrotte.png differ diff --git a/docs/port/screenshots/u2a/funkenlanze-attack_a.png b/docs/port/screenshots/u2a/funkenlanze-attack_a.png new file mode 100644 index 0000000..c99caf6 Binary files /dev/null and b/docs/port/screenshots/u2a/funkenlanze-attack_a.png differ diff --git a/docs/port/screenshots/u2a/funkenlanze.png b/docs/port/screenshots/u2a/funkenlanze.png new file mode 100644 index 0000000..65047cb Binary files /dev/null and b/docs/port/screenshots/u2a/funkenlanze.png differ diff --git a/docs/port/screenshots/u2a/g01.png b/docs/port/screenshots/u2a/g01.png new file mode 100644 index 0000000..5dff8fe Binary files /dev/null and b/docs/port/screenshots/u2a/g01.png differ diff --git a/docs/port/screenshots/u2a/grenzwacht-ruin.png b/docs/port/screenshots/u2a/grenzwacht-ruin.png new file mode 100644 index 0000000..fe46aac Binary files /dev/null and b/docs/port/screenshots/u2a/grenzwacht-ruin.png differ diff --git a/docs/port/screenshots/u2a/grenzwacht.png b/docs/port/screenshots/u2a/grenzwacht.png new file mode 100644 index 0000000..96b027b Binary files /dev/null and b/docs/port/screenshots/u2a/grenzwacht.png differ diff --git a/docs/port/screenshots/u2a/kernwacht.png b/docs/port/screenshots/u2a/kernwacht.png new file mode 100644 index 0000000..91c6ab7 Binary files /dev/null and b/docs/port/screenshots/u2a/kernwacht.png differ diff --git a/docs/port/screenshots/u2a/map_props.png b/docs/port/screenshots/u2a/map_props.png new file mode 100644 index 0000000..8ba33b7 Binary files /dev/null and b/docs/port/screenshots/u2a/map_props.png differ diff --git a/docs/port/screenshots/u2a/schlundkrone-attack_a.png b/docs/port/screenshots/u2a/schlundkrone-attack_a.png new file mode 100644 index 0000000..032ed4c Binary files /dev/null and b/docs/port/screenshots/u2a/schlundkrone-attack_a.png differ diff --git a/docs/port/screenshots/u2a/schlundkrone.png b/docs/port/screenshots/u2a/schlundkrone.png new file mode 100644 index 0000000..ab43a22 Binary files /dev/null and b/docs/port/screenshots/u2a/schlundkrone.png differ diff --git a/tools/blender/export_fbx.sh b/tools/blender/export_fbx.sh new file mode 100644 index 0000000..5157f1f --- /dev/null +++ b/tools/blender/export_fbx.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# Blender -> FBX export of the Unity port (U2A): sh tools/blender/export_fbx.sh [id,id,...] +# Without ids every asset of tools/blender/export_manifest.json is exported. Needs Blender 5.2 +# (BLENDER, default "blender") and the Godot reference (GODOT_PROJECT, default ../saumwacht-godot). +# PYTHONHASHSEED=0 with --python-use-system-env makes the FBX object ids reproducible. +set -eu +cd "$(dirname "$0")/../.." +BLENDER="${BLENDER:-blender}" +GODOT_PROJECT="${GODOT_PROJECT:-../saumwacht-godot}" +PYTHONHASHSEED=0 "$BLENDER" --background --factory-startup --python-use-system-env \ + --python tools/blender/lune_fbx_export.py -- --godot "$GODOT_PROJECT" --ids "${1:-}" diff --git a/tools/blender/export_manifest.json b/tools/blender/export_manifest.json new file mode 100644 index 0000000..8d52a1e --- /dev/null +++ b/tools/blender/export_manifest.json @@ -0,0 +1,58 @@ +{ + "comment": "Export rules per asset for tools/blender/lune_fbx_export.py. source: Blender file in the Godot reference (../saumwacht-godot). godot_manifest: the manifest entry of the GLB the reference game uses; the FBX must match it (triangles, names, materials, bounds, bones, clips). kind: static | rigid (named parts, animated by the view) | skinned.", + "assets": [ + { + "id": "g01", "group": "Units", "kind": "rigid", "representative": "normal unit (Glutpakt melee, 131 named parts)", + "source": "assets-source/phase4/blend/g01.blend", + "godot_manifest": {"file": "assets/phase4_manifest.json", "id": "g01"}, + "rules": {"skip_modifiers": ["HIGH RES"], "logical_names": true, "forward_marker": "Forward", "check_parts": false} + }, + { + "id": "funkenlanze", "group": "Characters", "kind": "skinned", "representative": "rigged unit (hero Funkenlanze)", + "source": "assets-source/phase18/funkenlanze.blend", + "godot_manifest": {"file": "assets/phase18_manifest.json", "id": "g05"}, + "rules": {"join": {"parent": "FunkenRig", "into": "FunkenBody"}, "rest_action": null, "root_bone": "Root", + "required_clips": ["idle", "walk", "attack_a", "attack_b", "hit", "ability", "death"]} + }, + { + "id": "grenzwacht", "group": "Buildings", "kind": "static", "representative": "tower (outer lane tower)", + "source": "assets-source/luneraria/g2/grenzwacht.blend", + "godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "grenzwacht"}, + "rules": {"bounds_exclude": ["Upper_Damaged", "Debris", "Ruin", "Pennant", "Banner"]} + }, + { + "id": "ancient", "group": "Buildings", "kind": "static", "representative": "Ancient (Mondherz)", + "source": "assets-source/luneraria/g2/ancient.blend", + "godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "ancient"}, + "rules": {"bounds_exclude": ["Banner", "Ruin_"]} + }, + { + "id": "schlundkrone", "group": "Characters", "kind": "skinned", "representative": "Schlundkrone (boss)", + "source": "assets-source/luneraria/g2/schlundkrone.blend", + "godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "schlundkrone"}, + "rules": {"rest_action": null, "root_bone": "Root", + "required_clips": ["idle", "walk", "attack_a", "attack_b", "hit", "ability", "death", "roar", "victory"]} + }, + { + "id": "map_props", "group": "Environment", "kind": "static", "representative": "vegetation and map props (oaks, pines, shrubs, rocks, bridge, curb)", + "source": "assets-source/luneraria/map_props.blend" + }, + { + "id": "bastion", "group": "Buildings", "kind": "static", + "source": "assets-source/luneraria/g2/bastion.blend", + "godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "bastion"}, + "rules": {"bounds_exclude": ["Upper_Damaged", "Debris", "Ruin", "Pennant", "Banner"]} + }, + { + "id": "kernwacht", "group": "Buildings", "kind": "static", + "source": "assets-source/luneraria/g2/kernwacht.blend", + "godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "kernwacht"}, + "rules": {"bounds_exclude": ["Upper_Damaged", "Debris", "Ruin", "Pennant", "Banner"]} + }, + { + "id": "bossgrotte", "group": "Buildings", "kind": "static", + "source": "assets-source/luneraria/g2/bossgrotte.blend", + "godot_manifest": {"file": "assets/luneraria/g2/g2_manifest.json", "id": "bossgrotte"} + } + ] +} diff --git a/tools/blender/inspect_blend.py b/tools/blender/inspect_blend.py new file mode 100644 index 0000000..357a925 --- /dev/null +++ b/tools/blender/inspect_blend.py @@ -0,0 +1,33 @@ +"""Prints a JSON summary of a .blend file (objects, meshes, materials, armatures, actions). +Usage: blender --background --python tools/blender/inspect_blend.py -- """ +import bpy, json, sys +out = sys.argv[sys.argv.index('--') + 1] if '--' in sys.argv else None +scene = bpy.context.scene +info = {'file': bpy.data.filepath, 'unit_system': scene.unit_settings.system, 'scale_length': scene.unit_settings.scale_length, + 'fps': scene.render.fps, 'objects': [], 'actions': []} +for obj in bpy.data.objects: + entry = {'name': obj.name, 'type': obj.type, 'parent': obj.parent.name if obj.parent else None, + 'location': [round(v, 4) for v in obj.location], 'rotation': [round(v, 4) for v in obj.rotation_euler], + 'scale': [round(v, 4) for v in obj.scale], 'in_scene': obj.name in scene.objects, + 'hide_render': obj.hide_render} + if obj.type == 'MESH': + me = obj.data + entry.update({'mesh': me.name, 'verts': len(me.vertices), 'polys': len(me.polygons), + 'ngons': sum(1 for p in me.polygons if len(p.vertices) > 4), + 'materials': [m.name if m else None for m in me.materials], 'uv_layers': [uv.name for uv in me.uv_layers], + 'color_attributes': [(c.name, c.domain, c.data_type) for c in me.color_attributes], + 'custom_normals': me.has_custom_normals, 'shape_keys': [k.name for k in me.shape_keys.key_blocks] if me.shape_keys else [], + 'modifiers': [(m.type, m.name) for m in obj.modifiers], 'vertex_groups': len(obj.vertex_groups)}) + if obj.type == 'ARMATURE': + arm = obj.data + entry.update({'bones': len(arm.bones), 'roots': [b.name for b in arm.bones if b.parent is None], + 'bone_names': [b.name for b in arm.bones][:80], 'action': obj.animation_data.action.name if obj.animation_data and obj.animation_data.action else None, + 'nla': [(t.name, [s.action.name for s in t.strips if s.action]) for t in obj.animation_data.nla_tracks] if obj.animation_data else []}) + info['objects'].append(entry) +for act in bpy.data.actions: + info['actions'].append({'name': act.name, 'range': [round(v, 2) for v in act.frame_range], 'users': act.users, 'fake_user': act.use_fake_user}) +text = json.dumps(info, indent=1) +if out: + open(out, 'w').write(text) +else: + print(text) diff --git a/tools/blender/lune_fbx_export.py b/tools/blender/lune_fbx_export.py new file mode 100644 index 0000000..d7ea485 --- /dev/null +++ b/tools/blender/lune_fbx_export.py @@ -0,0 +1,454 @@ +"""Reproducible Blender -> FBX export for the Unity port (docs/port/U2-WORLD.md, U2A). + +Runs headless on the Blender sources of the Godot reference, applies the per-asset export +rules of tools/blender/export_manifest.json, checks the result and writes, per asset: + + Assets/Luneraria/Art//.fbx the model for Unity + Assets/Luneraria/Art//.export.json facts and checks (read by Unity's importer) + +Checks: units and scale, up and forward axis, object transforms, mesh names, triangle counts, +material slots, UVs, normals, tangent prerequisites, vertex colours, root bone, bone names, +clips (names, lengths, loop flags, contact events), bounds. Expectations come from the Godot +manifests of the GLBs the reference game uses, so the FBX must describe the same model. +After writing, the FBX is imported into an empty scene and checked again (round trip). + +Usage (from the Unity project root): sh tools/blender/export_fbx.sh [id,id,...] + (runs blender --background --factory-startup --python-use-system-env with PYTHONHASHSEED=0 + --python tools/blender/lune_fbx_export.py -- --godot ../saumwacht-godot --ids ) +Exit code 0 only if every check of every asset passed. +""" +import bpy +import hashlib +import json +import math +import sys +from pathlib import Path + +from mathutils import Matrix, Vector + +UNITY_ROOT = Path(__file__).resolve().parents[2] +EXPORTER_VERSION = 5 + +# One export setting for every asset. The file keeps Blender's Z-up axes; Unity's importer +# converts them with "Bake Axis Conversion" as Unity (x, y, z) = Blender (x, z, y), so no root +# carries a rotation and animation data is converted with the meshes (Blender's own "Apply +# Transform" is documented as broken for armatures). Before export every asset is turned by 180 +# degrees about Blender's Z and the turn is applied (face_unity_forward): the front (Blender -Y, +# glTF/Godot +Z) then becomes Unity +Z, and Unity = (-x, y, z) of the Godot coordinates. +FBX_SETTINGS = dict( + use_selection=True, use_visible=False, use_active_collection=False, + global_scale=1.0, apply_unit_scale=True, apply_scale_options='FBX_SCALE_UNITS', + axis_forward='Y', axis_up='Z', bake_space_transform=False, + object_types={'EMPTY', 'MESH', 'ARMATURE'}, + use_mesh_modifiers=True, use_mesh_modifiers_render=True, + mesh_smooth_type='OFF', use_subsurf=False, use_mesh_edges=False, use_tspace=True, + use_triangles=False, colors_type='LINEAR', prioritize_active_color=True, + use_custom_props=False, + add_leaf_bones=False, primary_bone_axis='Y', secondary_bone_axis='X', + use_armature_deform_only=True, armature_nodetype='NULL', + bake_anim=True, bake_anim_use_all_bones=True, bake_anim_use_nla_strips=False, + bake_anim_use_all_actions=True, bake_anim_force_startend_keying=True, + bake_anim_step=1.0, bake_anim_simplify_factor=0.0, + path_mode='STRIP', embed_textures=False, batch_mode='OFF', +) + + +def args(): + argv = sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else [] + result = {'manifest': str(UNITY_ROOT / 'tools/blender/export_manifest.json'), 'godot': str(UNITY_ROOT.parent / 'saumwacht-godot'), 'ids': ''} + for i in range(0, len(argv) - 1, 2): + result[argv[i].lstrip('-')] = argv[i + 1] + return result + + +class Report: + def __init__(self, spec): + self.data = {'id': spec['id'], 'group': spec['group'], 'source': spec['source'], 'exporter_version': EXPORTER_VERSION, + 'blender': bpy.app.version_string, 'fbx_settings': {k: (sorted(v) if isinstance(v, set) else v) for k, v in FBX_SETTINGS.items()}, + 'checks': []} + + def check(self, name, ok, detail=''): + self.data['checks'].append({'check': name, 'ok': bool(ok), 'detail': str(detail)}) + return ok + + @property + def ok(self): + return all(c['ok'] for c in self.data['checks']) + + +def godot_expectations(spec, godot_root): + """Facts of the GLB the reference uses, from its manifest (triangles, nodes, bounds, ...).""" + source = spec.get('godot_manifest') + if not source: + return {} + data = json.loads((godot_root / source['file']).read_text()) + assets = data['assets'] if isinstance(data, dict) and 'assets' in data else data + for entry in assets: + if entry.get('id') == source['id']: + return entry + raise KeyError('no entry %s in %s' % (source['id'], source['file'])) + + +def triangles(mesh): + return sum(len(p.vertices) - 2 for p in mesh.polygons) + + +def evaluated_mesh(obj, depsgraph): + evaluated = obj.evaluated_get(depsgraph) + return evaluated, evaluated.to_mesh() + + +def prepare(spec, report): + """Applies the export rules of the manifest to the opened .blend (never saved).""" + rules = spec.get('rules', {}) + skip = tuple(rules.get('skip_modifiers', ())) + removed = 0 + if skip: + for obj in bpy.data.objects: + for modifier in list(obj.modifiers): + if modifier.name.startswith(skip): + obj.modifiers.remove(modifier) + removed += 1 + report.data['removed_modifiers'] = removed + if rules.get('logical_names'): + logical_names(report) + join = rules.get('join') + if join: + parts = [o for o in bpy.context.scene.objects if o.type == 'MESH' and o.parent and o.parent.name == join['parent']] + bpy.ops.object.select_all(action='DESELECT') + for obj in parts: + obj.select_set(True) + bpy.context.view_layer.objects.active = parts[0] + bpy.ops.object.join() + bpy.context.object.name = join['into'] + bpy.context.object.data.name = join['into'] + report.data['joined_parts'] = len(parts) + face_unity_forward(report) + rest_action = rules.get('rest_action') + for obj in bpy.context.scene.objects: + if obj.type == 'ARMATURE' and obj.animation_data: + # Export the bind pose, not the last evaluated frame of some action. + obj.animation_data.action = bpy.data.actions.get(rest_action) if rest_action else None + bpy.context.scene.frame_set(0) + + +def face_unity_forward(report): + """Turns every root 180 degrees about Z and applies the turn to all objects (meshes, empties, + armatures with their rest pose). Bone animation is stored relative to the rest pose and + stays valid. Shared mesh data is made single-user first.""" + turn = Matrix.Rotation(math.pi, 4, 'Z') + scene_objects = [o for o in bpy.context.scene.objects if o.type in ('MESH', 'ARMATURE', 'EMPTY')] + for obj in scene_objects: + if obj.parent is None: + obj.matrix_world = turn @ obj.matrix_world + bpy.ops.object.select_all(action='DESELECT') + for obj in scene_objects: + obj.hide_set(False) + obj.hide_select = False + obj.select_set(True) + bpy.context.view_layer.objects.active = scene_objects[0] + bpy.ops.object.transform_apply(location=False, rotation=True, scale=False, isolate_users=True) + turned = [o.name for o in scene_objects if o.matrix_world.to_euler().z != 0.0 and abs(o.matrix_world.to_euler().z) > 1e-5] + report.check('turn_applied', not turned, turned[:8]) + + +def logical_names(report): + """Phase-4 sources keep their logical names in custom properties (part_name, material_name); + Blender may have suffixed the datablocks (.004). The Godot pipeline renamed the GLB nodes the + same way (assets-source/phase4/blender/pipeline.py, _canonical_glb_names). Materials that share + a logical name are one material and are merged.""" + renamed = 0 + for obj in list(bpy.data.objects): + if 'part_name' in obj.keys(): + obj.name = '__lune_tmp_' + obj.name + for obj in list(bpy.data.objects): + if 'part_name' in obj.keys(): + obj.name = obj['part_name'] + renamed += int(obj.name == obj['part_name']) + groups = {} + for material in list(bpy.data.materials): + logical = material.get('material_name') + if logical: + groups.setdefault(logical, []).append(material) + merged = 0 + for logical, materials in groups.items(): + keep = materials[0] + for other in materials[1:]: + other.user_remap(keep) + merged += 1 + for material in materials[1:]: + bpy.data.materials.remove(material) + keep.name = '__lune_tmp_' + logical + for logical in groups: + bpy.data.materials['__lune_tmp_' + logical].name = logical + collisions = [o.name for o in bpy.data.objects if 'part_name' in o.keys() and o.name != o['part_name']] + report.check('logical_names_unique', not collisions, collisions[:12]) + report.data['logical_names'] = {'objects': renamed, 'materials': len(groups), 'merged_materials': merged} + + +def export_objects(spec): + include = spec.get('rules', {}).get('objects') + objects = [] + for obj in bpy.context.scene.objects: + if obj.type not in ('MESH', 'ARMATURE', 'EMPTY'): + continue + if include and obj.name not in include: + continue + if obj.hide_render: + continue + objects.append(obj) + return objects + + +def to_unity(v): + """Blender (x, y, z), after the turn of face_unity_forward -> Unity (x, y, z) = (x, z, y).""" + return Vector((v.x, v.z, v.y)) + + +def facts(objects, depsgraph): + """Scene facts in Unity coordinates: meshes, materials, bounds, bones, actions.""" + meshes = {} + low = Vector((math.inf,) * 3) + high = Vector((-math.inf,) * 3) + for obj in objects: + if obj.type != 'MESH': + continue + evaluated, mesh = evaluated_mesh(obj, depsgraph) + world = evaluated.matrix_world + # Skinned meshes: bounds of the rest pose (armature modifier is evaluated in the bind pose). + mesh_low = Vector((math.inf,) * 3) + mesh_high = Vector((-math.inf,) * 3) + for vertex in mesh.vertices: + p = to_unity(world @ vertex.co) + mesh_low = Vector(map(min, mesh_low, p)) + mesh_high = Vector(map(max, mesh_high, p)) + low = Vector(map(min, low, mesh_low)) + high = Vector(map(max, high, mesh_high)) + normals_ok = all(abs(n.vector.length - 1.0) < 1e-3 for n in mesh.corner_normals) + meshes[obj.name] = { + 'mesh': obj.data.name, 'triangles': triangles(mesh), 'vertices': len(mesh.vertices), + 'ngons': sum(1 for p in mesh.polygons if len(p.vertices) > 4), + 'materials': [slot.material.name if slot.material else None for slot in obj.material_slots], + 'uv_layers': [uv.name for uv in mesh.uv_layers], + 'color_attributes': [c.name for c in mesh.color_attributes], + 'active_color': mesh.color_attributes.active_color.name if mesh.color_attributes.active_color else None, + 'custom_normals': obj.data.has_custom_normals, 'normals_unit_length': normals_ok, + 'shape_keys': len(obj.data.shape_keys.key_blocks) - 1 if obj.data.shape_keys else 0, + 'skinned': any(m.type == 'ARMATURE' for m in obj.modifiers), + 'scale': [round(s, 6) for s in obj.matrix_world.to_scale()], + 'bounds_unity': {'min': [round(c, 4) for c in mesh_low], 'max': [round(c, 4) for c in mesh_high]}, + } + evaluated.to_mesh_clear() + armatures = {} + for obj in objects: + if obj.type == 'ARMATURE': + bones = [b for b in obj.data.bones if b.use_deform] + armatures[obj.name] = {'bones': [b.name for b in bones], 'roots': [b.name for b in bones if b.parent is None or not b.parent.use_deform]} + empties = {o.name: [round(c, 4) for c in to_unity(o.matrix_world.translation)] for o in objects if o.type == 'EMPTY'} + return {'meshes': meshes, 'armatures': armatures, 'empties': empties, + 'bounds_unity': {'min': [round(c, 4) for c in low], 'max': [round(c, 4) for c in high]} if meshes else None} + + +def clip_facts(fps): + clips = [] + for action in bpy.data.actions: + start, end = action.frame_range + clips.append({'name': action.name, 'frames': [round(start, 3), round(end, 3)], 'seconds': round((end - start) / fps, 4), + 'loop': bool(action.get('loop', action.name in ('idle', 'walk'))), + 'contact_seconds': float(action.get('contact_seconds', -1.0))}) + return clips + + +def godot_to_unity_bounds(bounds): + """Godot/glTF bounds (x, y, z) -> Unity (-x, y, z).""" + lo, hi = bounds['min'], bounds['max'] + return {'min': [-hi[0], lo[1], lo[2]], 'max': [-lo[0], hi[1], hi[2]]} + + +def run_checks(spec, report, before, clips, expect): + scene = bpy.context.scene + report.check('units_metric', scene.unit_settings.system == 'METRIC', scene.unit_settings.system) + report.check('unit_scale_1', abs(scene.unit_settings.scale_length - 1.0) < 1e-9, scene.unit_settings.scale_length) + meshes = before['meshes'] + bad_scale = {n: m['scale'] for n, m in meshes.items() if any(abs(s - 1.0) > 1e-4 for s in m['scale'])} + negative = {n: s for n, s in bad_scale.items() if any(c < 0 for c in s)} + report.check('no_negative_scale', not negative, negative) + report.check('object_scale_1', not bad_scale or spec.get('rules', {}).get('allow_object_scale', False), bad_scale) + names = [m['mesh'] for m in meshes.values()] + report.check('mesh_names_unique', len(set(meshes)) == len(meshes), sorted(meshes)) + empty_slots = {n: m['materials'] for n, m in meshes.items() if None in m['materials'] or not m['materials']} + report.check('material_slots_filled', not empty_slots, empty_slots) + report.check('normals_unit_length', all(m['normals_unit_length'] for m in meshes.values()), + [n for n, m in meshes.items() if not m['normals_unit_length']]) + # Tangents need UVs and faces with at most four corners; meshes without UVs are shaded + # triplanar or unlit and carry no tangents (recorded, not an error). + tangent_blockers = {n: m['ngons'] for n, m in meshes.items() if m['uv_layers'] and m['ngons']} + report.check('tangent_prerequisites', not tangent_blockers, tangent_blockers) + report.data['meshes_without_uv'] = sorted(n for n, m in meshes.items() if not m['uv_layers']) + # Blend shapes: none of the sources uses them; Unity imports them only when they exist. + shapes = {n: m['shape_keys'] for n, m in meshes.items() if m['shape_keys']} + report.check('no_blend_shapes', not shapes or spec.get('rules', {}).get('blend_shapes', False), shapes) + total = sum(m['triangles'] for m in meshes.values()) + report.data['triangles'] = total + if 'triangles' in expect: + report.check('triangles_match_godot', total == expect['triangles'], '%d fbx / %d godot' % (total, expect['triangles'])) + if 'nodes' in expect: + report.check('mesh_names_match_godot', sorted(meshes) == sorted(expect['nodes']), sorted(set(meshes) ^ set(expect['nodes']))) + if 'parts' in expect and spec.get('rules', {}).get('check_parts', True): + report.check('mesh_names_match_godot', sorted(meshes) == sorted(expect['parts']), sorted(set(meshes) ^ set(expect['parts']))[:12]) + if 'materials' in expect: + used = sorted({name for m in meshes.values() for name in m['materials'] if name}) + report.check('materials_match_godot', used == sorted(expect['materials']), sorted(set(used) ^ set(expect['materials']))) + if expect.get('bounds_godot') and before['bounds_unity']: + # The Godot manifests measure the intact model (towers: without damaged upper part, + # debris, ruin and cloth); bounds_exclude names those parts. + exclude = tuple(spec.get('rules', {}).get('bounds_exclude', ())) + chosen = [m['bounds_unity'] for n, m in meshes.items() if not (exclude and n.startswith(exclude))] + got = {'min': [min(b['min'][i] for b in chosen) for i in range(3)], 'max': [max(b['max'][i] for b in chosen) for i in range(3)]} + want = godot_to_unity_bounds(expect['bounds_godot']) + worst = max(abs(a - b) for key in ('min', 'max') for a, b in zip(got[key], want[key])) + report.check('bounds_match_godot', worst < 2e-3, 'largest difference %.5f m' % worst) + armatures = before['armatures'] + if spec['kind'] == 'skinned': + report.check('one_armature', len(armatures) == 1, sorted(armatures)) + for name, arm in armatures.items(): + report.check('single_root_bone', len(arm['roots']) == 1, arm['roots']) + want_root = spec.get('rules', {}).get('root_bone', 'Root') + report.check('root_bone_name', arm['roots'] == [want_root], arm['roots']) + if 'bone_names' in expect: + report.check('bone_names_match_godot', sorted(arm['bones']) == sorted(expect['bone_names']), sorted(set(arm['bones']) ^ set(expect['bone_names']))) + if 'bones' in expect: + report.check('bone_count_match_godot', len(arm['bones']) == expect['bones'], '%d / %d' % (len(arm['bones']), expect['bones'])) + bad = [b for b in arm['bones'] if not b.replace('.', '').replace('_', '').isalnum()] + report.check('bone_names_portable', not bad, bad) + report.check('skinned_meshes_present', any(m['skinned'] for m in meshes.values()), '') + names = sorted(c['name'] for c in clips) + if 'clips' in expect: + report.check('clips_match_godot', names == sorted(expect['clips']), sorted(set(names) ^ set(expect['clips']))) + required = spec.get('rules', {}).get('required_clips', []) + report.check('required_clips_present', all(c in names for c in required), [c for c in required if c not in names]) + if 'clip_seconds' in expect: + worst = max(abs(c['seconds'] - expect['clip_seconds'][c['name']]) for c in clips if c['name'] in expect['clip_seconds']) + report.check('clip_lengths_match_godot', worst < 1e-3, 'largest difference %.4f s' % worst) + else: + report.check('no_armature', not armatures, sorted(armatures)) + forward = spec.get('rules', {}).get('forward_marker') + if forward: + marker = next((p for n, p in before['empties'].items() if n.startswith(forward)), None) + report.check('forward_marker_unity_plus_z', marker is not None and marker[2] > 0.1 and abs(marker[0]) < 1e-3, marker) + + +def reproducible_fbx(): + """Byte-identical FBX for identical sources: Blender's FBX writer stamps the current time into + the header and derives object ids from Python's string hash. The clock is fixed here; the hash + seed comes from PYTHONHASHSEED=0 with --python-use-system-env (tools/blender/export_fbx.sh).""" + import datetime + import io_scene_fbx.export_fbx_bin as writer + + class FixedClock(datetime.datetime): + @classmethod + def now(cls, tz=None): + return cls(2026, 1, 1, 0, 0, 0) + + class Clock: + datetime = FixedClock + + writer.datetime = Clock + + +def export_fbx(path, objects): + bpy.ops.object.select_all(action='DESELECT') + for obj in objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = objects[0] + path.parent.mkdir(parents=True, exist_ok=True) + bpy.ops.export_scene.fbx(filepath=str(path), **FBX_SETTINGS) + + +def round_trip(path, spec, report, before, clips): + """Imports the written FBX into an empty file and compares names and counts.""" + bpy.ops.wm.read_factory_settings(use_empty=True) + bpy.ops.import_scene.fbx(filepath=str(path), use_custom_normals=True, use_anim=True, automatic_bone_orientation=False) + depsgraph = bpy.context.evaluated_depsgraph_get() + imported = [o for o in bpy.context.scene.objects] + meshes = {o.name: o for o in imported if o.type == 'MESH'} + report.check('roundtrip_mesh_names', sorted(meshes) == sorted(before['meshes']), sorted(set(meshes) ^ set(before['meshes']))) + tri = 0 + for obj in meshes.values(): + evaluated, mesh = evaluated_mesh(obj, depsgraph) + tri += triangles(mesh) + evaluated.to_mesh_clear() + report.check('roundtrip_triangles', tri == report.data['triangles'], '%d / %d' % (tri, report.data['triangles'])) + materials = sorted({s.material.name for o in meshes.values() for s in o.material_slots if s.material}) + want = sorted({name for m in before['meshes'].values() for name in m['materials'] if name}) + report.check('roundtrip_materials', materials == want, sorted(set(materials) ^ set(want))) + if spec['kind'] == 'skinned': + arm = next(o for o in imported if o.type == 'ARMATURE') + bones = sorted(b.name for b in arm.data.bones) + want_bones = sorted(next(iter(before['armatures'].values()))['bones']) + report.check('roundtrip_bones', bones == want_bones, sorted(set(bones) ^ set(want_bones))) + takes = sorted(a.name.split('|')[-1] for a in bpy.data.actions) + report.check('roundtrip_clips', takes == sorted(c['name'] for c in clips), takes) + + +def export_asset(spec, godot_root): + report = Report(spec) + source = godot_root / spec['source'] + bpy.ops.wm.open_mainfile(filepath=str(source)) + report.data['source_sha256'] = hashlib.sha256(source.read_bytes()).hexdigest() + expect = godot_expectations(spec, godot_root) + fps = bpy.context.scene.render.fps / bpy.context.scene.render.fps_base + prepare(spec, report) + objects = export_objects(spec) + # Facts of the bind pose (rest), like the Godot manifests; the animation bake needs POSE again. + armatures = [o for o in objects if o.type == 'ARMATURE'] + for arm in armatures: + arm.data.pose_position = 'REST' + bpy.context.view_layer.update() + depsgraph = bpy.context.evaluated_depsgraph_get() + before = facts(objects, depsgraph) + for arm in armatures: + arm.data.pose_position = 'POSE' + bpy.context.view_layer.update() + clips = clip_facts(fps) if spec['kind'] == 'skinned' else [] + report.data.update({'kind': spec['kind'], 'fps': fps, 'objects': len(objects), 'meshes': before['meshes'], 'armatures': before['armatures'], + 'empties': before['empties'], 'bounds_unity': before['bounds_unity'], 'clips': clips, + 'expected_from_godot': {k: expect[k] for k in ('triangles', 'bounds_godot', 'bones', 'clips', 'resource_path') if k in expect}}) + run_checks(spec, report, before, clips, expect) + out = UNITY_ROOT / 'Assets/Luneraria/Art' / spec['group'] / (spec['id'] + '.fbx') + export_fbx(out, objects) + report.data['fbx'] = str(out.relative_to(UNITY_ROOT)) + report.data['fbx_bytes'] = out.stat().st_size + round_trip(out, spec, report, before, clips) + report.data['ok'] = report.ok + (out.with_suffix('.export.json')).write_text(json.dumps(report.data, indent=1) + '\n') + failed = [c for c in report.data['checks'] if not c['ok']] + print('LUNE_EXPORT %s %s: %d checks, %d failed%s' % ('OK' if not failed else 'FAIL', spec['id'], len(report.data['checks']), len(failed), + ''.join('\n FAIL %s: %s' % (c['check'], c['detail']) for c in failed))) + return report.ok + + +def main(): + reproducible_fbx() + options = args() + manifest = json.loads(Path(options['manifest']).read_text()) + godot_root = Path(options['godot']).resolve() + wanted = [i for i in options['ids'].split(',') if i] + specs = [s for s in manifest['assets'] if not wanted or s['id'] in wanted] + missing = set(wanted) - {s['id'] for s in specs} + ok = not missing + if missing: + print('LUNE_EXPORT FAIL unknown ids', sorted(missing)) + for spec in specs: + try: + ok = export_asset(spec, godot_root) and ok + except Exception as error: # a broken asset must not stop the batch + import traceback + traceback.print_exc() + print('LUNE_EXPORT FAIL %s: %s' % (spec['id'], error)) + ok = False + print('LUNE_EXPORT_DONE ok=%s assets=%d' % (ok, len(specs))) + sys.exit(0 if ok else 1) + + +main()