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
1 change: 1 addition & 0 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ nnnotes config check # each setting's origin and whether it is valid
| `audio` | CRI cue sheet | one audio file per cue (FLAC / Ogg / WAV) + cue metadata |
| `crikey` | APK | the CRI HCA keycode from the game's boot data (shows whether it was found; can write a `.hcakey`) |
| `player` | APK | render-related global settings (color space, quality levels, renderers) as JSON |
| `ui` (experimental) | APK set and its embedded catalog | an offline serialized prefab library with dependency roots, AnimatorControllers, stable references and PNG/font resources for the optional ournotes-player UI preview ([format and limits](https://github.com/MetaSekaiLab/nnnotes/blob/main/docs/ui.md)) |
| `live` | music ID + difficulty | a full chart directory: chart and runtime notes, 3D scene, note and effect assets, BGM and sounds, sound routing |
| `web` | `--pair music:difficulty` (repeatable) or `--all`; `--live2d model` (repeatable) or `--all-live2d`; `--story episode` (repeatable) or `--all-stories`; `--region region` (repeatable) or `--all-regions` | an ournotes-player static site: shared player + per-chart / per-model / per-episode manifests + content-addressed assets; the Live2D models of the stories are built first as models, listed in `models.json`, and the story manifests reference them; one site can serve several regions, with listing texts in five languages; a story's interface texts are grouped by language, with TextMeshPro font assets generated from open fonts (the game's fonts with `--fonts game`); compressible assets (JSON, shaders, moc3, ...) are stored gzip encoded by default (`--compress br` / `none`) |
| `music-data` | master data files (`--master-files` directory or `--apk-master`), or decoded master data with its manifest (`--decoded-master`) | one JSON file with every song and chart: titles and credits in five languages, bands, vocal characters, category, tags, release time, score ranks, BGM length; per difficulty the level, note counts, BPM, chart times, skill events and fever ranges; and the chart statistics the deck model ournotes-deck (built into nnnotes) measures on its whole-live simulation (the no-skill score, the weight of every score-up skill kind at every position). `--full` adds the deck model's input: every chart's runtime notes and the master data tables about cards, skills, bonuses, scores and events ([format](https://github.com/MetaSekaiLab/nnnotes/blob/main/docs/music-data.md)) |
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ nnnotes config check # 每项设置的来源和格式是否有效,
| `audio` | CRI cue sheet | 每个 cue 一个音频文件(FLAC / Ogg / WAV)+ cue 元数据 |
| `crikey` | APK | 读出游戏启动数据中的 CRI HCA 解码密钥(只显示是否找到,可写成 `.hcakey`) |
| `player` | APK | 渲染相关的全局设置(色彩空间、画质等级、渲染器)JSON |
| `ui`(实验性) | APK 集合及内嵌 catalog | 离线序列化预制体库,包含依赖根对象、AnimatorController、稳定引用与 PNG/字体资源,供 ournotes-player 可选 UI 预览使用([格式与边界](https://github.com/MetaSekaiLab/nnnotes/blob/main/docs/ui.md)) |
| `live` | 曲目 ID + 难度 | 完整谱面目录:谱面与运行时音符、3D 场景、音符与特效资源、BGM 与音效、声音路由 |
| `web` | `--pair 曲目:难度`(可重复)或 `--all`;`--live2d 模型`(可重复)或 `--all-live2d`;`--story 剧情 ID`(可重复)或 `--all-stories`;`--region 区服`(可重复)或 `--all-regions` | ournotes-player 静态站点:共享播放器 + 每谱 / 每模型 / 每集剧情清单 + 内容寻址资源;剧情用到的 Live2D 模型先按模型构建并列入 `models.json`,剧情清单引用它们;一个站点可服务多个区服,列表文本含五种语言;剧情的界面文字按语言分组,字形由开源字体生成 TextMeshPro 字体资源(`--fonts game` 时用游戏字体);可压缩的资源(JSON、着色器、moc3 等)默认以 gzip 存储,`--compress br` / `none` 可改 |
| `music-data` | masterdata 文件(`--master-files` 目录或 `--apk-master`),或带清单的解码 masterdata(`--decoded-master`) | 全部歌曲与谱面的单个 JSON:五语标题与作词作曲编曲、乐队、演唱角色、分类、标签、上线时间、评级线、BGM 时长;每个难度的等级、音符数、BPM、谱面时间、技能事件与 fever 区间;以及组卡模型 ournotes-deck(内置于 nnnotes)在整场模拟上实测的谱面统计(无技能得分、每种加分技能在每个演出位的权重)。`--full` 另附组卡模型的输入:每张谱面的运行时音符与卡牌、技能、加成、分数、活动相关的 masterdata 表([格式](docs/music-data.md)) |
Expand Down
66 changes: 66 additions & 0 deletions docs/ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Serialized UI libraries (experimental)

`nnnotes ui` exports an offline prefab library for the optional `ournotes-player/ui` preview module. It reads the
embedded Addressables catalog and bundle closure of the APK set you supply; it does not contact a game API. Keep
outputs outside the nnnotes and ournotes-player source repositories. The export contains game data that these
repositories and their packages do not redistribute.

```sh
nnnotes --apk /path/to/base.apk ui --prefix EmbUI/Prefab/ --limit 10 -o /path/to/ui-data
nnnotes --apk /path/to/base.apk ui --key YOUR_EXACT_APK_KEY -o /path/to/ui-data
```

`--key` is repeatable. Without it, `--prefix` defaults to `EmbUI/`. `--no-dependencies` omits additional root
prefabs and AnimatorControllers; `--force` re-exports the selected keys. A failed key is retained as an explicit
index entry and makes the command exit with status 1. Existing unrelated entries of the same input stay present.

## Inputs and regions

The command uses the same `ApkSet` reader as the existing extractors: one APK, base.apk with adjacent splits, a
directory of splits, or an APKS/XAPK archive. Explicit `--apk` wins over the selected region's APK configuration.
The configured cache and bundle decryption settings are used when needed. Readable unencrypted local bundles do
not require a key. Default Unity resources are read from the selected APK set through the existing player reader.

```sh
nnnotes --region jp ui --prefix EmbUI/Prefab/ --limit 10 -o /path/to/jp-ui-data
```

For JP, configure the actual JP APK set as described in [jp.md](jp.md). Do not point a JP region at an international
APK: this command exports the APK selected by the configuration, not a replacement fetched from that region.
Keep international and JP libraries in separate output directories. Their keys, classes and fonts can differ.

Current real UI smoke checks used international client 1.0.1 (versionCode 25). A synthetic split-APK test verifies
the JP command/configuration path; it is not a full JP UI export or pixel-fidelity verification. Existing JP
catalog, chart, story and model validation is described separately in [jp.md](jp.md).

## Files and resume

`index.json` has `schema: 1`, `format: "ournotes-ui-library"`, and three lists:

- `assets`: selected catalog keys, IDs, kind, export status, pack file and SHA-256; failures contain an error type
and message rather than a pack file.
- `embedded`: additional root GameObjects found in a selected key's dependency closure.
- `controllers`: AnimatorControllers found in that closure, keyed by actual serialized object identity.

Pack files under `packs/`, `embedded/` and `controllers/` have `format: "ournotes-ui-pack"`, a `document`,
`resources` and `resourceBase: "../"`. Hierarchy nodes retain serialized rectangles, transforms, active flags,
component fields and preorder paths. `nodeId` and reference `nodeId` values distinguish same-named instances;
controller references carry a matching ID. Negative intermediate rectangle sizes are preserved.

Resources contain Sprite metadata and texture/font paths. PNGs and embedded TTFs are written under `textures/`
and `fonts/`. Each used VibeMO numeric font face has separate ASCII glyph metrics in `fontMetricsByAsset`; the
legacy `fontMetrics` field names the first one. A metrics file's texture is relative to that file when its
`textureBase` is `"metrics"`. Rotated packed sprites are decoded to standalone RGBA images.

The index records hashes of every pack and its texture/font/metrics files, as well as dependency IDs. A resumed
key is skipped only when these files and its dependency records still validate. Missing or corrupt files are
re-exported. Provenance records hashes of the APK catalog and effective APK-set member metadata, the manifest
version and configured region; it contains no credentials or server addresses. A different input is rejected
before updating an existing library. The index is replaced atomically after each key.

## Scope

This is inspectable serialized data, not an implementation of every game Presenter. The preview implements a
subset of layout, graphics, component binding and animation. Exported particle, shader/material, localization,
video, camera and custom component fields do not imply that the preview executes them. `runtime_verified` stays
false. The companion player documentation lists rendering limits and the optional viewer.
13 changes: 13 additions & 0 deletions src/nnnotes/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,11 @@ def _out(c, what: str, required: bool = True) -> None:
c.add_argument("-o", "--out", required=required, help=what)


def cmd_ui(args, cfg):
from . import ui
ui.command(args, cfg)


def build_parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(prog="nnnotes", description="BanG Dream! Our Notes data toolkit")
p.add_argument("--version", action="version", version=f"nnnotes {__version__}")
Expand Down Expand Up @@ -987,6 +992,14 @@ def target(m, what):

cli_assets.register(sub, argparse.Namespace(open_catalog=open_catalog, print_json=_print_json))
voices.register(sub, argparse.Namespace(open_catalog=open_catalog, master_dir=master_dir))
c = sub.add_parser("ui", help="export an offline UI prefab library for ournotes-player/ui")
_out(c, "UI data directory outside the source repositories")
c.add_argument("--key", action="append", help="exact APK catalog key (repeatable)")
c.add_argument("--prefix", default="EmbUI/", help="APK UI key prefix (default EmbUI/)")
c.add_argument("--limit", type=int, help="maximum number of keys")
c.add_argument("--no-dependencies", action="store_true", help="omit additional prefab roots and controllers")
c.add_argument("--force", action="store_true", help="re-export the selected keys")
c.set_defaults(func=cmd_ui, usage=c.error)
return p


Expand Down
Loading
Loading