sprout-toolkit 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sprout_toolkit-0.1.0/LICENSE +21 -0
- sprout_toolkit-0.1.0/PKG-INFO +208 -0
- sprout_toolkit-0.1.0/README.md +160 -0
- sprout_toolkit-0.1.0/pyproject.toml +47 -0
- sprout_toolkit-0.1.0/setup.cfg +4 -0
- sprout_toolkit-0.1.0/sprout/__init__.py +3 -0
- sprout_toolkit-0.1.0/sprout/assets/fonts/DejaVuSansMono-Bold.LICENSE.txt +78 -0
- sprout_toolkit-0.1.0/sprout/assets/fonts/DejaVuSansMono-Bold.ttf +0 -0
- sprout_toolkit-0.1.0/sprout/autotile.py +57 -0
- sprout_toolkit-0.1.0/sprout/cli.py +518 -0
- sprout_toolkit-0.1.0/sprout/exporter.py +687 -0
- sprout_toolkit-0.1.0/sprout/generators/__init__.py +35 -0
- sprout_toolkit-0.1.0/sprout/generators/base.py +31 -0
- sprout_toolkit-0.1.0/sprout/generators/blob_walk.py +71 -0
- sprout_toolkit-0.1.0/sprout/generators/font.py +79 -0
- sprout_toolkit-0.1.0/sprout/generators/particles.py +136 -0
- sprout_toolkit-0.1.0/sprout/generators/props.py +189 -0
- sprout_toolkit-0.1.0/sprout/generators/terrain.py +179 -0
- sprout_toolkit-0.1.0/sprout/generators/ui.py +169 -0
- sprout_toolkit-0.1.0/sprout/sksl.py +139 -0
- sprout_toolkit-0.1.0/sprout/spec.py +193 -0
- sprout_toolkit-0.1.0/sprout_toolkit.egg-info/PKG-INFO +208 -0
- sprout_toolkit-0.1.0/sprout_toolkit.egg-info/SOURCES.txt +35 -0
- sprout_toolkit-0.1.0/sprout_toolkit.egg-info/dependency_links.txt +1 -0
- sprout_toolkit-0.1.0/sprout_toolkit.egg-info/entry_points.txt +2 -0
- sprout_toolkit-0.1.0/sprout_toolkit.egg-info/requires.txt +5 -0
- sprout_toolkit-0.1.0/sprout_toolkit.egg-info/top_level.txt +1 -0
- sprout_toolkit-0.1.0/tests/test_autotile.py +160 -0
- sprout_toolkit-0.1.0/tests/test_cli.py +407 -0
- sprout_toolkit-0.1.0/tests/test_determinism.py +107 -0
- sprout_toolkit-0.1.0/tests/test_exporter.py +126 -0
- sprout_toolkit-0.1.0/tests/test_font.py +121 -0
- sprout_toolkit-0.1.0/tests/test_particles.py +161 -0
- sprout_toolkit-0.1.0/tests/test_props.py +174 -0
- sprout_toolkit-0.1.0/tests/test_sksl.py +112 -0
- sprout_toolkit-0.1.0/tests/test_spec.py +65 -0
- sprout_toolkit-0.1.0/tests/test_ui.py +161 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tzinny
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sprout-toolkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generación procedural determinista de assets 2D para Expo + react-native-skia
|
|
5
|
+
Author: Tzinny
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Tzinny
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/Tzinny-dev/sprout-toolkit
|
|
29
|
+
Project-URL: Repository, https://github.com/Tzinny-dev/sprout-toolkit
|
|
30
|
+
Project-URL: Issues, https://github.com/Tzinny-dev/sprout-toolkit/issues
|
|
31
|
+
Keywords: procgen,sprites,spritesheet,skia,expo,react-native,game-dev
|
|
32
|
+
Classifier: Development Status :: 3 - Alpha
|
|
33
|
+
Classifier: Environment :: Console
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Topic :: Games/Entertainment
|
|
38
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
39
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: pillow>=10
|
|
44
|
+
Requires-Dist: typer>=0.12
|
|
45
|
+
Provides-Extra: test
|
|
46
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# sprout-toolkit
|
|
50
|
+
|
|
51
|
+
**SPROUT** — Skia Procedural Rendering & Optimization Unified Toolkit
|
|
52
|
+
|
|
53
|
+
> Grow your 2D assets procedurally.
|
|
54
|
+
|
|
55
|
+
Sprout es un toolkit de código abierto para **generación procedural determinista de assets 2D**
|
|
56
|
+
destinados a [Expo](https://expo.dev) + [`react-native-skia`](https://github.com/Shopify/react-native-skia).
|
|
57
|
+
Genera atlases, mapas de tiles, autotiles, bitmap fonts y shaders SkSL a partir de specs JSON.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Arquitectura
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
sprout/
|
|
65
|
+
├── sprout/ # Paquete Python
|
|
66
|
+
│ ├── __init__.py # __version__
|
|
67
|
+
│ ├── cli.py # CLI (Typer): generate, batch, watch, info, lint, diff, validate
|
|
68
|
+
│ ├── exporter.py # Spritesheet packing, manifest.json, index.ts
|
|
69
|
+
│ ├── spec.py # Carga/validación de specs JSON (schema v0)
|
|
70
|
+
│ ├── autotile.py # Máscaras 8-bit, lookup 16/47
|
|
71
|
+
│ ├── sksl.py # Shaders SkSL runtime (FBM value-noise)
|
|
72
|
+
│ ├── assets/fonts/ # Fuente empaquetada (viaja en el wheel)
|
|
73
|
+
│ └── generators/ # Plugins de generación
|
|
74
|
+
│ ├── base.py # FrameData + Generator (contrato)
|
|
75
|
+
│ ├── terrain.py # Tiles seamless + autotile
|
|
76
|
+
│ ├── props.py # Objetos estáticos (5 kinds, anchor points)
|
|
77
|
+
│ ├── particles.py # Bursts animados con easing
|
|
78
|
+
│ ├── ui.py # Botón, slider, panel 9-patch
|
|
79
|
+
│ ├── font.py # Bitmap font desde TTF (un glifo por frame)
|
|
80
|
+
│ └── blob_walk.py # 8-frame walk cycle
|
|
81
|
+
├── specs/ # Specs de ejemplo (uno por generador)
|
|
82
|
+
├── tests/ # 142 tests (determinismo, autotile, SkSL, generadores, CLI)
|
|
83
|
+
├── LICENSE # MIT
|
|
84
|
+
└── pyproject.toml
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Características
|
|
88
|
+
|
|
89
|
+
| Característica | Descripción |
|
|
90
|
+
|---|---|
|
|
91
|
+
| **Procgen determinista** | Seeds numéricas → assets reproducibles (testeable en CI). |
|
|
92
|
+
| **Auto-tile 8-bit** | Máscara de autotile con 8 bits (N/E/S/W + diagonales), 16 o 47 variantes. |
|
|
93
|
+
| **Bitmap fonts desde TTF** | Atlas de glifos con métricas de avance, listo para layout de texto. |
|
|
94
|
+
| **Shaders SkSL runtime** | Shaders generados para Skia (FBM value-noise, tileable), sin engordar el bundle. |
|
|
95
|
+
| **Introspección de specs** | `sprout info`/`sprout lint`/`sprout diff` para inspeccionar, validar calidad y comparar builds. |
|
|
96
|
+
| **Exportación flexible** | PNG8/PNG24, formato TexturePacker, mipmaps del atlas — todo opt-in. |
|
|
97
|
+
|
|
98
|
+
## Instalación
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pip install sprout-toolkit
|
|
102
|
+
# o en desarrollo:
|
|
103
|
+
git clone https://github.com/Tzinny-dev/sprout-toolkit
|
|
104
|
+
cd sprout-toolkit
|
|
105
|
+
python -m venv .venv && source .venv/bin/activate
|
|
106
|
+
pip install -e ".[test]"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
El comando instalado es `sprout` (no `sprout-toolkit` — ese es solo el nombre de distribución en PyPI).
|
|
110
|
+
|
|
111
|
+
## Uso rápido
|
|
112
|
+
|
|
113
|
+
### Generar assets
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Generar todos los assets definidos en specs/
|
|
117
|
+
sprout batch specs/ --out ./out
|
|
118
|
+
|
|
119
|
+
# Generar un spec específico
|
|
120
|
+
sprout generate specs/demo.json --out ./out
|
|
121
|
+
|
|
122
|
+
# Modo watch: regenera al detectar cambios en specs/ (Ctrl-C para salir)
|
|
123
|
+
sprout watch specs/ --out ./out --interval 1.0
|
|
124
|
+
|
|
125
|
+
# Inspeccionar una spec (reporte humano o JSON)
|
|
126
|
+
sprout info specs/particles.json
|
|
127
|
+
sprout info --json specs/particles.json
|
|
128
|
+
|
|
129
|
+
# Analizar calidad de una spec: padding de atlas + frames vacíos
|
|
130
|
+
sprout lint specs/ui.json
|
|
131
|
+
sprout lint --json specs/ui.json
|
|
132
|
+
|
|
133
|
+
# Generar un atlas de bitmap font (ASCII imprimible, fuente empaquetada)
|
|
134
|
+
sprout generate specs/font.json --out ./out
|
|
135
|
+
|
|
136
|
+
# Comparar dos specs, o dos directorios de salida ya generados
|
|
137
|
+
sprout diff specs/props.json specs/ui.json
|
|
138
|
+
sprout diff --json ./out/a ./out/b
|
|
139
|
+
|
|
140
|
+
# Validar un spec
|
|
141
|
+
sprout validate specs/demo.json
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Opciones de exportación (`generate` / `batch`)
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# PNG8 (paleta indexada, atlas más liviano) o PNG24 (sin alpha)
|
|
148
|
+
sprout generate specs/ui.json --png-mode png8
|
|
149
|
+
sprout generate specs/autotile.json --png-mode png24 # solo si el atlas no usa transparencia
|
|
150
|
+
|
|
151
|
+
# Además de manifest.json, emite <name>.tpsheet.json (formato TexturePacker JSON Hash)
|
|
152
|
+
sprout generate specs/props.json --texturepacker
|
|
153
|
+
|
|
154
|
+
# Cadena de mip levels del atlas (@0.5x, @0.25x, @0.125x por defecto)
|
|
155
|
+
sprout generate specs/particles.json --mipmaps
|
|
156
|
+
sprout generate specs/particles.json --mipmaps --mipmap-levels 2
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`--png-mode` default es `rgba` (sin cambios). `png8` cuantiza a 256 colores
|
|
160
|
+
preservando el canal alpha (ideal para paletas acotadas tipo pixel-art);
|
|
161
|
+
`png24` descarta el alpha por completo — solo usarlo en atlases sin
|
|
162
|
+
transparencia real (p. ej. `terrain`). `--texturepacker`/`--mipmaps` son
|
|
163
|
+
opt-in y no afectan `manifest.json`/`index.ts`, salvo que `--mipmaps`
|
|
164
|
+
agrega el bloque `mipmaps.levels` al manifest.
|
|
165
|
+
|
|
166
|
+
### Generadores disponibles
|
|
167
|
+
|
|
168
|
+
| `generator` | Descripción | Params |
|
|
169
|
+
|-------------|-------------|--------|
|
|
170
|
+
| `terrain` | Tiles de ruido seamless + autotile 16/47 | `contrast`, `lift`, `cells`, `octaves`, `bevel`, `autotile` |
|
|
171
|
+
| `blob_walk` | Ciclo de caminata de 8 frames (hero blob) | colores (`body`, `outline`, `belly`, ...) |
|
|
172
|
+
| `props` | Objetos estáticos: `rock`, `bush`, `chest`, `mushroom`, `flower` — cada frame incluye un anchor point (`frames[].anchor` en el manifest, calculado desde el bbox alpha real) | `kind`, `fill`, `outline` |
|
|
173
|
+
| `particles` | Bursts animados: `spark`, `smoke`, `dust`, `bubble` | `kind`, `particles`, `core`, `trail` |
|
|
174
|
+
| `ui` | Interfaz: `button` (estados normal/hover/pressed), `slider` (progreso + knob), `panel` (9-patch, `frames=9`) | `kind`, `fill`, `outline`, `accent` |
|
|
175
|
+
| `font` | Bitmap font desde TTF, un glifo por frame (`frames` = `len(chars)`) | `chars`, `font_path`, `size`, `fill` |
|
|
176
|
+
|
|
177
|
+
Ejemplo de spec con `props`:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"name": "props_atlas",
|
|
182
|
+
"seed": 2024,
|
|
183
|
+
"layout": { "framePx": 64, "cols": 6, "tileLogical": 32, "sample": "nearest" },
|
|
184
|
+
"items": [
|
|
185
|
+
{ "id": "rock", "generator": "props", "frames": 6, "params": { "kind": "rock" } },
|
|
186
|
+
{ "id": "chest", "generator": "props", "frames": 4, "params": { "kind": "chest", "fill": [160, 110, 50] } }
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Desarrollo
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
pip install -e ".[test]"
|
|
195
|
+
pytest -q
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
CI (`.github/workflows/tests.yml`) corre la suite completa en cada push/PR.
|
|
199
|
+
|
|
200
|
+
## Créditos
|
|
201
|
+
|
|
202
|
+
- `typer` + `Pillow` — CLI y generación de imágenes
|
|
203
|
+
- **DejaVu Fonts** (`DejaVuSansMono-Bold.ttf`, empaquetada en `sprout/assets/fonts/`) —
|
|
204
|
+
licencia Bitstream Vera, ver `sprout/assets/fonts/DejaVuSansMono-Bold.LICENSE.txt`
|
|
205
|
+
|
|
206
|
+
## Licencia
|
|
207
|
+
|
|
208
|
+
MIT — ver [LICENSE](LICENSE).
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# sprout-toolkit
|
|
2
|
+
|
|
3
|
+
**SPROUT** — Skia Procedural Rendering & Optimization Unified Toolkit
|
|
4
|
+
|
|
5
|
+
> Grow your 2D assets procedurally.
|
|
6
|
+
|
|
7
|
+
Sprout es un toolkit de código abierto para **generación procedural determinista de assets 2D**
|
|
8
|
+
destinados a [Expo](https://expo.dev) + [`react-native-skia`](https://github.com/Shopify/react-native-skia).
|
|
9
|
+
Genera atlases, mapas de tiles, autotiles, bitmap fonts y shaders SkSL a partir de specs JSON.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Arquitectura
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
sprout/
|
|
17
|
+
├── sprout/ # Paquete Python
|
|
18
|
+
│ ├── __init__.py # __version__
|
|
19
|
+
│ ├── cli.py # CLI (Typer): generate, batch, watch, info, lint, diff, validate
|
|
20
|
+
│ ├── exporter.py # Spritesheet packing, manifest.json, index.ts
|
|
21
|
+
│ ├── spec.py # Carga/validación de specs JSON (schema v0)
|
|
22
|
+
│ ├── autotile.py # Máscaras 8-bit, lookup 16/47
|
|
23
|
+
│ ├── sksl.py # Shaders SkSL runtime (FBM value-noise)
|
|
24
|
+
│ ├── assets/fonts/ # Fuente empaquetada (viaja en el wheel)
|
|
25
|
+
│ └── generators/ # Plugins de generación
|
|
26
|
+
│ ├── base.py # FrameData + Generator (contrato)
|
|
27
|
+
│ ├── terrain.py # Tiles seamless + autotile
|
|
28
|
+
│ ├── props.py # Objetos estáticos (5 kinds, anchor points)
|
|
29
|
+
│ ├── particles.py # Bursts animados con easing
|
|
30
|
+
│ ├── ui.py # Botón, slider, panel 9-patch
|
|
31
|
+
│ ├── font.py # Bitmap font desde TTF (un glifo por frame)
|
|
32
|
+
│ └── blob_walk.py # 8-frame walk cycle
|
|
33
|
+
├── specs/ # Specs de ejemplo (uno por generador)
|
|
34
|
+
├── tests/ # 142 tests (determinismo, autotile, SkSL, generadores, CLI)
|
|
35
|
+
├── LICENSE # MIT
|
|
36
|
+
└── pyproject.toml
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Características
|
|
40
|
+
|
|
41
|
+
| Característica | Descripción |
|
|
42
|
+
|---|---|
|
|
43
|
+
| **Procgen determinista** | Seeds numéricas → assets reproducibles (testeable en CI). |
|
|
44
|
+
| **Auto-tile 8-bit** | Máscara de autotile con 8 bits (N/E/S/W + diagonales), 16 o 47 variantes. |
|
|
45
|
+
| **Bitmap fonts desde TTF** | Atlas de glifos con métricas de avance, listo para layout de texto. |
|
|
46
|
+
| **Shaders SkSL runtime** | Shaders generados para Skia (FBM value-noise, tileable), sin engordar el bundle. |
|
|
47
|
+
| **Introspección de specs** | `sprout info`/`sprout lint`/`sprout diff` para inspeccionar, validar calidad y comparar builds. |
|
|
48
|
+
| **Exportación flexible** | PNG8/PNG24, formato TexturePacker, mipmaps del atlas — todo opt-in. |
|
|
49
|
+
|
|
50
|
+
## Instalación
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install sprout-toolkit
|
|
54
|
+
# o en desarrollo:
|
|
55
|
+
git clone https://github.com/Tzinny-dev/sprout-toolkit
|
|
56
|
+
cd sprout-toolkit
|
|
57
|
+
python -m venv .venv && source .venv/bin/activate
|
|
58
|
+
pip install -e ".[test]"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
El comando instalado es `sprout` (no `sprout-toolkit` — ese es solo el nombre de distribución en PyPI).
|
|
62
|
+
|
|
63
|
+
## Uso rápido
|
|
64
|
+
|
|
65
|
+
### Generar assets
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Generar todos los assets definidos en specs/
|
|
69
|
+
sprout batch specs/ --out ./out
|
|
70
|
+
|
|
71
|
+
# Generar un spec específico
|
|
72
|
+
sprout generate specs/demo.json --out ./out
|
|
73
|
+
|
|
74
|
+
# Modo watch: regenera al detectar cambios en specs/ (Ctrl-C para salir)
|
|
75
|
+
sprout watch specs/ --out ./out --interval 1.0
|
|
76
|
+
|
|
77
|
+
# Inspeccionar una spec (reporte humano o JSON)
|
|
78
|
+
sprout info specs/particles.json
|
|
79
|
+
sprout info --json specs/particles.json
|
|
80
|
+
|
|
81
|
+
# Analizar calidad de una spec: padding de atlas + frames vacíos
|
|
82
|
+
sprout lint specs/ui.json
|
|
83
|
+
sprout lint --json specs/ui.json
|
|
84
|
+
|
|
85
|
+
# Generar un atlas de bitmap font (ASCII imprimible, fuente empaquetada)
|
|
86
|
+
sprout generate specs/font.json --out ./out
|
|
87
|
+
|
|
88
|
+
# Comparar dos specs, o dos directorios de salida ya generados
|
|
89
|
+
sprout diff specs/props.json specs/ui.json
|
|
90
|
+
sprout diff --json ./out/a ./out/b
|
|
91
|
+
|
|
92
|
+
# Validar un spec
|
|
93
|
+
sprout validate specs/demo.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Opciones de exportación (`generate` / `batch`)
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# PNG8 (paleta indexada, atlas más liviano) o PNG24 (sin alpha)
|
|
100
|
+
sprout generate specs/ui.json --png-mode png8
|
|
101
|
+
sprout generate specs/autotile.json --png-mode png24 # solo si el atlas no usa transparencia
|
|
102
|
+
|
|
103
|
+
# Además de manifest.json, emite <name>.tpsheet.json (formato TexturePacker JSON Hash)
|
|
104
|
+
sprout generate specs/props.json --texturepacker
|
|
105
|
+
|
|
106
|
+
# Cadena de mip levels del atlas (@0.5x, @0.25x, @0.125x por defecto)
|
|
107
|
+
sprout generate specs/particles.json --mipmaps
|
|
108
|
+
sprout generate specs/particles.json --mipmaps --mipmap-levels 2
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`--png-mode` default es `rgba` (sin cambios). `png8` cuantiza a 256 colores
|
|
112
|
+
preservando el canal alpha (ideal para paletas acotadas tipo pixel-art);
|
|
113
|
+
`png24` descarta el alpha por completo — solo usarlo en atlases sin
|
|
114
|
+
transparencia real (p. ej. `terrain`). `--texturepacker`/`--mipmaps` son
|
|
115
|
+
opt-in y no afectan `manifest.json`/`index.ts`, salvo que `--mipmaps`
|
|
116
|
+
agrega el bloque `mipmaps.levels` al manifest.
|
|
117
|
+
|
|
118
|
+
### Generadores disponibles
|
|
119
|
+
|
|
120
|
+
| `generator` | Descripción | Params |
|
|
121
|
+
|-------------|-------------|--------|
|
|
122
|
+
| `terrain` | Tiles de ruido seamless + autotile 16/47 | `contrast`, `lift`, `cells`, `octaves`, `bevel`, `autotile` |
|
|
123
|
+
| `blob_walk` | Ciclo de caminata de 8 frames (hero blob) | colores (`body`, `outline`, `belly`, ...) |
|
|
124
|
+
| `props` | Objetos estáticos: `rock`, `bush`, `chest`, `mushroom`, `flower` — cada frame incluye un anchor point (`frames[].anchor` en el manifest, calculado desde el bbox alpha real) | `kind`, `fill`, `outline` |
|
|
125
|
+
| `particles` | Bursts animados: `spark`, `smoke`, `dust`, `bubble` | `kind`, `particles`, `core`, `trail` |
|
|
126
|
+
| `ui` | Interfaz: `button` (estados normal/hover/pressed), `slider` (progreso + knob), `panel` (9-patch, `frames=9`) | `kind`, `fill`, `outline`, `accent` |
|
|
127
|
+
| `font` | Bitmap font desde TTF, un glifo por frame (`frames` = `len(chars)`) | `chars`, `font_path`, `size`, `fill` |
|
|
128
|
+
|
|
129
|
+
Ejemplo de spec con `props`:
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"name": "props_atlas",
|
|
134
|
+
"seed": 2024,
|
|
135
|
+
"layout": { "framePx": 64, "cols": 6, "tileLogical": 32, "sample": "nearest" },
|
|
136
|
+
"items": [
|
|
137
|
+
{ "id": "rock", "generator": "props", "frames": 6, "params": { "kind": "rock" } },
|
|
138
|
+
{ "id": "chest", "generator": "props", "frames": 4, "params": { "kind": "chest", "fill": [160, 110, 50] } }
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Desarrollo
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pip install -e ".[test]"
|
|
147
|
+
pytest -q
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
CI (`.github/workflows/tests.yml`) corre la suite completa en cada push/PR.
|
|
151
|
+
|
|
152
|
+
## Créditos
|
|
153
|
+
|
|
154
|
+
- `typer` + `Pillow` — CLI y generación de imágenes
|
|
155
|
+
- **DejaVu Fonts** (`DejaVuSansMono-Bold.ttf`, empaquetada en `sprout/assets/fonts/`) —
|
|
156
|
+
licencia Bitstream Vera, ver `sprout/assets/fonts/DejaVuSansMono-Bold.LICENSE.txt`
|
|
157
|
+
|
|
158
|
+
## Licencia
|
|
159
|
+
|
|
160
|
+
MIT — ver [LICENSE](LICENSE).
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sprout-toolkit"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Generación procedural determinista de assets 2D para Expo + react-native-skia"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [{ name = "Tzinny" }]
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
license = { file = "LICENSE" }
|
|
13
|
+
keywords = ["procgen", "sprites", "spritesheet", "skia", "expo", "react-native", "game-dev"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Topic :: Games/Entertainment",
|
|
21
|
+
"Topic :: Multimedia :: Graphics",
|
|
22
|
+
"Topic :: Software Development :: Code Generators",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"pillow>=10",
|
|
26
|
+
"typer>=0.12",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/Tzinny-dev/sprout-toolkit"
|
|
31
|
+
Repository = "https://github.com/Tzinny-dev/sprout-toolkit"
|
|
32
|
+
Issues = "https://github.com/Tzinny-dev/sprout-toolkit/issues"
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
test = ["pytest>=8"]
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
sprout = "sprout.cli:app"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages.find]
|
|
41
|
+
include = ["sprout*"]
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.package-data]
|
|
44
|
+
sprout = ["assets/fonts/*.ttf", "assets/fonts/*.txt"]
|
|
45
|
+
|
|
46
|
+
[tool.pytest.ini_options]
|
|
47
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
2
|
+
Upstream-Name: DejaVu fonts
|
|
3
|
+
Upstream-Author: Stepan Roh <src@users.sourceforge.net> (original author),
|
|
4
|
+
see /usr/share/doc/fonts-dejavu-core/AUTHORS for full list
|
|
5
|
+
Source: https://dejavu-fonts.github.io/
|
|
6
|
+
|
|
7
|
+
Files: *
|
|
8
|
+
Copyright: Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.
|
|
9
|
+
Bitstream Vera is a trademark of Bitstream, Inc.
|
|
10
|
+
DejaVu changes are in public domain.
|
|
11
|
+
License: bitstream-vera
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of the fonts accompanying this license ("Fonts") and associated
|
|
14
|
+
documentation files (the "Font Software"), to reproduce and distribute the
|
|
15
|
+
Font Software, including without limitation the rights to use, copy, merge,
|
|
16
|
+
publish, distribute, and/or sell copies of the Font Software, and to permit
|
|
17
|
+
persons to whom the Font Software is furnished to do so, subject to the
|
|
18
|
+
following conditions:
|
|
19
|
+
.
|
|
20
|
+
The above copyright and trademark notices and this permission notice shall
|
|
21
|
+
be included in all copies of one or more of the Font Software typefaces.
|
|
22
|
+
.
|
|
23
|
+
The Font Software may be modified, altered, or added to, and in particular
|
|
24
|
+
the designs of glyphs or characters in the Fonts may be modified and
|
|
25
|
+
additional glyphs or characters may be added to the Fonts, only if the fonts
|
|
26
|
+
are renamed to names not containing either the words "Bitstream" or the word
|
|
27
|
+
"Vera".
|
|
28
|
+
.
|
|
29
|
+
This License becomes null and void to the extent applicable to Fonts or Font
|
|
30
|
+
Software that has been modified and is distributed under the "Bitstream
|
|
31
|
+
Vera" names.
|
|
32
|
+
.
|
|
33
|
+
The Font Software may be sold as part of a larger software package but no
|
|
34
|
+
copy of one or more of the Font Software typefaces may be sold by itself.
|
|
35
|
+
.
|
|
36
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
37
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
|
38
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
|
39
|
+
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
|
40
|
+
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
|
41
|
+
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
|
42
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
43
|
+
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
|
44
|
+
FONT SOFTWARE.
|
|
45
|
+
.
|
|
46
|
+
Except as contained in this notice, the names of Gnome, the Gnome
|
|
47
|
+
Foundation, and Bitstream Inc., shall not be used in advertising or
|
|
48
|
+
otherwise to promote the sale, use or other dealings in this Font Software
|
|
49
|
+
without prior written authorization from the Gnome Foundation or Bitstream
|
|
50
|
+
Inc., respectively. For further information, contact: fonts at gnome dot
|
|
51
|
+
org.
|
|
52
|
+
|
|
53
|
+
Files: debian/*
|
|
54
|
+
Copyright: (C) 2005-2006 Peter Cernak <pce@users.sourceforge.net>
|
|
55
|
+
(C) 2006-2011 Davide Viti <zinosat@tiscali.it>
|
|
56
|
+
(C) 2011-2013 Christian Perrier <bubulle@debian.org>
|
|
57
|
+
(C) 2013 Fabian Greffrath <fabian+debian@greffrath.com>
|
|
58
|
+
License: GPL-2+
|
|
59
|
+
This program is free software; you can redistribute it
|
|
60
|
+
and/or modify it under the terms of the GNU General Public
|
|
61
|
+
License as published by the Free Software Foundation; either
|
|
62
|
+
version 2 of the License, or (at your option) any later
|
|
63
|
+
version.
|
|
64
|
+
.
|
|
65
|
+
This program is distributed in the hope that it will be
|
|
66
|
+
useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
67
|
+
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
68
|
+
PURPOSE. See the GNU General Public License for more
|
|
69
|
+
details.
|
|
70
|
+
.
|
|
71
|
+
You should have received a copy of the GNU General Public
|
|
72
|
+
License along with this package; if not, write to the Free
|
|
73
|
+
Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
74
|
+
Boston, MA 02110-1301 USA
|
|
75
|
+
.
|
|
76
|
+
On Debian systems, the full text of the GNU General Public
|
|
77
|
+
License version 2 can be found in the file
|
|
78
|
+
/usr/share/common-licenses/GPL-2'.
|
|
Binary file
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Autotiling 16 / 47 — reducción canónica de máscaras de vecindad 8-bit.
|
|
2
|
+
|
|
3
|
+
Bits (convención canónica sprout, ver INVESTIGACION.md §5.3)::
|
|
4
|
+
|
|
5
|
+
N=1, NE=2, E=4, SE=8, S=16, SW=32, W=64, NW=128
|
|
6
|
+
|
|
7
|
+
El bit diagonal solo cuenta si **ambos** cardinales adyacentes están presentes:
|
|
8
|
+
así 2**8 = 256 vecindades colapsan a 47. Un "corner bit" describe el cuadrante
|
|
9
|
+
donde se juntan sus dos lados; si falta un lado, ese cuadrante ya es borde
|
|
10
|
+
exterior y la diagonal no aporta una silueta distinta.
|
|
11
|
+
|
|
12
|
+
Referencia verificada contra Godot 4.7 (Blobsmith Autotile Wirer, MIT):
|
|
13
|
+
https://github.com/leobaray/blobsmith-autotile-wirer/blob/master/docs/why-47-tiles-not-256.md
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
N, NE, E, SE, S, SW, W, NW = 1, 2, 4, 8, 16, 32, 64, 128
|
|
18
|
+
|
|
19
|
+
SIDES = N | E | S | W # 0b01010101 == 85
|
|
20
|
+
CORNERS = NE | SE | SW | NW
|
|
21
|
+
|
|
22
|
+
BITMASK = "N1,E4,S16,W64,NE2,SE8,SW32,NW128"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def canonical_47(mask: int) -> int:
|
|
26
|
+
"""Máscara canónica del sistema 8-bit (47 clases)."""
|
|
27
|
+
m = mask & SIDES
|
|
28
|
+
if (mask & NE) and (mask & N) and (mask & E):
|
|
29
|
+
m |= NE
|
|
30
|
+
if (mask & SE) and (mask & S) and (mask & E):
|
|
31
|
+
m |= SE
|
|
32
|
+
if (mask & SW) and (mask & S) and (mask & W):
|
|
33
|
+
m |= SW
|
|
34
|
+
if (mask & NW) and (mask & N) and (mask & W):
|
|
35
|
+
m |= NW
|
|
36
|
+
return m
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def canonical_16(mask: int) -> int:
|
|
40
|
+
"""Máscara canónica del sistema cardinal (16 clases, Match Sides)."""
|
|
41
|
+
return mask & SIDES
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def canonical(mask: int, size: int) -> int:
|
|
45
|
+
if size == 16:
|
|
46
|
+
return canonical_16(mask)
|
|
47
|
+
if size == 47:
|
|
48
|
+
return canonical_47(mask)
|
|
49
|
+
raise ValueError(f"autotile no soportado: {size!r} (esperado 16 | 47)")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def masks(size: int) -> list[int]:
|
|
53
|
+
"""Máscaras canónicas en orden ascendente = orden de la hoja (cols=8)."""
|
|
54
|
+
fn = {16: canonical_16, 47: canonical_47}.get(size)
|
|
55
|
+
if fn is None:
|
|
56
|
+
raise ValueError(f"autotile no soportado: {size!r} (esperado 16 | 47)")
|
|
57
|
+
return [m for m in range(256) if fn(m) == m]
|