Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions scripts/gen_typetrees.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,33 @@
("Adv", "AdvSystem.Rendering", "AdvFieldRendererFeature"),
("App.Runtime", "App.Config", "AppConfigDefaultData"),
("DOTween.dll", "DG.Tweening.Core", "DOTweenSettings"),
("Fwk", "Fwk.Cam", "CameraManager"),
("Fwk", "Fwk.Localization", "LocalizeManager"),
("Fwk", "Fwk.Rendering", "ScreenCaptureRendererFeature"),
("Fwk", "Fwk.Sound", "SoundVolumeSettings"),
("Fwk", "Fwk.UI", "UICameraController"),
("Fwk", "Fwk.UI", "UIInputController"),
("Fwk", "Fwk.UI", "UIManager"),
("Fwk", "Fwk.UI.Rendering", "UIRendererFeature"),
("SiriusAsset", "App.GachaAnimation.Blur.DualKawase", "DualKawaseBlurFeature"),
("Fwk", "Fwk.UI", "UIScreenSizeWatcher"),
("SiriusAsset", "App.GachaAnimation.PostProcessing", "CameraBlendFeature"),
("SiriusAsset", "App.GachaAnimation.ChromaticAberration", "ChromaticAberrationFeature"),
("SiriusAsset", "App.GachaAnimation.Blur.DualKawase", "DualKawaseBlurFeature"),
("SiriusAsset", "App.GachaAnimation.Paraffin", "ParaffinFeature"),
("SiriusAsset", "App.GachaAnimation.PostProcessing", "CameraBlendFeature"),
("SiriusAsset", "App.GachaAnimation.PostProcessing", "RadialBlurFeature"),
("SiriusAsset", "App.UI.Text.DropShadow", "TextDropShadowFeature"),
("Unity.InputSystem", "UnityEngine.InputSystem.UI", "InputSystemUIInputModule"),
("Unity.RenderPipelines.Universal.Runtime", "UnityEngine.Rendering.Universal", "PostProcessData"),
("Unity.RenderPipelines.Universal.Runtime", "UnityEngine.Rendering.Universal", "UniversalAdditionalCameraData"),
("Unity.RenderPipelines.Universal.Runtime", "UnityEngine.Rendering.Universal", "UniversalRenderPipelineAsset"),
("Unity.RenderPipelines.Universal.Runtime", "UnityEngine.Rendering.Universal", "UniversalRendererData"),
("Unity.TextMeshPro", "TMPro", "TMP_Settings"),
("Unity.TextMeshPro", "TMPro", "TMP_StyleSheet"),
("UnityEngine.UI", "UnityEngine.UI", "CanvasScaler"),
("UnityEngine.UI", "UnityEngine.EventSystems", "EventSystem"),
("UnityEngine.UI", "UnityEngine.UI", "GraphicRaycaster"),
("UnityEngine.UI", "UnityEngine.UI", "Image"),
("UnityEngine.UI", "UnityEngine.EventSystems", "Physics2DRaycaster"),
)
DEFAULT_OUT = Path(__file__).resolve().parents[1] / "src" / "nnnotes" / "unity" / "typetrees"

Expand Down
30 changes: 29 additions & 1 deletion src/nnnotes/content/prefabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,37 @@ def builtin_root(objects: Objects, cls: str) -> str:
return hits[0]


# the app manager prefabs: catalog keys of some game versions, root GameObjects of the boot scene of others
BOOT_MANAGERS = ("EmbCommon/Prefab/CameraManager", "EmbCommon/Prefab/UIManager")


def boot_managers(catalog: Iterable[str]) -> list[str]:
"""The app manager keys that the catalog `catalog` (its keys) lacks: the boot scene holds those managers."""
held = set(catalog)
return [k for k in BOOT_MANAGERS if k not in held]


def boot_builtins(catalog: Iterable[str]) -> list[str]:
"""The built-in selectors that bring the boot scene's manager GameObjects into a product ([] when the catalog
lists every manager)."""
return ["GameObject"] if boot_managers(catalog) else []


