control-converter

August 21, 2026 · View on GitHub

中文

Convert control-layout JSON between Zalith Launcher 2 and FoldCraftLauncher.

License: MIT Python Demo API

Note: This tool was originally created by iqisge-gif, who is no longer actively maintaining the converter. This repository continues its development.

Quick Start

# ZL -> FCL
python cc.py zl2fcl zl_layout.json fcl_layout.json

# FCL -> ZL
python cc.py fcl2zl fcl_layout.json zl_layout.json

# auto-detect format
python cc.py auto input.json output.json

Zero dependencies. Python 3.8+ standard library only.

Install

git clone https://github.com/NingZeStudio/control-converter.git
cd control-converter

No pip install needed. Just run python cc.py.

Try it online: cc.miawa.cn -- web-based converter. API at api.cc.miawa.cn.

Android JNI Library

dist/libcc.so is a Go re-implementation of cc.py, built as an Android aarch64 JNI shared library. It is compiled in an Android (arm64) environment (e.g. Termux), then loaded from Java via System.loadLibrary("cc"). See BUILD.md for build instructions.

What It Does

Zalith Launcher 2 and FoldCraftLauncher use completely different JSON schemas for their on-screen control layouts -- different key codes, color formats, size units, and event models. This tool translates between the two, handling:

  • Key mapping -- bi-directional GLFW key names <-> FCL integer keycodes (100+ keys, 3 mouse buttons, scroll events)
  • Color conversion -- ZL Compose Color (signed Long packed sRGB) <-> FCL ARGB int, with alpha blending
  • Size conversion -- ZL dp/percentage/wrap_content <-> FCL ABSOLUTE/PERCENTAGE with per-mille scaling, including wrap_content dp estimation
  • Style mapping -- bidirectional button style conversion (text, border, fill, corner radius, pressed state)
  • Event translation -- key presses, launcher events (scroll, IME toggle, menu), send_text, layer visibility toggles
  • Layer preservation -- ZL layers -> FCL view groups with group-level visibility and order
  • Direction controls -- FCL rocker <-> ZL native joystick (ZL editor v12); FCL direction pad <-> ZL button grids
  • Roundtrip metadata -- embeds _control_converter metadata in output so the original layout can be recovered

Modes that can't map 1:1 use documented fallbacks with substitution tracking, printed to stderr.

Features

FeatureCLIAPI
ZL -> FCLzl2fcl/convert
FCL -> ZLfcl2zl/convert
Auto-detectauto/convert
Direction controls--include-directionsincludeDirections
Lossless mode--losslesslossless
Absolute -> percentage--absolute-as-percentageabsoluteAsPercentage
Strip metadata--strip-metastripMeta
Usable safe mode--usableusable
JSON comment support--/convert-file
Health check--GET /health

CLI Usage

python cc.py <mode> <input> <output> [options]

Modes

ModeDirection
zl2fclZalith Launcher 2 -> FoldCraftLauncher
fcl2zlFoldCraftLauncher -> Zalith Launcher 2
autoDetect format and convert
apiStart HTTP API server

Options

FlagEffect
--include-directionsConvert FCL direction controls: ROCKER -> ZL joystick, direction pad -> ZL button grids
--losslessSubstitute unsupported controls instead of dropping them; also converts FCL directions
--absolute-as-percentageConvert FCL absolute dp sizes to ZL percentage sizes
--strictFail on unsupported fields instead of warning
--compactOutput compact JSON (no whitespace)
--strip-metaRemove _control_converter metadata from output
--usableZL->FCL structural safe mode; remove only large blank blockers
--aspect 16/9Screen aspect ratio for direction approximation (default: 1.778)

API Server

Start the server:

python cc.py api --host 0.0.0.0 --port 8000

Endpoints

POST /convert -- Convert layout in request body.

{
  "mode": "zl2fcl",
  "data": { ... },
  "strict": false,
  "stripMeta": false
}

Response:

{ "ok": true, "data": { ... } }

POST /convert-file -- Convert uploaded JSON file. Supports // and /* */ comments.

POST /convert-file?mode=zl2fcl&strict=false
Content-Type: application/json

{ ... layout with comments ... }

GET /health -- Health check.

{ "ok": true }

Limitations

  • ZL wrap_content sizes have no FCL equivalent; estimated from text length and font size
  • ZL hideWhenMouse / hideWhenGamepad layer flags have no FCL equivalent; skipped with warning
  • FCL side mouse buttons 4-8 map to scroll events as fallback
  • FCL KEY_KPCOMMA has no exact GLFW key; falls back to keypad decimal

All substitutions are tracked, documented with reasons, and printed to stderr.

License

MIT -- see LICENSE.