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
5 changes: 4 additions & 1 deletion SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,10 @@ if platform in ["macos", "ios"]:
plist_subst = {
"${BUNDLE_LIBRARY}": file_name,
"${BUNDLE_NAME}": "ssplayer-godot",
"${BUNDLE_IDENTIFIER}": "jp.co.cri-mw.spritestudio.ssplayer-godot.{}".format(env["target"]),
# CFBundleIdentifier allows only alphanumerics, '-' and '.', so sanitize the
# target name ("template_debug" -> "template-debug"); underscores make Xcode
# reject the embedded framework on iOS ("invalid CFBundleIdentifier").
"${BUNDLE_IDENTIFIER}": "jp.co.cri-mw.spritestudio.ssplayer-godot.{}".format(env["target"].replace("_", "-")),
"${BUNDLE_VERSION}": version,
"${MIN_MACOS_VERSION}": "10.12",
"${MIN_IOS_VERSION}": "12.0"
Expand Down
2 changes: 2 additions & 0 deletions docs/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ Animation playback uses `libssruntime` provided by [SpriteStudio-SDK](https://gi
- [Integration with AnimationPlayer](workflow/animation_player.md)
- [Asset Import and Editor Integration](workflow/usage_asset_pipeline.md) (start here for the initial `.sspj` import)
- [Scripting and Events](workflow/usage_scripting.md)
- [Exporting Your Project](workflow/export.md)
- **Advanced Topics**
- [CLI Conversion and Automation](workflow/import.md)
- [Performance Tuning and Advanced Settings](workflow/tips.md)
- **API Reference**
- [SpriteStudioPlayer2D](api/player.md)
- [Resource Classes](api/resource.md)
- [Limitations & Scope](limitations.md)
- [Migration from v1.x](migration_from_v1.md)

## Key Features
Expand Down
34 changes: 34 additions & 0 deletions docs/en/limitations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Limitations & Scope

Constraints and platform-specific caveats to be aware of when shipping with the current SpriteStudio Player for Godot. For the list of what *is* supported, see the [Key Features](index.md#key-features) and workflow guides.

> [!NOTE]
> This is a living document. Items are added as they are confirmed; wording and coverage may change as the plugin evolves.

## Platforms & Export

The plugin ships in two build variants — **GDExtension** and **custom module** — and both can be exported to every Godot target. Build and execution are actively verified on **Windows / macOS**; the other targets are supported but less frequently exercised. See [Build Guide](setup/build.md) for the export flow of each.

Per-platform caveats to keep in mind:

- **macOS (GDExtension)** — released as a `universal` build (`arch=universal`).
- **iOS** — requires macOS + Xcode, and only `template_debug` / `template_release` are produced (no editor target).
- **Android** — the runtime is shipped as a native library placed under the matching ABI directory (`arm64-v8a` / `armeabi-v7a` / `x86_64`); build only the ABI of the device/emulator you run on.
- **Web** — see the dedicated section below.

## Web (WASM)

> [!WARNING]
> - **Single-threaded (`nothread`) only.** On the Web the plugin runs without threads. The upside is that no cross-origin isolation (COOP/COEP) headers are required, so a plain HTTP server is enough to run an export. Build the extension with `threads=no`.
> - **WebAssembly SIMD is required.** The runtime is built with WebAssembly SIMD instructions and will **not run on browsers without SIMD support**. Treat SIMD support as a browser requirement for your distribution.
> - **GDExtension on the Web needs a dlink-enabled engine template.** The official Godot Web export templates do not support GDExtension libraries. You must supply an engine template built with `dlink_enabled=yes` and turn on **"Extensions Support"** in the export preset — otherwise the exported page fails with *"GDExtension libraries are not supported by this engine version."* See [Exporting Your Project → Web](workflow/export.md#web) for the steps. (The **custom module** variant embeds the code into the engine itself and does not need this.)

## Playback Feature Constraints

These come from the shared `libssruntime` and therefore apply regardless of build variant.

> [!WARNING]
> - **`independent=true` parts (Instance / Effect) do not reverse or seek correctly.** An `independent=true` child runs on its own real-time clock, detached from the parent timeline. Parent **reverse playback** and **seeking** break it; only **forward** playback (including forward frame-skips) is correct. Prefer authoring without `independent=true` for animations that may be played in reverse or seeked.
> - **Seeking does not fire the events it skips over.** Jumping the playhead directly (e.g. setting the frame) does **not** emit the `UserData` / `Signal` / `Audio` events on the frames passed over — only the destination frame's events fire. If you need every intermediate event, advance the animation step by step instead of jumping.
> - **No reverse audio.** Sounds fire only while the animation advances forward in time. When the effective direction is backward (reverse direction, ping-pong return, or negative speed), audio events are skipped — audio cannot be played in reverse.
> - **Animation blending is same-`.ssab` only.** Cross-`.ssab` (cross-resource) blending is not supported, and every blended animation must assign the **same Cell to the same part**; mismatched Cells cause size / pivot mismatches that break the pose.
81 changes: 81 additions & 0 deletions docs/en/setup/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ If you want to debug the C++ code (`ss_player/`) of the plugin embedded as a cus

To verify and debug whether the custom module or GDExtension works correctly in the exported application, using the headless export from the CLI is convenient.

> [!IMPORTANT]
> Common export pitfalls (all platforms):
> - **Build the exact `target` you export with.** An `editor` build alone is not enough — `--export-debug` needs the `template_debug` library and `--export-release` needs `template_release`. If those were never built, the export still "succeeds" but ships an empty/missing extension library (on macOS this surfaces as a `CodeSign: Invalid binary format` error on the embedded framework).
> - **The extension architecture is bounded by the runtime slices you have.** The GDExtension links `libssruntime` from `ss_player/runtime/libs/<platform>/`; you can only build the architectures present there. For example, with an `arm64`-only macOS runtime you cannot produce a `universal` / `x86_64` extension — set the preset's `binary_format/architecture` to match (e.g. `arm64`). The engine template can still be `universal`; a single-arch extension just won't load on the missing arch.
> - **Enable ETC2/ASTC for `universal` / `arm64` / mobile exports.** Set `rendering/textures/vram_compression/import_etc2_astc=true` in the project (`project.godot` → `[rendering]`), otherwise the export aborts with *"Cannot export … with the ETC2/ASTC texture format disabled."*
> - **Export templates must match the editor version.** Setting `custom_template/debug` / `custom_template/release` bypasses the version check (this is how a template built from the bundled `godot/` source can be reused). Set **both** debug and release paths even for a debug-only export — Godot validates both and otherwise reports the release template as missing.

The following is the flow for building/installing templates and exporting a sample project. (The example below uses macOS)

1. **Build the runtime and templates**
Expand Down Expand Up @@ -218,6 +225,40 @@ python3 -m http.server 8000
After starting the server, access `http://localhost:8000` in your browser to verify it works.
(Since this plugin operates with `nothread` on the Web, it can be launched with a simple HTTP server without requiring special CORS headers.)

#### GDExtension on the Web (Extensions Support / `dlink`)

The official Godot Web export templates do **not** support GDExtension libraries. If you export the **GDExtension** build variant for the Web with a stock template, the page fails at startup with:

> GDExtension libraries are not supported by this engine version. Enable "Extensions Support" for your export preset and/or build your custom template with "dlink_enabled=yes".

To load a GDExtension on the Web, you need an engine template built with dynamic linking enabled (`dlink_enabled=yes`). Build one from the bundled `godot/` source, matching the `threads` mode of your extension (this plugin ships `nothread`, so use `threads=no`):

```bash
# Build dlink-enabled Web templates from source (nothreads)
cd godot
scons platform=web target=template_debug dlink_enabled=yes threads=no
scons platform=web target=template_release dlink_enabled=yes threads=no
# → godot/bin/godot.web.template_debug.wasm32.nothreads.dlink.zip
# → godot/bin/godot.web.template_release.wasm32.nothreads.dlink.zip
```

Then install the built templates so Godot can resolve them by name:

```bash
./scripts/install-template.sh web
# installs → <export_templates>/<version>/web_nothreads_dlink_debug.zip
# web_nothreads_dlink_release.zip
```

Once these are installed, exporting only requires turning on **Extensions Support** in the Web preset — Godot auto-selects the matching `..._dlink_...` template by name, so no `custom_template` is needed. The preset side (from a plugin user's perspective) is covered in [Exporting Your Project → Web](../workflow/export.md#web).

> If you would rather not install them into Godot's templates folder, you can instead point `custom_template/debug` / `custom_template/release` in the `Web` preset directly at the built `*.dlink.zip` files.

A dlink template splits the engine into a small main module plus a large `godot.side.wasm`; after export you will see a corresponding `index.side.wasm` alongside `index.wasm`, which confirms the dlink template was used.

> [!NOTE]
> `dlink` / *Extensions Support* is required only for the **GDExtension** build variant. The **custom module** variant compiles the plugin into the engine, so its Web template is the ordinary (non-`dlink`) `web_nothreads_{debug,release}.zip` produced by `release-web.sh` (via `build.sh`) and installed the same way — with no `dlink_enabled` and no *Extensions Support* in the preset.

### Android Platform Export and Testing

Android export templates are template APKs packaged by the engine's Gradle project. Unlike the desktop platforms, the template build therefore has three stages (runtime → per-ABI engine libraries → Gradle packaging) before `install-template.sh`.
Expand Down Expand Up @@ -271,6 +312,46 @@ Android export templates are template APKs packaged by the engine's Gradle proje
```
The `dev_module` sample plays the `Knight_arrow` animation on `SpriteStudioPlayer2D` with autoplay, so a successful run renders the character on screen.

### iOS Platform Export and Testing

iOS export requires **macOS with Xcode**. Godot generates an **Xcode project** (not a ready-to-run app) and then auto-runs `xcodebuild archive` for a device, which needs an Apple Developer account — so an **App Store Team ID must be set in the preset**, and the device-archive step fails without valid signing. For a quick, unsigned check, build the generated project for the **iOS Simulator** yourself.

> [!IMPORTANT]
> **Self-built iOS templates do not bundle MoltenVK.** Godot's iOS engine is built with Vulkan, so the app binary hard-links `@rpath/MoltenVK.framework/MoltenVK` (confirm with `otool -L`). This is a property of the *engine build*, not the project's renderer — a GL Compatibility project links it too. The **official** Godot iOS templates ship `MoltenVK.xcframework`; the template produced by `release-ios.sh` does **not**. When testing a self-built template you must supply it yourself, or the app crashes at launch with `Library not loaded: @rpath/MoltenVK.framework/MoltenVK`.

Simulator smoke-test of a self-built template (custom module shown; the GDExtension flow is identical with `dev_gdextension`):

```bash
# 1. Export the Xcode project (Godot's device-archive step will fail on signing — that's expected)
mkdir -p bin_export/ios
./godot/Godot.app/Contents/MacOS/Godot --path ./examples/dev_module/ --headless \
--export-debug "iOS" "$(pwd)/bin_export/ios/dev_module.xcodeproj" || true

# 2. Place MoltenVK where the Xcode project expects it (e.g. from the Vulkan SDK)
MVK="$HOME/VulkanSDK/<ver>/iOS/lib/MoltenVK.xcframework"
cp -R "$MVK" bin_export/ios/MoltenVK.xcframework

# 3. Build for the Simulator, unsigned
cd bin_export/ios
xcodebuild -project dev_module.xcodeproj -scheme dev_module \
-sdk iphonesimulator -configuration Debug -derivedDataPath ./DerivedData \
CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO build
APP="DerivedData/Build/Products/Debug-iphonesimulator/dev_module.app"

# 4. Embed MoltenVK into the app and ad-hoc re-sign (the simulator rejects the SDK's own signature)
cp -R "$MVK/ios-arm64_x86_64-simulator/MoltenVK.framework" "$APP/Frameworks/"
codesign --force --sign - "$APP/Frameworks/MoltenVK.framework"
codesign --force --sign - "$APP"

# 5. Boot a simulator, install, launch, screenshot
DEV=$(xcrun simctl list devices available | grep -m1 -oE '\([0-9A-F-]{36}\)' | tr -d '()')
xcrun simctl boot "$DEV" && xcrun simctl install "$DEV" "$APP"
xcrun simctl launch "$DEV" com.crimw.devmodule
xcrun simctl io "$DEV" screenshot screen.png
```

> **Note:** The proper fix is to bundle `MoltenVK.xcframework` into the iOS template itself (`install-template.sh` / `misc/dist/apple_embedded_xcode`) so the export embeds and signs it automatically, matching the official templates. The manual steps above are only needed for **self-built** templates — end users on the official Godot editor and official export templates are unaffected.

### GDExtension Export and Testing

For GDExtensions (e.g., `dev_gdextension`), **rebuilding the engine itself or installing custom templates is unnecessary**. You can export as-is using the standard Godot editor and official export templates distributed by Godot.
Expand Down
31 changes: 31 additions & 0 deletions docs/en/workflow/export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Exporting Your Project

Once your scene plays correctly in the editor, you export it like any other Godot project (**Project → Export…**). SpriteStudioPlayer runs in exported builds on every Godot target. There are only a few plugin-specific points to know.

## General

- **GDExtension variant** — the native library lives in your project's `addons/spritestudio/bin/`, and Godot bundles it into the export automatically. Desktop targets need nothing extra.
- **Custom module variant** — the plugin is compiled into the engine, so there is nothing plugin-specific to configure at export time.
- **Mobile / universal targets** — if an export stops with a message about the *ETC2/ASTC texture format being disabled*, enable **Project → Project Settings → Rendering → Textures → VRAM Compression → Import ETC2 ASTC**, then re-export.

## Web

Web builds have two plugin-specific requirements when you use the **GDExtension** variant.

1. **Enable "Extensions Support" in the Web export preset.**
In the Export dialog, select your **Web** preset → **Options** → turn on **Extensions Support**. GDExtension libraries only load on the Web when the engine template supports dynamic linking, and this option tells Godot to use that template.

2. **The dlink-enabled Web export templates must be installed.**
The stock Godot Web templates do not support GDExtension. You need the `web_nothreads_dlink_debug.zip` / `web_nothreads_dlink_release.zip` templates installed in your Godot export-templates folder. Building and installing them is an advanced step covered in the [Build Guide → GDExtension on the Web](../setup/build.md#web-platform-export-and-testing). Once they are in place, enabling **Extensions Support** is all the preset needs — Godot finds the right template automatically.

> [!WARNING]
> If a Web build fails at startup with *"GDExtension libraries are not supported by this engine version…"*, one of the two requirements above is missing (Extensions Support is off, or the dlink templates are not installed).

Additional notes for the Web:

- The plugin runs **single-threaded (`nothread`)** on the Web, so leave **Thread Support** off in the preset. A plain HTTP server is enough to test the export — no special cross-origin (COOP/COEP) headers are required.
- A working GDExtension Web export produces an `index.side.wasm` next to `index.wasm`; its presence confirms the dlink template was used.
- The runtime uses **WebAssembly SIMD**, so the target browser must support it.

> [!NOTE]
> The **custom module** variant needs none of the steps above — no *Extensions Support* and no dlink template — because the plugin is compiled into the engine. It still runs single-threaded on the Web, and (like every custom-module target) it uses **your own engine-built Web template**, which already contains the plugin, rather than a stock Godot template. That build/install flow is described in the [Build Guide](../setup/build.md).
2 changes: 2 additions & 0 deletions docs/ja/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
- [AnimationPlayer との連携](workflow/animation_player.md)
- [アセットのインポートとエディタ連携](workflow/usage_asset_pipeline.md)(初回の `.sspj` インポートはこちら)
- [スクリプト制御とイベント](workflow/usage_scripting.md)
- [プロジェクトのエクスポート](workflow/export.md)
- **応用**
- [CLI コンバートと自動化](workflow/import.md)
- [パフォーマンスチューニングと高度な設定](workflow/tips.md)
- **API リファレンス**
- [SpriteStudioPlayer2D](api/player.md)
- [リソース管理クラス](api/resource.md)
- [仕様と制約事項](limitations.md)
- [v1.x からのマイグレーション](migration_from_v1.md)

## 主な機能 (Key Features)
Expand Down
Loading
Loading