def key_object(objects: Objects, key: str, cls: str) -> str:
"""The one object of the catalog key `key` of class `cls`: a GameObject with its prefab document, a MonoBehaviour
by its script class, any other object by its class (ValueError otherwise)."""
by its script class, any other object by its class (ValueError otherwise). A manager key (BOOT_MANAGERS) that
is not a key of the table names the root GameObject of the boot scene with the key's last segment as its name."""
if cls == "GameObject" and key in BOOT_MANAGERS and key not in objects.keys():
name = key.rsplit("/", 1)[-1]
roots = [
o
for o in objects.roots
if o in objects and objects.info(o).get("class") == "GameObject" and objects.info(o).get("name") == name
]
hits = [o for o in roots if has_json(objects, o)]
if len(hits) != 1:
raise ValueError(f"{key}: {len(hits)} boot scene GameObjects named {name}")
return hits[0]

def of(oid: str) -> str | None:
c = objects.info(oid).get("class")
Expand Down
14 changes: 10 additions & 4 deletions src/nnnotes/content/storyscene.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@

from __future__ import annotations

from collections.abc import Iterable

from .livenotes import animator_bindings
from .livescene import GRAPHICS
from .prefabs import Objects, builtin_root, has_json, key_object, mesh_roles, ref_id, shader_table
from .prefabs import Objects, boot_managers, builtin_root, has_json, key_object, mesh_roles, ref_id, shader_table

SCENE_FORMAT = 1 # scene.json "format"
SCENE_KEY = "EmbScene/Adv"
Expand All @@ -39,9 +41,13 @@
}


def keys() -> list[str]:
"""The catalog keys of the story scene: the scene key, the prefab keys and the settings keys, sorted."""
return sorted([SCENE_KEY, *PREFAB_KEYS.values(), *(key for key, _ in SETTINGS_KEYS.values())])
def keys(catalog: Iterable[str]) -> list[str]:
"""The catalog keys of the story scene in the catalog `catalog` (its keys): the scene key, the prefab keys and the
settings keys, sorted; a manager that the boot scene holds is no catalog key."""
absent = set(boot_managers(catalog))
return sorted(
[SCENE_KEY, *(k for k in PREFAB_KEYS.values() if k not in absent), *(key for key, _ in SETTINGS_KEYS.values())]
)


def scene(objects: Objects) -> tuple[dict, set[str], dict[str, set[str]]]:
Expand Down
2 changes: 1 addition & 1 deletion src/nnnotes/content/storysimpleui.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def addresses(catalog) -> dict[str, str]:


def keys(catalog) -> list[str]:
return sorted({*addresses(catalog).values(), storyui.UI_MANAGER_KEY})
return sorted({*addresses(catalog).values(), *(k for k in (storyui.UI_MANAGER_KEY,) if k in set(catalog))})


