""" Season 2 crates and tools for Anchorage, copied out once (2026-10-21). The user: "use creates and tools from Modular Scifi Season 2 Starter Bundle meaningfully place it inside anchorage". The vessel's interior fork (models/M_Ship_v2_interior_season2.blend) holds one of each Season 2 piece, imported from the packs with their materials rebuilt (models/vessel-interior, collection "11 KIT | Modular SciFi Season 2 (source, one of each)"). The pieces Anchorage uses are copied out of it into source_fab/season2/season2.blend, one collection, with the textures they use copied to source_fab/season2/textures/ (the same folders as under models/vessel-interior/textures). Every mesh keeps its ["ue_mesh"]: in Unreal they are the packs' own assets (/Game/ModSci_EngiProps, /Game/ModSci_Engineer). blender -b --factory-startup models/M_Ship_v2_interior_season2.blend --python models/anchorage/build/season2_prepare.py The ship file is only read: this saves a new file and never the one it opened. """ import os import shutil import sys import bpy from mathutils import Matrix sys.dont_write_bytecode = True HERE = os.path.dirname(os.path.abspath(__file__)) ROOT = os.path.dirname(HERE) OUT = os.path.join(ROOT, "source_fab", "season2") SRC_TEX = os.path.join(os.path.dirname(ROOT), "vessel-interior", "textures") COLLECTION = "KIT | Modular SciFi Season 2 (Anchorage's crates and tools)" PIECES = ( "EP_SM_Case_A", "EP_SM_PlasticPallet", "EP_SM_WaterDrum", "EP_SM_WireReel_A", "EP_SM_Toolbox", "EP_SM_Screwdriver", "EP_SM_Wrench", "EP_SM_PortableLight", "EP_SM_RubberMat_Flat", "EP_SM_RubberMat_Rolled", "EP_SM_FireExtinguisher", "EP_SM_FireExtinguisher_Mount", "EP_SM_OxygenTank", "EP_SM_OxygenTank_B", "EN_SM_NitrogenTank", ) def main(): src_file = bpy.data.filepath if os.path.normcase(os.path.dirname(src_file)) == os.path.normcase(OUT): raise RuntimeError("run this on the ship file, not on its output") src = next(c for c in bpy.data.collections if c.name.startswith("11 KIT") and "Season 2" in c.name) keep, missing = [], [] for n in PIECES: o = src.objects.get("KIT | " + n) (keep.append(o) if o is not None else missing.append(n)) if missing: raise RuntimeError("not in %s: %s" % (src.name, missing)) meshes = {o.data for o in keep} sc = bpy.context.scene for s in list(bpy.data.scenes): if s is not sc: bpy.data.scenes.remove(s) col = bpy.data.collections.new(COLLECTION) sc.collection.children.link(col) for o in keep: col.objects.link(o) for o in list(bpy.data.objects): if o not in keep: bpy.data.objects.remove(o) for c in list(bpy.data.collections): if c is not col: bpy.data.collections.remove(c) for coll in (bpy.data.meshes, bpy.data.materials, bpy.data.images, bpy.data.node_groups, bpy.data.textures, bpy.data.actions, bpy.data.objects, bpy.data.collections, bpy.data.worlds, bpy.data.curves): for idb in coll: idb.use_fake_user = False for me in meshes: me.use_fake_user = True bpy.data.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True) for lib in list(bpy.data.libraries): if not lib.users: bpy.data.libraries.remove(lib) # the pieces side by side along x, so the library file reads at a glance (placing uses the meshes, not these) x = 0.0 for o in keep: o.parent = None o.matrix_world = Matrix.Identity(4) o.location.x = x + o.dimensions.x / 2.0 x += o.dimensions.x + 0.3 n_tex, gone = 0, [] for im in bpy.data.images: if im.source != "FILE" or not im.filepath: continue p = os.path.normpath(bpy.path.abspath(im.filepath)) if not os.path.isfile(p): gone.append(im.name) continue rel = os.path.relpath(p, SRC_TEX) if os.path.normcase(p).startswith(os.path.normcase(SRC_TEX)) else os.path.basename(p) dst = os.path.join(OUT, "textures", rel) os.makedirs(os.path.dirname(dst), exist_ok=True) shutil.copyfile(p, dst) im.filepath = dst n_tex += 1 os.makedirs(OUT, exist_ok=True) path = os.path.join(OUT, "season2.blend") bpy.ops.wm.save_as_mainfile(filepath=path, relative_remap=True, compress=True, copy=True) for o in keep: print("[s2] %-30s %-58s %.2f x %.2f x %.2f m, materials %s" % ( o.name, o.data.get("ue_mesh", "-"), o.dimensions.x, o.dimensions.y, o.dimensions.z, [m.name for m in o.data.materials if m][:4])) print("[s2] %d pieces, %d materials, %d textures copied, missing %s; saved %s (from %s, not changed)" % ( len(keep), len(bpy.data.materials), n_tex, gone[:6], path, src_file)) main()