gummy-snake 0.5.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.
- gummy_snake-0.5.0/PKG-INFO +208 -0
- gummy_snake-0.5.0/README.md +186 -0
- gummy_snake-0.5.0/crates/gummy_canvas/Cargo.lock +2609 -0
- gummy_snake-0.5.0/crates/gummy_canvas/Cargo.toml +22 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/bindings.rs +353 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/curves.rs +191 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/gpu.rs +267 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/images/helpers.rs +212 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/images/mod.rs +142 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/lifecycle.rs +243 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/methods.rs +324 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/mod.rs +8 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/pixels.rs +212 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/primitives.rs +232 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/text/cache.rs +209 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/canvas/text/mod.rs +130 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/mod.rs +13 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/pipeline.rs +277 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/render.rs +223 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/setup.rs +183 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/shaders.rs +117 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/surface.rs +162 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/tests.rs +73 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/textures.rs +136 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/gpu/types.rs +96 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/images.rs +265 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/lib.rs +443 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/performance.rs +45 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/raster/blend.rs +70 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/raster/blit.rs +179 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/raster/gpu.rs +29 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/raster/mod.rs +22 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/raster/queries.rs +91 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/raster/shapes.rs +236 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/raster/transform.rs +187 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/raster/types.rs +69 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/runtime/app/handler.rs +130 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/runtime/app.rs +236 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/runtime/desktop.rs +94 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/runtime/event.rs +138 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/runtime/input.rs +106 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/runtime/mod.rs +20 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/runtime/stub.rs +49 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/runtime/style.rs +229 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/lighting.rs +106 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/math.rs +97 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/mod.rs +389 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/obj.rs +411 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/payload.rs +178 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/primitives.rs +397 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/project.rs +176 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/rasterize.rs +211 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/software3d/types.rs +77 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/tests.rs +225 -0
- gummy_snake-0.5.0/crates/gummy_canvas/src/text.rs +139 -0
- gummy_snake-0.5.0/license.txt +458 -0
- gummy_snake-0.5.0/pyproject.toml +83 -0
- gummy_snake-0.5.0/src/gummysnake/__init__.py +745 -0
- gummy_snake-0.5.0/src/gummysnake/_async.py +81 -0
- gummy_snake-0.5.0/src/gummysnake/_context/__init__.py +1 -0
- gummy_snake-0.5.0/src/gummysnake/_context/_protocols.py +16 -0
- gummy_snake-0.5.0/src/gummysnake/_context/canvas.py +233 -0
- gummy_snake-0.5.0/src/gummysnake/_context/helpers.py +114 -0
- gummy_snake-0.5.0/src/gummysnake/_context/images.py +45 -0
- gummy_snake-0.5.0/src/gummysnake/_context/input.py +120 -0
- gummy_snake-0.5.0/src/gummysnake/_context/pixels.py +241 -0
- gummy_snake-0.5.0/src/gummysnake/_context/shapes.py +226 -0
- gummy_snake-0.5.0/src/gummysnake/_context/style.py +121 -0
- gummy_snake-0.5.0/src/gummysnake/_context/text.py +179 -0
- gummy_snake-0.5.0/src/gummysnake/_context/three_d/__init__.py +7 -0
- gummy_snake-0.5.0/src/gummysnake/_context/three_d/_protocols.py +34 -0
- gummy_snake-0.5.0/src/gummysnake/_context/three_d/camera.py +139 -0
- gummy_snake-0.5.0/src/gummysnake/_context/three_d/context.py +125 -0
- gummy_snake-0.5.0/src/gummysnake/_context/three_d/material.py +134 -0
- gummy_snake-0.5.0/src/gummysnake/_context/three_d/model.py +127 -0
- gummy_snake-0.5.0/src/gummysnake/_context/three_d/primitives.py +123 -0
- gummy_snake-0.5.0/src/gummysnake/_context/transform.py +81 -0
- gummy_snake-0.5.0/src/gummysnake/_fast_draw.py +105 -0
- gummy_snake-0.5.0/src/gummysnake/api/__init__.py +1 -0
- gummy_snake-0.5.0/src/gummysnake/api/_environment_input.py +126 -0
- gummy_snake-0.5.0/src/gummysnake/api/_facades.py +107 -0
- gummy_snake-0.5.0/src/gummysnake/api/_lifecycle.py +120 -0
- gummy_snake-0.5.0/src/gummysnake/api/_media_text_pixels.py +204 -0
- gummy_snake-0.5.0/src/gummysnake/api/advanced.py +267 -0
- gummy_snake-0.5.0/src/gummysnake/api/current.py +38 -0
- gummy_snake-0.5.0/src/gummysnake/api/global_mode/__init__.py +391 -0
- gummy_snake-0.5.0/src/gummysnake/api/global_mode/canvas.py +144 -0
- gummy_snake-0.5.0/src/gummysnake/api/global_mode/contexts.py +127 -0
- gummy_snake-0.5.0/src/gummysnake/api/global_mode/exports.py +192 -0
- gummy_snake-0.5.0/src/gummysnake/api/global_mode/helpers.py +28 -0
- gummy_snake-0.5.0/src/gummysnake/api/global_mode/shapes.py +124 -0
- gummy_snake-0.5.0/src/gummysnake/assets/__init__.py +40 -0
- gummy_snake-0.5.0/src/gummysnake/assets/_paths.py +47 -0
- gummy_snake-0.5.0/src/gummysnake/assets/data.py +96 -0
- gummy_snake-0.5.0/src/gummysnake/assets/image/__init__.py +9 -0
- gummy_snake-0.5.0/src/gummysnake/assets/image/canvas.py +56 -0
- gummy_snake-0.5.0/src/gummysnake/assets/image/deferred.py +57 -0
- gummy_snake-0.5.0/src/gummysnake/assets/image/loading.py +32 -0
- gummy_snake-0.5.0/src/gummysnake/assets/image/model.py +276 -0
- gummy_snake-0.5.0/src/gummysnake/assets/image/ops.py +125 -0
- gummy_snake-0.5.0/src/gummysnake/assets/image/source.py +58 -0
- gummy_snake-0.5.0/src/gummysnake/assets/media/__init__.py +21 -0
- gummy_snake-0.5.0/src/gummysnake/assets/media/cv2.py +52 -0
- gummy_snake-0.5.0/src/gummysnake/assets/media/frame.py +50 -0
- gummy_snake-0.5.0/src/gummysnake/assets/media/streams.py +303 -0
- gummy_snake-0.5.0/src/gummysnake/assets/model.py +73 -0
- gummy_snake-0.5.0/src/gummysnake/assets/shader.py +47 -0
- gummy_snake-0.5.0/src/gummysnake/assets/sound.py +270 -0
- gummy_snake-0.5.0/src/gummysnake/assets/text.py +59 -0
- gummy_snake-0.5.0/src/gummysnake/backend/__init__.py +14 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/__init__.py +1 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/backend/__init__.py +1 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/backend/_protocols.py +37 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/backend/events.py +199 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/backend/pacing.py +90 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/backend/runtime.py +166 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/events.py +132 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/renderer/__init__.py +1 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/renderer/_protocols.py +35 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/renderer/core.py +255 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/renderer/images.py +117 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/renderer/pixels.py +165 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/renderer/primitives.py +243 -0
- gummy_snake-0.5.0/src/gummysnake/backend/_canvas/renderer/text.py +59 -0
- gummy_snake-0.5.0/src/gummysnake/backend/base.py +68 -0
- gummy_snake-0.5.0/src/gummysnake/backend/canvas.py +160 -0
- gummy_snake-0.5.0/src/gummysnake/backend/canvas_renderer.py +56 -0
- gummy_snake-0.5.0/src/gummysnake/backend/registry.py +23 -0
- gummy_snake-0.5.0/src/gummysnake/constants/__init__.py +205 -0
- gummy_snake-0.5.0/src/gummysnake/constants/aliases.py +189 -0
- gummy_snake-0.5.0/src/gummysnake/constants/drawing.py +99 -0
- gummy_snake-0.5.0/src/gummysnake/constants/input.py +59 -0
- gummy_snake-0.5.0/src/gummysnake/constants/renderer.py +48 -0
- gummy_snake-0.5.0/src/gummysnake/context.py +71 -0
- gummy_snake-0.5.0/src/gummysnake/core/__init__.py +0 -0
- gummy_snake-0.5.0/src/gummysnake/core/color.py +249 -0
- gummy_snake-0.5.0/src/gummysnake/core/data.py +26 -0
- gummy_snake-0.5.0/src/gummysnake/core/geometry.py +133 -0
- gummy_snake-0.5.0/src/gummysnake/core/math.py +165 -0
- gummy_snake-0.5.0/src/gummysnake/core/random.py +91 -0
- gummy_snake-0.5.0/src/gummysnake/core/state.py +111 -0
- gummy_snake-0.5.0/src/gummysnake/core/transform.py +214 -0
- gummy_snake-0.5.0/src/gummysnake/core/vector/__init__.py +7 -0
- gummy_snake-0.5.0/src/gummysnake/core/vector/basic.py +175 -0
- gummy_snake-0.5.0/src/gummysnake/core/vector/common.py +81 -0
- gummy_snake-0.5.0/src/gummysnake/core/vector/model.py +37 -0
- gummy_snake-0.5.0/src/gummysnake/core/vector/ops.py +272 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/__init__.py +0 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/prototype3d.py +205 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/renderer.py +173 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/renderer3d.py +613 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/__init__.py +41 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/export.py +92 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/math3d.py +65 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/primitives.py +118 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/projection.py +95 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/raster.py +205 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/rust_bridge.py +167 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/shading.py +197 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/transform.py +42 -0
- gummy_snake-0.5.0/src/gummysnake/drawing/software3d/types.py +31 -0
- gummy_snake-0.5.0/src/gummysnake/events/__init__.py +0 -0
- gummy_snake-0.5.0/src/gummysnake/events/input_state.py +147 -0
- gummy_snake-0.5.0/src/gummysnake/exceptions.py +33 -0
- gummy_snake-0.5.0/src/gummysnake/pixels/__init__.py +0 -0
- gummy_snake-0.5.0/src/gummysnake/plugins/__init__.py +31 -0
- gummy_snake-0.5.0/src/gummysnake/plugins/base.py +105 -0
- gummy_snake-0.5.0/src/gummysnake/plugins/registry.py +216 -0
- gummy_snake-0.5.0/src/gummysnake/rust/__init__.py +39 -0
- gummy_snake-0.5.0/src/gummysnake/rust/_accelerated.pyi +19 -0
- gummy_snake-0.5.0/src/gummysnake/rust/_canvas.pyi +311 -0
- gummy_snake-0.5.0/src/gummysnake/rust/acceleration.py +74 -0
- gummy_snake-0.5.0/src/gummysnake/rust/animated.py +102 -0
- gummy_snake-0.5.0/src/gummysnake/rust/benchmarks.py +123 -0
- gummy_snake-0.5.0/src/gummysnake/rust/blend.py +40 -0
- gummy_snake-0.5.0/src/gummysnake/rust/canvas.py +302 -0
- gummy_snake-0.5.0/src/gummysnake/rust/noise.py +115 -0
- gummy_snake-0.5.0/src/gummysnake/rust/runtime.py +137 -0
- gummy_snake-0.5.0/src/gummysnake/rust/validation.py +20 -0
- gummy_snake-0.5.0/src/gummysnake/sketch/__init__.py +7 -0
- gummy_snake-0.5.0/src/gummysnake/sketch/facade.py +292 -0
- gummy_snake-0.5.0/src/gummysnake/sketch/runtime.py +208 -0
- gummy_snake-0.5.0/src/gummysnake/testing/__init__.py +0 -0
- gummy_snake-0.5.0/src/gummysnake/testing/resources/__init__.py +1 -0
- gummy_snake-0.5.0/src/gummysnake/testing/resources/triangle.obj +5 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gummy-snake
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: Intended Audience :: Education
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Topic :: Artistic Software
|
|
10
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
11
|
+
Requires-Dist: opencv-python-headless>=4.13.0.92 ; extra == 'media'
|
|
12
|
+
Requires-Dist: numpy>=2.4.6 ; extra == 'numpy'
|
|
13
|
+
Provides-Extra: media
|
|
14
|
+
Provides-Extra: numpy
|
|
15
|
+
License-File: license.txt
|
|
16
|
+
Summary: A playful Python toolkit for creative coding and small games.
|
|
17
|
+
Keywords: creative-coding,games,graphics,python,sketches
|
|
18
|
+
License-Expression: LGPL-2.1-only
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
21
|
+
|
|
22
|
+
# Gummy Snake
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/gummy-snake/)
|
|
25
|
+
[](https://pypi.org/project/gummy-snake/)
|
|
26
|
+
[](license.txt)
|
|
27
|
+
[](https://pypi.org/project/gummy-snake/)
|
|
28
|
+
|
|
29
|
+
Gummy Snake is a playful Python toolkit for creative coding and small games. It
|
|
30
|
+
is for people who want to sketch with code: draw shapes, animate motion, react
|
|
31
|
+
to input, load sprites, play with pixels, and build visual toys without first
|
|
32
|
+
building a full app.
|
|
33
|
+
|
|
34
|
+
The public API is Python-first. Function names use `snake_case`, sketches are
|
|
35
|
+
ordinary Python files, and the renderer is powered by the packaged Rust canvas
|
|
36
|
+
runtime.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pip install gummy-snake
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Published wheels include the required Rust `gummy_canvas` canvas runtime. Source
|
|
45
|
+
or editable installs must build that PyO3 module; there is no Python renderer
|
|
46
|
+
fallback for canvas-owned behavior.
|
|
47
|
+
|
|
48
|
+
Install optional media helpers when you need camera, video, or sound-related
|
|
49
|
+
extras:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
pip install "gummy-snake[media]"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## First Sketch
|
|
56
|
+
|
|
57
|
+
Create a file named `circle_sketch.py`:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
import gummysnake as gs
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@gs.setup
|
|
64
|
+
def setup() -> None:
|
|
65
|
+
gs.create_canvas(400, 300)
|
|
66
|
+
gs.no_stroke()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@gs.draw
|
|
70
|
+
def draw() -> None:
|
|
71
|
+
gs.background(245)
|
|
72
|
+
gs.fill(255, 90, 90)
|
|
73
|
+
gs.circle(200, 150, 100)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
gs.run()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Run it:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
python circle_sketch.py
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For repeatable scripts, use a bounded headless render:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
gs.run(headless=True, max_frames=1)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Callbacks can also be `async def`, which is useful with async-compatible asset
|
|
92
|
+
helpers:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
image = None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@gs.preload
|
|
99
|
+
async def preload() -> None:
|
|
100
|
+
global image
|
|
101
|
+
image = await gs.load_image_async("sprite.png")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## What You Can Make
|
|
105
|
+
|
|
106
|
+
- 2D drawings with shapes, curves, color, transforms, and blend modes.
|
|
107
|
+
- Animated sketches using the familiar `setup()` and `draw()` lifecycle.
|
|
108
|
+
- Decorator-based sketches, async-compatible callbacks, and object-oriented
|
|
109
|
+
`Sketch` subclasses.
|
|
110
|
+
- Image and pixel experiments, including canvas export.
|
|
111
|
+
- Text, font measurement, and accessibility descriptions.
|
|
112
|
+
- Interactive sketches with mouse, keyboard, and touch state when native window
|
|
113
|
+
support is available.
|
|
114
|
+
- Software 3D sketches with primitives, lights, materials, models, textures,
|
|
115
|
+
and shader objects on the current Rust-backed software 3D path.
|
|
116
|
+
- Small games and visual toys using the examples as starting points.
|
|
117
|
+
|
|
118
|
+
Loaded images, models/meshes, and sounds keep Rust-managed asset handles behind
|
|
119
|
+
friendly Python wrappers. This is intentional for performance: bulk asset bytes,
|
|
120
|
+
geometry arrays, parsing, export, and metadata extraction should stay in the
|
|
121
|
+
Rust canvas runtime so sketches avoid repeated Python object materialization and
|
|
122
|
+
per-element loops. Normal `load_image(); image(...)` sprite drawing can stay on
|
|
123
|
+
the fast renderer path, model projection/export can use Rust-owned geometry
|
|
124
|
+
without first creating Python `Vec3` objects, and loaded sounds keep their bytes
|
|
125
|
+
and duration metadata in `CanvasSound` until user code asks for Python bytes.
|
|
126
|
+
Image-local resize, mask, filter, crop/copy, and alpha compositing delegate
|
|
127
|
+
bulk byte work to the Rust canvas runtime while keeping the Python `Image`
|
|
128
|
+
API and version semantics.
|
|
129
|
+
For pixel effects, `load_pixels()` returns a list-based pixel buffer and
|
|
130
|
+
`load_pixel_bytes()` provides a bytes readback path; `update_pixels()` accepts
|
|
131
|
+
lists and buffer-like inputs such as `bytes`, `bytearray`, and `memoryview`.
|
|
132
|
+
Small canvas `get()` and `set()` region operations use Rust region calls instead
|
|
133
|
+
of reconstructing the full canvas as a Python image.
|
|
134
|
+
For dense drawing loops, `gs.fast()` returns a frame-local facade that keeps
|
|
135
|
+
public style/transform state while reducing global-mode dispatch overhead.
|
|
136
|
+
Opt-in `enable_performance_diagnostics()` counters can identify readback, pixel
|
|
137
|
+
conversion, upload, texture cache, and CPU compositing fallback paths.
|
|
138
|
+
|
|
139
|
+
## Learn More
|
|
140
|
+
|
|
141
|
+
- [Getting started](docs/getting_started/index.md)
|
|
142
|
+
- [Examples](examples/README.md)
|
|
143
|
+
- [API reference](docs/reference/index.md)
|
|
144
|
+
- [Contributor docs](docs/contribute/index.md)
|
|
145
|
+
|
|
146
|
+
## For Contributors
|
|
147
|
+
|
|
148
|
+
This repository uses `uv` for Python commands:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
uv sync --dev
|
|
152
|
+
uv run ruff check .
|
|
153
|
+
uv run mypy src
|
|
154
|
+
uv run pytest
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The canvas runtime is a required PyO3 module for development/source installs:
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
uvx maturin develop --manifest-path crates/gummy_canvas/Cargo.toml --features extension-module
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The refactored Python package is split by responsibility: public API modules in
|
|
164
|
+
`src/gummysnake/api/`, `SketchContext` mixins in `src/gummysnake/_context/`,
|
|
165
|
+
lifecycle code in `src/gummysnake/sketch/`, enum-backed constants in
|
|
166
|
+
`src/gummysnake/constants/`, and thin canvas backend/renderer facades over the
|
|
167
|
+
implementation modules in `src/gummysnake/backend/_canvas/`.
|
|
168
|
+
|
|
169
|
+
The contributor documentation explains the architecture, lifecycle, testing
|
|
170
|
+
workflow, and release shape in more detail:
|
|
171
|
+
|
|
172
|
+
- [Contributor guide](docs/contribute/index.md)
|
|
173
|
+
- [Architecture](docs/contribute/architecture.md)
|
|
174
|
+
- [Backend and renderer boundaries](docs/contribute/backend_renderer.md)
|
|
175
|
+
- [Runtime model](docs/contribute/runtime.md)
|
|
176
|
+
- [Runtime diagnostics](docs/contribute/runtime_diagnostics.md)
|
|
177
|
+
- [Build capabilities](docs/contribute/build_capabilities.md)
|
|
178
|
+
- [API performance policy](docs/contribute/api_performance_policy.md)
|
|
179
|
+
- [Testing and CI](docs/contribute/testing.md)
|
|
180
|
+
|
|
181
|
+
Performance benchmarks are opt-in:
|
|
182
|
+
|
|
183
|
+
```sh
|
|
184
|
+
uv run pytest tests/benchmark/test_canvas_backend_perf.py --run-benchmarks
|
|
185
|
+
uv run pytest tests/benchmark/test_api_overhead_perf.py --run-benchmarks
|
|
186
|
+
uv run pytest tests/benchmark/test_image_pipeline_perf.py --run-benchmarks
|
|
187
|
+
uv run pytest tests/benchmark/test_model_export_perf.py --run-benchmarks
|
|
188
|
+
uv run pytest tests/benchmark/test_webgl_3d_perf.py --run-benchmarks
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Canvas benchmark scenarios are expected to average at least 120 FPS. Failures
|
|
192
|
+
below that floor are intentional optimization signals. Model export benchmarks
|
|
193
|
+
use a memory budget for streaming OBJ/STL output. Machine-specific baseline
|
|
194
|
+
snapshots live in `tests/benchmark/baselines/`.
|
|
195
|
+
|
|
196
|
+
Long-running resource lifecycle checks are also opt-in:
|
|
197
|
+
|
|
198
|
+
```sh
|
|
199
|
+
uv run pytest tests/stress --run-stress -q -s
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Compatibility
|
|
203
|
+
|
|
204
|
+
Gummy Snake keeps the sketch lifecycle familiar, but it is not a browser port.
|
|
205
|
+
It does not include DOM helpers, browser-only APIs, JavaScript aliases, or a
|
|
206
|
+
Pillow/Pyglet/Python renderer fallback. Unsupported features raise explicit
|
|
207
|
+
package errors so sketches fail clearly.
|
|
208
|
+
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Gummy Snake
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/gummy-snake/)
|
|
4
|
+
[](https://pypi.org/project/gummy-snake/)
|
|
5
|
+
[](license.txt)
|
|
6
|
+
[](https://pypi.org/project/gummy-snake/)
|
|
7
|
+
|
|
8
|
+
Gummy Snake is a playful Python toolkit for creative coding and small games. It
|
|
9
|
+
is for people who want to sketch with code: draw shapes, animate motion, react
|
|
10
|
+
to input, load sprites, play with pixels, and build visual toys without first
|
|
11
|
+
building a full app.
|
|
12
|
+
|
|
13
|
+
The public API is Python-first. Function names use `snake_case`, sketches are
|
|
14
|
+
ordinary Python files, and the renderer is powered by the packaged Rust canvas
|
|
15
|
+
runtime.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pip install gummy-snake
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Published wheels include the required Rust `gummy_canvas` canvas runtime. Source
|
|
24
|
+
or editable installs must build that PyO3 module; there is no Python renderer
|
|
25
|
+
fallback for canvas-owned behavior.
|
|
26
|
+
|
|
27
|
+
Install optional media helpers when you need camera, video, or sound-related
|
|
28
|
+
extras:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pip install "gummy-snake[media]"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## First Sketch
|
|
35
|
+
|
|
36
|
+
Create a file named `circle_sketch.py`:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import gummysnake as gs
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@gs.setup
|
|
43
|
+
def setup() -> None:
|
|
44
|
+
gs.create_canvas(400, 300)
|
|
45
|
+
gs.no_stroke()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@gs.draw
|
|
49
|
+
def draw() -> None:
|
|
50
|
+
gs.background(245)
|
|
51
|
+
gs.fill(255, 90, 90)
|
|
52
|
+
gs.circle(200, 150, 100)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
gs.run()
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Run it:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
python circle_sketch.py
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For repeatable scripts, use a bounded headless render:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
gs.run(headless=True, max_frames=1)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Callbacks can also be `async def`, which is useful with async-compatible asset
|
|
71
|
+
helpers:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
image = None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@gs.preload
|
|
78
|
+
async def preload() -> None:
|
|
79
|
+
global image
|
|
80
|
+
image = await gs.load_image_async("sprite.png")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## What You Can Make
|
|
84
|
+
|
|
85
|
+
- 2D drawings with shapes, curves, color, transforms, and blend modes.
|
|
86
|
+
- Animated sketches using the familiar `setup()` and `draw()` lifecycle.
|
|
87
|
+
- Decorator-based sketches, async-compatible callbacks, and object-oriented
|
|
88
|
+
`Sketch` subclasses.
|
|
89
|
+
- Image and pixel experiments, including canvas export.
|
|
90
|
+
- Text, font measurement, and accessibility descriptions.
|
|
91
|
+
- Interactive sketches with mouse, keyboard, and touch state when native window
|
|
92
|
+
support is available.
|
|
93
|
+
- Software 3D sketches with primitives, lights, materials, models, textures,
|
|
94
|
+
and shader objects on the current Rust-backed software 3D path.
|
|
95
|
+
- Small games and visual toys using the examples as starting points.
|
|
96
|
+
|
|
97
|
+
Loaded images, models/meshes, and sounds keep Rust-managed asset handles behind
|
|
98
|
+
friendly Python wrappers. This is intentional for performance: bulk asset bytes,
|
|
99
|
+
geometry arrays, parsing, export, and metadata extraction should stay in the
|
|
100
|
+
Rust canvas runtime so sketches avoid repeated Python object materialization and
|
|
101
|
+
per-element loops. Normal `load_image(); image(...)` sprite drawing can stay on
|
|
102
|
+
the fast renderer path, model projection/export can use Rust-owned geometry
|
|
103
|
+
without first creating Python `Vec3` objects, and loaded sounds keep their bytes
|
|
104
|
+
and duration metadata in `CanvasSound` until user code asks for Python bytes.
|
|
105
|
+
Image-local resize, mask, filter, crop/copy, and alpha compositing delegate
|
|
106
|
+
bulk byte work to the Rust canvas runtime while keeping the Python `Image`
|
|
107
|
+
API and version semantics.
|
|
108
|
+
For pixel effects, `load_pixels()` returns a list-based pixel buffer and
|
|
109
|
+
`load_pixel_bytes()` provides a bytes readback path; `update_pixels()` accepts
|
|
110
|
+
lists and buffer-like inputs such as `bytes`, `bytearray`, and `memoryview`.
|
|
111
|
+
Small canvas `get()` and `set()` region operations use Rust region calls instead
|
|
112
|
+
of reconstructing the full canvas as a Python image.
|
|
113
|
+
For dense drawing loops, `gs.fast()` returns a frame-local facade that keeps
|
|
114
|
+
public style/transform state while reducing global-mode dispatch overhead.
|
|
115
|
+
Opt-in `enable_performance_diagnostics()` counters can identify readback, pixel
|
|
116
|
+
conversion, upload, texture cache, and CPU compositing fallback paths.
|
|
117
|
+
|
|
118
|
+
## Learn More
|
|
119
|
+
|
|
120
|
+
- [Getting started](docs/getting_started/index.md)
|
|
121
|
+
- [Examples](examples/README.md)
|
|
122
|
+
- [API reference](docs/reference/index.md)
|
|
123
|
+
- [Contributor docs](docs/contribute/index.md)
|
|
124
|
+
|
|
125
|
+
## For Contributors
|
|
126
|
+
|
|
127
|
+
This repository uses `uv` for Python commands:
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
uv sync --dev
|
|
131
|
+
uv run ruff check .
|
|
132
|
+
uv run mypy src
|
|
133
|
+
uv run pytest
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The canvas runtime is a required PyO3 module for development/source installs:
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
uvx maturin develop --manifest-path crates/gummy_canvas/Cargo.toml --features extension-module
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The refactored Python package is split by responsibility: public API modules in
|
|
143
|
+
`src/gummysnake/api/`, `SketchContext` mixins in `src/gummysnake/_context/`,
|
|
144
|
+
lifecycle code in `src/gummysnake/sketch/`, enum-backed constants in
|
|
145
|
+
`src/gummysnake/constants/`, and thin canvas backend/renderer facades over the
|
|
146
|
+
implementation modules in `src/gummysnake/backend/_canvas/`.
|
|
147
|
+
|
|
148
|
+
The contributor documentation explains the architecture, lifecycle, testing
|
|
149
|
+
workflow, and release shape in more detail:
|
|
150
|
+
|
|
151
|
+
- [Contributor guide](docs/contribute/index.md)
|
|
152
|
+
- [Architecture](docs/contribute/architecture.md)
|
|
153
|
+
- [Backend and renderer boundaries](docs/contribute/backend_renderer.md)
|
|
154
|
+
- [Runtime model](docs/contribute/runtime.md)
|
|
155
|
+
- [Runtime diagnostics](docs/contribute/runtime_diagnostics.md)
|
|
156
|
+
- [Build capabilities](docs/contribute/build_capabilities.md)
|
|
157
|
+
- [API performance policy](docs/contribute/api_performance_policy.md)
|
|
158
|
+
- [Testing and CI](docs/contribute/testing.md)
|
|
159
|
+
|
|
160
|
+
Performance benchmarks are opt-in:
|
|
161
|
+
|
|
162
|
+
```sh
|
|
163
|
+
uv run pytest tests/benchmark/test_canvas_backend_perf.py --run-benchmarks
|
|
164
|
+
uv run pytest tests/benchmark/test_api_overhead_perf.py --run-benchmarks
|
|
165
|
+
uv run pytest tests/benchmark/test_image_pipeline_perf.py --run-benchmarks
|
|
166
|
+
uv run pytest tests/benchmark/test_model_export_perf.py --run-benchmarks
|
|
167
|
+
uv run pytest tests/benchmark/test_webgl_3d_perf.py --run-benchmarks
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Canvas benchmark scenarios are expected to average at least 120 FPS. Failures
|
|
171
|
+
below that floor are intentional optimization signals. Model export benchmarks
|
|
172
|
+
use a memory budget for streaming OBJ/STL output. Machine-specific baseline
|
|
173
|
+
snapshots live in `tests/benchmark/baselines/`.
|
|
174
|
+
|
|
175
|
+
Long-running resource lifecycle checks are also opt-in:
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
uv run pytest tests/stress --run-stress -q -s
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Compatibility
|
|
182
|
+
|
|
183
|
+
Gummy Snake keeps the sketch lifecycle familiar, but it is not a browser port.
|
|
184
|
+
It does not include DOM helpers, browser-only APIs, JavaScript aliases, or a
|
|
185
|
+
Pillow/Pyglet/Python renderer fallback. Unsupported features raise explicit
|
|
186
|
+
package errors so sketches fail clearly.
|