def ui(objects, language: str, settings) -> tuple[dict, set, dict]:
Expand Down
3 changes: 2 additions & 1 deletion src/nnnotes/content/storyui.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,12 @@ def window_keys(catalog: Iterable[str]) -> dict[str, str]:
def keys(catalog: Iterable[str]) -> list[str]:
"""The catalog keys of the story UI in the catalog `catalog` (its keys): the widget, the chat widget, UIManager, the
letterbox, the master id settings, the dialogs, the animations and the talk windows (window_keys), sorted."""
held = set(catalog)
return sorted(
{
WIDGET_KEY,
CHAT_WIDGET_KEY,
UI_MANAGER_KEY,
*(k for k in (UI_MANAGER_KEY,) if k in held),
LETTERBOX_KEY,
MASTER_ID_SETTINGS_KEY,
*DIALOG_KEYS.values(),
Expand Down
2 changes: 1 addition & 1 deletion src/nnnotes/musicdata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,7 @@ def record(sid: int) -> dict:
"master": {
"source": master_source,
"version": master_version,
"tables": {t: {"sha256": table_sha[t]} for t in read},
"tables": {t: {"sha256": table_sha[t]} for t in read if t in table_sha},
},
"exporter": exporter,
"deck": deck.info() if deck is not None else None,
Expand Down
8 changes: 8 additions & 0 deletions src/nnnotes/musicdata/deckdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@
)


# Tables a master data version may leave out (no rows then): the master data of newer game versions does not list them.
OPTIONAL_TABLES = frozenset({"MasterArenaMusic"})


class DeckDataError(ValueError):
"""An input the deck data cannot be made from (the message names it)."""

Expand Down Expand Up @@ -261,10 +265,13 @@ def read(names):

def read_master(src: MasterSource, key, tables=None) -> tuple[dict[str, list[dict]], dict[str, str]]:
"""The rows (`_allData`) of every table of `tables` (default: TABLES) and the SHA-256 of each file as served.
A table of OPTIONAL_TABLES the manifest does not list has no rows and no SHA-256.
`key`: a master.MasterKey (unused for decoded master data: None)."""
from ..source import master

names = {t: f"{t}.bin" for t in (tables if tables is not None else (t for t, _ in TABLES))}
absent = {t for t, n in names.items() if t in OPTIONAL_TABLES and n not in src.hashes}
names = {t: n for t, n in names.items() if t not in absent}
unlisted = [t for t, n in names.items() if n not in src.hashes]
if unlisted:
raise DeckDataError(f"master data {src.where}: {MANIFEST} lists no {', '.join(unlisted)}")
Expand Down Expand Up @@ -296,6 +303,7 @@ def read_master(src: MasterSource, key, tables=None) -> tuple[dict[str, list[dic
if not isinstance(rows, list) or not all(isinstance(r, dict) for r in rows):
raise DeckDataError(f"master data {src.where}: {f} has no `_allData` rows")
tables[t], shas[t] = rows, sha
tables.update((t, []) for t in absent)
return tables, shas


Expand Down
16 changes: 11 additions & 5 deletions src/nnnotes/pipeline/story.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@

from ..content import (
liveaudio,
prefabs,
storyasset,
storychat,
storyepisode,
Expand Down Expand Up @@ -261,14 +262,14 @@ class SceneStage(ProductStage):
KIND = "StoryScene"

def select(self, keys: list[str], env) -> list[str]:
return [DEFAULT] if set(storyscene.keys()) <= set(keys) else []
return [DEFAULT] if set(storyscene.keys(keys)) <= set(keys) else []

def keys(self, subject: str, env) -> list[str]:
_default(subject)
return storyscene.keys()
return storyscene.keys(_catalog(env))

def builtins(self, subject: str, env) -> list[str]:
return sorted(GRAPHICS.values())
return sorted([*GRAPHICS.values(), *prefabs.boot_builtins(_catalog(env))])

def manifest(self, subject: str) -> str:
return f"storyscenes/{_default(subject)}.json"
Expand Down Expand Up @@ -362,6 +363,11 @@ def _language(subject: str) -> str:
return subject


def _catalog(env) -> set[str]:
"""The primary keys of the catalog of a planning environment."""
return {loc["primaryKey"] for loc in env.fact("index")["locations"]}


class UiStage(FontInputsStage):
"""story.ui: the ADV story UI in one client language (module documentation)."""

Expand All @@ -386,7 +392,7 @@ def resources(self, subject: str, env) -> list[str]:

def builtins(self, subject: str, env) -> list[str]:
_language(subject)
return list(storyui.BUILTINS)
return [*storyui.BUILTINS, *prefabs.boot_builtins(_catalog(env))]

def record(self, subject: str, env) -> dict:
"""The master record of the language: the text of every MasterText row in its text column."""
Expand Down Expand Up @@ -490,7 +496,7 @@ def resources(self, subject, env):

def builtins(self, subject, env):
font_subject(subject)
return list(storyui.BUILTINS)
return [*storyui.BUILTINS, *prefabs.boot_builtins(_catalog(env))]

def record(self, subject, env):
return UiStage().record(font_subject(subject)[1], env)
Expand Down
Loading
Loading