""" The Modular SciFi Season 1 Starter Bundle for the vessel. The kit was brought out of Unreal for the Anchorage station (models/anchorage: kit_export/, textures/ and build/bl_kit.py). It is read from there in place; nothing is written into that folder. Its Kit class is loaded under its own module name so it can live next to this folder's Season 2 kit (names do not collide: Season 1 datablocks are HW_ / IN_ / CC_ / PR_ / MT_, Season 2 ones SI_ / EN_ / EP_). Units are cut out of the pack's own demo maps, as for Season 2 (units.py), and returned in a local frame. Wall runs ("liners"): origin at the start of the run on the wall's BACK plane, at floor level; +X along the wall, the room is on +Y. Both Season 1 wall systems step 4.4 m: a 0.82 m pilaster and a 3.6 m wall panel. """ import importlib.util import math import os import sys from mathutils import Matrix from units import Demo, Unit HERE = os.path.dirname(os.path.abspath(__file__)) ANCHORAGE = os.path.join(os.path.dirname(os.path.dirname(HERE)), "anchorage") KIT_DIR = os.path.join(ANCHORAGE, "kit_export") S1_GAME = "/Game/StarterBundle/" PITCH = 4.4 # pilaster + wall panel BUFFER = 0.82 # the pilaster's width # Each demo map fixes its own exposure; brought to the hallway map's as in the Anchorage build, times that build's # preview gain. (x light_scale goes into the Blender lamp only; the Unreal values travel in ob["ue_light"].) LIGHT_SCALE = {"SciFi_Example_D_Ext": 1.0 * 2.0, "SciFi_INT_EX1": 3.2 * 2.0, "SciFi_COMM_EX1": 0.8 * 2.0, "ExampleMap": 2.0} _kit = None _demos = {} def kit(log=print): """The Season 1 Kit object (same interface as this folder's bl_kit.Kit).""" global _kit if _kit is None: mod = sys.modules.get("bl_kit_s1") if mod is None: spec = importlib.util.spec_from_file_location("bl_kit_s1", os.path.join(ANCHORAGE, "build", "bl_kit.py")) mod = importlib.util.module_from_spec(spec) sys.modules["bl_kit_s1"] = mod spec.loader.exec_module(mod) _kit = mod.Kit(log=log) return _kit def demo(name): if name not in _demos: _demos[name] = Demo(name, KIT_DIR) return _demos[name] def rot_z(deg): return Matrix.Rotation(math.radians(deg), 4, "Z") def _run(bays, closing, seq): out = [] for j, b in enumerate(seq): t = Matrix.Translation((j * PITCH, 0.0, 0.0)) out += [it.moved(t) for it in bays[b]] t = Matrix.Translation((len(seq) * PITCH, 0.0, 0.0)) out += [it.moved(t) for it in closing] return Unit(out) def run_length(n): return n * PITCH + BUFFER # --------------------------------------------------------------------------------------------------------------- # Hallways pack: the two-bay hall's wall (lower locker band, two grey panels, pilasters with bronze fins) # --------------------------------------------------------------------------------------------------------------- HALL_MAP = "SciFi_Example_D_Ext" HALL_WALL_H = 4.4 HALL_WALL_DEPTH = 0.6 # pilasters; the panels between them are 0.3 deep HALL_NOT = ("SM_Hall_Pipes_Ceiling", "SM_EnergyCore_A", "SM_Ceiling", "SM_Hall_Ceiling", "SM_Hall_Floor_Main", "SM_Hall_FloorBuffer", "SM_Pipes_GRP", "SM_Hall_Doorway", "SM_Hall_Light_Square") def hall_wall(n=5, seq=None, foot_strip=True, lights=True): """n bays of the Hallways wall plus the closing pilaster (length n * 4.4 + 0.82).""" d = demo(HALL_MAP) x0, y_back = 9.29, 9.7 to_local = Matrix.Translation((-x0, -y_back, 0.0)) def pred(it, p): if not (-0.02 <= p.x <= 2 * PITCH + BUFFER + 0.02 and -0.05 <= p.y <= (1.75 if it.kind == "light" else 0.75)): return False if it.kind == "light": return lights and p.z > 1.0 if it.kind == "mesh": if it.name.startswith(HALL_NOT): return False if it.name == "SM_Hall_FloorEdge" and not foot_strip: return False return True u = d.unit(to_local.inverted(), pred) bays = {0: [], 1: []} closing = [] for it in u.items: k = int((it.center.x + 1e-4) // PITCH) if k >= 2: closing.append(it.moved(Matrix.Translation((-2 * PITCH, 0, 0)))) else: bays[k].append(it.moved(Matrix.Translation((-k * PITCH, 0, 0)))) seq = seq if seq is not None else tuple(k % 2 for k in range(n)) return _run(bays, closing, seq) # --------------------------------------------------------------------------------------------------------------- # Interiors pack: the processing hall's white wall (one plain bay exists in the demo; it is repeated) # --------------------------------------------------------------------------------------------------------------- INT_MAP = "SciFi_INT_EX1" WHITE_WALL_H = 4.5 WHITE_WALL_DEPTH = 0.61 INT_NOT = ("SM_Ceiling", "SM_FloorPanel", "SM_FloorBuffer", "SM_Light_Square", "SM_Pipe_Ceiling", "SM_Pipe_Vent", "SM_Pipe_Div", "SM_Doorway", "SM_Pipe_Doorway", "SM_Wall_C") def white_wall(n=5, lights=True, kinds=None): """n bays of the Interiors white wall plus the closing pilaster. kinds: per bay "wall" or "open" (pilaster only: the bay is left free, for a doorway that stands behind it).""" d = demo(INT_MAP) # demo: the wall runs along +y from 66.99 to 72.21 at x 18.9 (back) .. 19.5, the room is on +x to_local = Matrix.Translation((72.21, -18.9, 0.0)) @ rot_z(90.0) def pred(it, p): if not (-0.02 <= p.x <= PITCH + BUFFER + 0.02 and -0.05 <= p.y <= (1.9 if it.kind == "light" else 0.75)): return False if it.kind == "light": return lights and p.z > 1.0 if it.kind == "mesh" and it.name.startswith(INT_NOT): return False return it.kind != "decal" u = d.unit(to_local.inverted(), pred) bay, closing = [], [] for it in u.items: (closing if it.center.x >= PITCH - 1e-3 else bay).append(it) closing = [it.moved(Matrix.Translation((-PITCH, 0, 0))) for it in closing] kinds = tuple(kinds) if kinds is not None else ("wall",) * n # an open bay keeps the pilaster at its start (everything of the bay that lies within the pilaster's width) post = [it for it in bay if it.center.x < BUFFER + 0.02 and it.kind == "mesh"] return _run({"wall": bay, "open": post}, closing, kinds) # --------------------------------------------------------------------------------------------------------------- # Command centre pack: the round command floor with the terminal (the middle of the pack's command centre) # --------------------------------------------------------------------------------------------------------------- CC_MAP = "SciFi_COMM_EX1" CC_CENTRE = ("SM_Floor_Center_A1", "SM_Floor_Center_A2", "SM_Floor_Center_A3", "SM_Floor_Center_B", "SM_Floor_Center_Pipes_A", "SM_Terminal_A", "SM_Terminal_A_UI", "SM_Railing_Center", "SM_Floor_Panel_A4") CC_RADIUS = 6.56 # the round floor; its walkway runs on to 5.9 m and the entrance panel to 9.11 m on +X CC_DOOR_X = 9.6 # where the pack's own entrance stands, on +X of the centre def command_centre(lettering=True): """Frame: the pack's own, origin at the centre of the round floor at floor level. The terminal's operator looks along -X; the walkway and the entrance are on +X.""" d = demo(CC_MAP) def pred(it, p): if it.kind == "mesh": return it.name in CC_CENTRE if it.kind == "light": return abs(p.x + 0.8) < 0.2 and abs(p.y) < 0.3 and 2.5 < p.z < 3.5 # the lamp over the terminal return lettering and p.z < 0.6 and (p.x * p.x + p.y * p.y < CC_RADIUS ** 2 or (0 < p.x < 9.2 and abs(p.y) < 1.9)) return d.unit(Matrix.Identity(4), pred) # --------------------------------------------------------------------------------------------------------------- # Props pack: furniture rows as the author set them out in the office demo (desk, cabinet, shelf, what lies on them) # --------------------------------------------------------------------------------------------------------------- PROPS_MAP = "ExampleMap" FLOOR_PROPS = 0.1 # the office floor's level in the demo FURNITURE = ("SM_Desk", "SM_Cabinet", "SM_Shelf", "SM_SingleDrawer", "SM_Stool", "SM_Laptop", "SM_TableLamp", "SM_CommDevice", "SM_MobileStorage", "SM_WirelessB", "SM_GlassCup", "SM_Coaster", "SM_MedBottle", "SM_AccessCard", "SM_WasteBin", "SM_CardReader", "SM_Keypad", "SM_FirstAidKit") ROWS = { # name: (x0, x1, y0, y1) in the demo; all stand with their back to the wall at y = 1.45 or y = 14.95 "bench": (-5.6, -0.5, 1.4, 3.4), # desk, cabinet with drawers, shelf, two stools: 5.0 m "desks": (1.4, 6.5, 1.4, 3.3), # shelf and two desks, three stools: 5.1 m "study": (-5.6, -0.5, 13.1, 15.0), # two desks and a shelf on the opposite wall, three stools (back at y 14.95) } def furniture_row(name): """Frame: origin at the row's left end (seen from the room) on the wall line, at floor level; +X along the wall, the room on +Y. Lengths about 5 m, depth 0.9 m, stools out to about 1.9 m.""" d = demo(PROPS_MAP) x0, x1, y0, y1 = ROWS[name] if y1 > 10: # the row on the far wall: turn it round to_local = Matrix.Translation((x1, 14.95, -FLOOR_PROPS)) @ rot_z(180.0) else: to_local = Matrix.Translation((-x0, -1.45, -FLOOR_PROPS)) def pred(it, p): return it.kind == "mesh" and it.name.startswith(FURNITURE) and -0.05 <= p.x <= (x1 - x0) + 0.05 and -0.05 <= p.y <= (y1 - y0) + 0.05 return d.unit(to_local.inverted(), pred)