You've already forked flecs_tests
Compare commits
10 Commits
81616f8a5d
...
rework
| Author | SHA1 | Date | |
|---|---|---|---|
| af0a39166c | |||
| 8ea6a0bf3e | |||
| dc708de354 | |||
| beea8a0281 | |||
| 936043340c | |||
| 9789e449c3 | |||
| 7e3da1c424 | |||
| c4d657043c | |||
| e71641c094 | |||
| 9ce6e4accd |
11
CLAUDE.md
11
CLAUDE.md
@@ -9,6 +9,7 @@ A browser-based world map creation tool (like Wonderdraft/Inkarnate). C99 compil
|
||||
- **UI:** Dear ImGui via cimgui — `lib/imgui/`
|
||||
- **Math:** cglm (types are C arrays: `vec2` = `float[2]`, `mat4` = `float[4][4]` column-major) — `lib/cglm/`
|
||||
- **Shaders:** WGSL in `src/shaders/`, compiled to C headers via `xxd -i` into `src/generated/`
|
||||
- **Shapes:** Line-strip based vector shapes (circle, star) with procedural vertex generation
|
||||
|
||||
### Build
|
||||
- `make` (release) / `make debug` — outputs `app.html`
|
||||
@@ -16,9 +17,13 @@ A browser-based world map creation tool (like Wonderdraft/Inkarnate). C99 compil
|
||||
- Include paths: `lib/sokol`, `lib/imgui`, `lib/imgui/imgui`, `lib/util`, `lib/cglm/include`
|
||||
|
||||
### Key files
|
||||
- `src/main.c` — entry point, sokol init, render loop, input (zoom/pan/drag)
|
||||
- `src/api.h` — central include hub, backend defines
|
||||
- `src/sprite.h` — sprite batching, texture manager, file import stubs
|
||||
- `src/main.c` — entry point, sokol init, render loop, all input handling, overlay geometry, UI panels, and debug stats
|
||||
- `src/api.h` — central include hub, backend defines, ALLOC/FREE macros (wired to smemtrack)
|
||||
- `src/camera.h` — viewport state (zoom/pan), MVP matrix computation, screen↔world coordinate transforms
|
||||
- `src/render.h` — shape pipeline init/shutdown, per-shape draw calls (shader uniform binding)
|
||||
- `src/shape.h` — shape geometry types, procedural generation (circle/star), transform building, hit testing, buffer management
|
||||
- `src/spatial.h` — spatial hash grid for accelerating hit tests and rect-selection queries
|
||||
- `src/history.h` — undo/redo stack with property-level tracking (position/scale/rotation/color), edit session capture, batch operations
|
||||
- `src/util.h` — `vector_t` (dynamic array) and `mem_pool_t` (free-list pool), both stripe-based
|
||||
- `src/rand.h` — xorshift32 PRNG
|
||||
|
||||
|
||||
43
README.md
43
README.md
@@ -1,29 +1,6 @@
|
||||
# Cartograph
|
||||
|
||||
A browser-based world map creation tool inspired by Wonderdraft and Inkarnate. Uses shape-based terrain generation with procedural detail.
|
||||
|
||||
## Features (planned)
|
||||
|
||||
- **Shapes** — the fundamental building block. Each shape has:
|
||||
- **Height** — additive (raise terrain) or subtractive (lower terrain)
|
||||
- **Biome** — determines the sampled texture applied to the shape
|
||||
- **Intensity** — blending weight of the biome texture
|
||||
- **Roughness** — edge noise amount (voronoi-like jagged edges at maximum)
|
||||
- **Shape editing** — select, move, rotate, scale individual shapes
|
||||
- **Groups** — combine shapes into groups for batch operations
|
||||
- **Shake landmass** — procedurally decompose a shape into a more complex set of shapes
|
||||
- **Viewport** — zoom and pan across the map canvas
|
||||
|
||||
## Tech stack
|
||||
|
||||
| Layer | Library |
|
||||
|---|---|
|
||||
| Language | C (C99) |
|
||||
| Compiler | [Emscripten](https://emscripten.org/) (emcc) → WebAssembly |
|
||||
| Graphics | [Sokol](https://github.com/floooh/sokol) with WebGPU backend |
|
||||
| UI | [Dear ImGui](https://github.com/ocornut/imgui) via [cimgui](https://github.com/cimgui/cimgui) |
|
||||
| Math | [cglm](https://github.com/recp/cglm) |
|
||||
| Shaders | WGSL (compiled to C headers via `xxd`) |
|
||||
A browser-based world map creation tool inspired by Wonderdraft and Inkarnate. Uses a hierarchical tile-based SDF rendering.
|
||||
|
||||
## Build
|
||||
|
||||
@@ -40,24 +17,6 @@ make debug
|
||||
|
||||
Output is `app.html`, served by Emscripten's built-in web server or any static server.
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
src/
|
||||
main.c Entry point, sokol init, render loop, input handling
|
||||
api.h Central include — all library headers and project-wide defines
|
||||
sprite.h Sprite batching, texture management, file import
|
||||
util.h Vector (dynamic array) and memory pool data structures
|
||||
rand.h Xorshift32 PRNG utilities
|
||||
shaders/ WGSL shader sources
|
||||
generated/ xxd-generated C headers from shaders
|
||||
lib/
|
||||
sokol/ Sokol single-file headers (gfx, app, glue, log)
|
||||
imgui/ Dear ImGui + cimgui
|
||||
cglm/ C linear math library
|
||||
util/ Sokol utility headers (memtrack, imgui integration)
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
@@ -5,12 +5,12 @@ LIB_DIR="lib"
|
||||
|
||||
echo "=== Fetching library dependencies ==="
|
||||
|
||||
# 1. Sokol (single-file headers)
|
||||
mkdir -p "$LIB_DIR/sokol"
|
||||
mkdir -p "$LIB_DIR/imgui"
|
||||
mkdir -p "$LIB_DIR/util"
|
||||
mkdir -p "$LIB_DIR/cglm"
|
||||
|
||||
# 1. Sokol (single-file headers)
|
||||
if [ ! -f "$LIB_DIR/sokol/sokol_gfx.h" ]; then
|
||||
echo " > Fetching sokol (pinned to emdawnwebgpu-compatible version)..."
|
||||
git clone --depth 500 https://github.com/floooh/sokol.git "$LIB_DIR/sokol_tmp"
|
||||
@@ -59,4 +59,14 @@ else
|
||||
echo " > cglm already present"
|
||||
fi
|
||||
|
||||
# 5. stb_ds.h
|
||||
if [ ! -f "$LIB_DIR/util/stb_ds.h" ]; then
|
||||
echo " > Fetching STB..."
|
||||
git clone --depth 1 https://github.com/nothings/stb.git "$LIB_DIR/stb_tmp"
|
||||
cp -r "$LIB_DIR/stb_tmp/stb_ds.h" "$LIB_DIR/util/stb_ds.h"
|
||||
rm -rf "$LIB_DIR/stb_tmp"
|
||||
else
|
||||
echo " > stb_ds.h already present"
|
||||
fi
|
||||
|
||||
echo "=== Done ==="
|
||||
|
||||
5
makefile
5
makefile
@@ -31,6 +31,7 @@ EMCC_FLAGS = --use-port=emdawnwebgpu \
|
||||
-sALLOW_MEMORY_GROWTH \
|
||||
-msimd128 \
|
||||
-sFILESYSTEM=0 \
|
||||
-sMALLOC=emmalloc \
|
||||
-flto
|
||||
|
||||
# Shell template
|
||||
@@ -45,6 +46,7 @@ $(TARGET): $(SHADER_HEADERS) $(C_SOURCES) $(IMGUI_SOURCES) $(CGLM_SOURCES) $(SHE
|
||||
-o $(TARGET) \
|
||||
$(EMCC_FLAGS) \
|
||||
-O3 \
|
||||
--closure 1 \
|
||||
-I$(LIB_DIR)/sokol \
|
||||
-I$(LIB_DIR)/imgui \
|
||||
-I$(LIB_DIR)/imgui/imgui \
|
||||
@@ -65,7 +67,8 @@ debug: $(FETCH) $(SHADER_HEADERS) $(C_SOURCES) $(IMGUI_SOURCES) $(CGLM_SOURCES)
|
||||
$(CC) $(C_SOURCES) $(IMGUI_SOURCES) $(CGLM_SOURCES) \
|
||||
-o $(TARGET) \
|
||||
$(EMCC_FLAGS) \
|
||||
-g -gsource-map=inline \
|
||||
-g3 --profiling-funcs -gsource-map \
|
||||
-sASSERTIONS \
|
||||
-I$(LIB_DIR)/sokol \
|
||||
-I$(LIB_DIR)/imgui \
|
||||
-I$(LIB_DIR)/imgui/imgui \
|
||||
|
||||
80
src/api.h
80
src/api.h
@@ -1,41 +1,59 @@
|
||||
#ifndef API_DEFINITION
|
||||
#define API_DEFINITION
|
||||
|
||||
#define CIMGUI_DEFINE_ENUMS_AND_STRUCTS
|
||||
|
||||
#define SOKOL_IMPL
|
||||
#define SOKOL_WGPU
|
||||
#define SOKOL_IMGUI_IMPL
|
||||
#define SOKOL_VALIDATE_NON_FATAL
|
||||
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_app.h"
|
||||
#include "sokol_glue.h"
|
||||
#include "sokol_log.h"
|
||||
#include "cimgui.h"
|
||||
#include "sokol_imgui.h"
|
||||
#include "sokol_memtrack.h"
|
||||
#include "sokol_shape.h"
|
||||
|
||||
#define ALLOC(arg) smemtrack_alloc(arg, NULL)
|
||||
#define FREE(arg) smemtrack_free(arg, NULL)
|
||||
|
||||
#include "cglm/cglm.h"
|
||||
|
||||
#include "rand.h"
|
||||
|
||||
#include "generated/sprite.h"
|
||||
#include "generated/shape.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "shape.h"
|
||||
#include "spatial.h"
|
||||
#include "history.h"
|
||||
|
||||
#include <emscripten.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <emscripten/emmalloc.h>
|
||||
|
||||
#define CIMGUI_DEFINE_ENUMS_AND_STRUCTS
|
||||
|
||||
static void log_fn(const char* tag, uint32_t log_level, uint32_t log_item_id, const char* message_or_null, uint32_t line_nr, const char* filename_or_null, void* user_data)
|
||||
{
|
||||
fprintf(stderr, "[%s - %s]: (%d) %s \tat %s:%d\r\n", tag, log_level == 0 ? "FATAL" : log_level == 1 ? "ERROR" : log_level == 2 ? "WARNING" : "INFO", log_item_id, message_or_null, filename_or_null, line_nr);
|
||||
}
|
||||
|
||||
#define SOKOL_ASSERT(x) ((void)((x) || (log_fn("ASSERT", 1, 1, "Assertion failed", __LINE__, __FILE__, NULL),0)))
|
||||
|
||||
#define SOKOL_IMPL
|
||||
#define SOKOL_WGPU
|
||||
#define SOKOL_IMGUI_IMPL
|
||||
|
||||
#define STB_DS_IMPLEMENTATION
|
||||
#define STBDS_NO_SHORT_NAMES
|
||||
|
||||
#define STBDS_REALLOC(context,ptr,size) emmalloc_realloc(ptr, size)
|
||||
#define STBDS_FREE(context,ptr) emmalloc_free(ptr)
|
||||
|
||||
#define COMPUTE_VIEWIDX_segments 0
|
||||
#define COMPUTE_VIEWIDX_shapes 1
|
||||
#define COMPUTE_VIEWIDX_circles 2
|
||||
#define COMPUTE_VIEWIDX_tiles 3
|
||||
#define COMPUTE_VIEWIDX_indices 4
|
||||
#define COMPUTE_VIEWIDX_SDF 5
|
||||
|
||||
#define DISPLAY_VIEWIDX_SDF 0
|
||||
#define DISPLAY_VIEWIDX_Sampler 1
|
||||
|
||||
static float clampf(float x, float a, float b)
|
||||
{
|
||||
return x < a ? a : (x > b ? b : x);
|
||||
}
|
||||
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_app.h"
|
||||
#include "sokol_glue.h"
|
||||
#include "cimgui.h"
|
||||
#include "sokol_imgui.h"
|
||||
#include "stb_ds.h"
|
||||
|
||||
#include "shape.h"
|
||||
//#include "cache.h"
|
||||
#include "pool.h"
|
||||
#include "generated/compute.h"
|
||||
#include "generated/display.h"
|
||||
|
||||
#endif
|
||||
107
src/cache.h
Normal file
107
src/cache.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "api.h"
|
||||
|
||||
tile_slot_t* cache_evict(scene_t* s)
|
||||
{
|
||||
tile_slot_t* best = NULL;
|
||||
uint64_t oldest = UINT64_MAX;
|
||||
|
||||
for(uint32_t i = 0; i < TILE_LAYERS; i++)
|
||||
{
|
||||
tile_slot_t* slot = &s->cache.slots[i];
|
||||
if(slot->key.lod == UINT32_MAX) continue; // LOD == UINT32_MAX means the slot is free.
|
||||
|
||||
//Found a better candidate
|
||||
if(slot->last_used < oldest)
|
||||
{
|
||||
oldest = slot->last_used;
|
||||
best = slot;
|
||||
}
|
||||
}
|
||||
|
||||
if(best == NULL)
|
||||
return best;
|
||||
|
||||
stbds_hmdel(s->cache.map, best->key);
|
||||
|
||||
s->cache.free_layers[s->cache.free_count] = best->layer;
|
||||
s->cache.free_count++;
|
||||
s->cache.slots[best->layer].key.lod = UINT32_MAX; //Mark the slot as free for the evict scan using lod == UINT32_MAX
|
||||
|
||||
return best;
|
||||
}
|
||||
uint32_t cache_allocate(scene_t* s)
|
||||
{
|
||||
assert(s->cache.free_count > 0);
|
||||
s->cache.free_count--;
|
||||
uint32_t layer = s->cache.free_layers[s->cache.free_count];
|
||||
|
||||
return layer;
|
||||
}
|
||||
tile_slot_t* cache_search(scene_t* s, tile_key_t* key, uint64_t frame_count)
|
||||
{
|
||||
uint32_t index = stbds_hmgeti(s->cache.map, *key);
|
||||
|
||||
if(index >= 0)
|
||||
{
|
||||
uint32_t layer = s->cache.map[index].value;
|
||||
tile_slot_t* slot = &s->cache.slots[layer];
|
||||
slot->last_used = frame_count;
|
||||
return slot;
|
||||
}
|
||||
|
||||
// Evict the least recently used (LRU) slot
|
||||
if(stbds_hmlen(s->cache.map) >= TILE_LAYERS)
|
||||
{
|
||||
tile_slot_t* evict = cache_evict(s);
|
||||
}
|
||||
|
||||
// Allocate a free layer
|
||||
uint32_t layer = cache_allocate(s);
|
||||
tile_slot_t* slot = &s->cache.slots[layer];
|
||||
slot->key.lod = key->lod; slot->key.tx = key->tx; slot->key.ty = key->ty;
|
||||
slot->layer = layer;
|
||||
slot->state = TILE_STATE_DIRTY;
|
||||
slot->last_used = frame_count;
|
||||
|
||||
stbds_hmput(s->cache.map, *key, layer);
|
||||
return slot;
|
||||
}
|
||||
// Works in 3 steps, first we select every required tiles and store the mising one from the cache
|
||||
// Then we evict the LRU cache until we have enough space for the missing tiles
|
||||
// Finally we allocate the missing tiles
|
||||
static int cache_query(scene_t* s, uint32_t lod, box_t* box, tile_key_t** buffer)
|
||||
{
|
||||
uint64_t frame = sapp_frame_count();
|
||||
tile_key_t tile_key = { lod, 0, 0 };
|
||||
|
||||
for(uint32_t ty = box->min_y; ty < box->max_y; ty++)
|
||||
{
|
||||
tile_key.ty = ty;
|
||||
for(uint32_t tx = box->min_x; tx < box->max_x; tx++)
|
||||
{
|
||||
tile_key.tx = tx;
|
||||
stbds_hmget(s->cache.map, tile_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
static int cache_cull(scene_t* s, uint32_t tile_count)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
for(uint32_t i = 0; i < tile_count; i++)
|
||||
{
|
||||
tile_slot_t slot = s->cache.slots[i];
|
||||
tile_task_t* tile = &s->cache.tiles[i];
|
||||
tile->bounds.min_x = slot.key.tx * s->LODs[slot.key.lod].texel_size;
|
||||
tile->bounds.min_y = slot.key.ty * s->LODs[slot.key.lod].texel_size;
|
||||
tile->bounds.max_x = (slot.key.tx + 1) * s->LODs[slot.key.lod].texel_size;
|
||||
tile->bounds.max_y = (slot.key.ty + 1) * s->LODs[slot.key.lod].texel_size;
|
||||
tile->layer = slot.layer;
|
||||
|
||||
uint32_t start = count;
|
||||
for(uint32_t j = 0; j < s->num_shapes; j++)
|
||||
{
|
||||
if(BOX_INTERSECTS(tile->bounds, s->shapes[j].aabb)) s->cache.indices[count++] = j;
|
||||
}
|
||||
tile->offset = start; tile->count = count - start;
|
||||
}
|
||||
}
|
||||
686
src/generated/compute.h
Normal file
686
src/generated/compute.h
Normal file
@@ -0,0 +1,686 @@
|
||||
unsigned char src_shaders_compute_wgsl[] = {
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x53, 0x65, 0x67, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x30,
|
||||
0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x70, 0x31, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x32, 0x3a, 0x20, 0x76, 0x65,
|
||||
0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x33,
|
||||
0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a, 0x7d, 0x0d,
|
||||
0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x53, 0x68, 0x61, 0x70,
|
||||
0x65, 0x4d, 0x65, 0x74, 0x61, 0x20, 0x7b, 0x20, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x65, 0x67, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x2c, 0x20, 0x2f, 0x2f,
|
||||
0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x62,
|
||||
0x75, 0x66, 0x66, 0x65, 0x72, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73,
|
||||
0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x3a, 0x20, 0x75, 0x33, 0x32, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x62, 0x62, 0x6f, 0x78, 0x5f, 0x6d, 0x69, 0x6e, 0x3a, 0x20, 0x76, 0x65,
|
||||
0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x62,
|
||||
0x6f, 0x78, 0x5f, 0x6d, 0x61, 0x78, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32,
|
||||
0x66, 0x2c, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63,
|
||||
0x74, 0x20, 0x43, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3a, 0x20,
|
||||
0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x66, 0x33, 0x32, 0x2c,
|
||||
0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20,
|
||||
0x54, 0x69, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x3a, 0x20, 0x76,
|
||||
0x65, 0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77,
|
||||
0x6f, 0x72, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x3a, 0x20, 0x76, 0x65,
|
||||
0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x66,
|
||||
0x66, 0x73, 0x65, 0x74, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x2c, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x5f, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x2c, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x20, 0x75,
|
||||
0x33, 0x32, 0x2c, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x40,
|
||||
0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x31, 0x29, 0x20, 0x40, 0x62, 0x69,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x29, 0x20, 0x76, 0x61, 0x72,
|
||||
0x3c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x3e, 0x20, 0x73, 0x65,
|
||||
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61,
|
||||
0x79, 0x3c, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x3e, 0x3b, 0x0d,
|
||||
0x0a, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x31, 0x29, 0x20, 0x40,
|
||||
0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x31, 0x29, 0x20, 0x76,
|
||||
0x61, 0x72, 0x3c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x3e, 0x20,
|
||||
0x73, 0x68, 0x61, 0x70, 0x65, 0x73, 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61,
|
||||
0x79, 0x3c, 0x53, 0x68, 0x61, 0x70, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x3e,
|
||||
0x3b, 0x0d, 0x0a, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x31, 0x29,
|
||||
0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x32, 0x29,
|
||||
0x20, 0x76, 0x61, 0x72, 0x3c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
|
||||
0x3e, 0x20, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x73, 0x3a, 0x20, 0x61,
|
||||
0x72, 0x72, 0x61, 0x79, 0x3c, 0x43, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x3e,
|
||||
0x3b, 0x0d, 0x0a, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x31, 0x29,
|
||||
0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x33, 0x29,
|
||||
0x20, 0x76, 0x61, 0x72, 0x3c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
|
||||
0x3e, 0x20, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x3a, 0x20, 0x61, 0x72, 0x72,
|
||||
0x61, 0x79, 0x3c, 0x54, 0x69, 0x6c, 0x65, 0x3e, 0x3b, 0x0d, 0x0a, 0x40,
|
||||
0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x31, 0x29, 0x20, 0x40, 0x62, 0x69,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x34, 0x29, 0x20, 0x76, 0x61, 0x72,
|
||||
0x3c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x3e, 0x20, 0x69, 0x6e,
|
||||
0x64, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79,
|
||||
0x3c, 0x75, 0x33, 0x32, 0x3e, 0x3b, 0x0d, 0x0a, 0x40, 0x67, 0x72, 0x6f,
|
||||
0x75, 0x70, 0x28, 0x31, 0x29, 0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69,
|
||||
0x6e, 0x67, 0x28, 0x35, 0x29, 0x20, 0x76, 0x61, 0x72, 0x20, 0x73, 0x64,
|
||||
0x66, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x3a, 0x20, 0x74, 0x65,
|
||||
0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
|
||||
0x65, 0x5f, 0x32, 0x64, 0x3c, 0x72, 0x31, 0x36, 0x66, 0x6c, 0x6f, 0x61,
|
||||
0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x3e, 0x3b, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x20, 0x54,
|
||||
0x49, 0x4c, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x3a, 0x20, 0x75, 0x33,
|
||||
0x32, 0x20, 0x3d, 0x20, 0x32, 0x35, 0x36, 0x75, 0x3b, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x20, 0x43, 0x75, 0x62, 0x69, 0x63, 0x20, 0x42, 0xc3, 0xa9,
|
||||
0x7a, 0x69, 0x65, 0x72, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x73,
|
||||
0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d,
|
||||
0x0a, 0x66, 0x6e, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x63, 0x75, 0x62,
|
||||
0x69, 0x63, 0x28, 0x74, 0x3a, 0x20, 0x66, 0x33, 0x32, 0x2c, 0x20, 0x70,
|
||||
0x30, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x20, 0x70, 0x31,
|
||||
0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x20, 0x70, 0x32, 0x3a,
|
||||
0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x20, 0x70, 0x33, 0x3a, 0x20,
|
||||
0x76, 0x65, 0x63, 0x32, 0x66, 0x29, 0x20, 0x2d, 0x3e, 0x20, 0x76, 0x65,
|
||||
0x63, 0x32, 0x66, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x74, 0x20, 0x6d, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20,
|
||||
0x2d, 0x20, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x6d, 0x74, 0x32, 0x20, 0x3d, 0x20, 0x6d, 0x74, 0x20, 0x2a,
|
||||
0x20, 0x6d, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x74, 0x32, 0x20, 0x3d, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x74,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
|
||||
0x6e, 0x20, 0x6d, 0x74, 0x32, 0x20, 0x2a, 0x20, 0x6d, 0x74, 0x20, 0x2a,
|
||||
0x20, 0x70, 0x30, 0x20, 0x2b, 0x20, 0x33, 0x2e, 0x30, 0x20, 0x2a, 0x20,
|
||||
0x6d, 0x74, 0x32, 0x20, 0x2a, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x70, 0x31,
|
||||
0x20, 0x2b, 0x20, 0x33, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x6d, 0x74, 0x20,
|
||||
0x2a, 0x20, 0x74, 0x32, 0x20, 0x2a, 0x20, 0x70, 0x32, 0x20, 0x2b, 0x20,
|
||||
0x74, 0x32, 0x20, 0x2a, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x70, 0x33, 0x3b,
|
||||
0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x6e, 0x20, 0x65, 0x76,
|
||||
0x61, 0x6c, 0x5f, 0x63, 0x75, 0x62, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x72,
|
||||
0x69, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65, 0x28, 0x74, 0x3a, 0x20, 0x66,
|
||||
0x33, 0x32, 0x2c, 0x20, 0x70, 0x30, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32,
|
||||
0x66, 0x2c, 0x20, 0x70, 0x31, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66,
|
||||
0x2c, 0x20, 0x70, 0x32, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c,
|
||||
0x20, 0x70, 0x33, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x29, 0x20,
|
||||
0x2d, 0x3e, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x20, 0x7b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x74, 0x20, 0x3d,
|
||||
0x20, 0x31, 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x74, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x33, 0x2e,
|
||||
0x30, 0x20, 0x2a, 0x20, 0x6d, 0x74, 0x20, 0x2a, 0x20, 0x6d, 0x74, 0x20,
|
||||
0x2a, 0x20, 0x28, 0x70, 0x31, 0x20, 0x2d, 0x20, 0x70, 0x30, 0x29, 0x20,
|
||||
0x2b, 0x20, 0x36, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x6d, 0x74, 0x20, 0x2a,
|
||||
0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x70, 0x32, 0x20, 0x2d, 0x20, 0x70,
|
||||
0x31, 0x29, 0x20, 0x2b, 0x20, 0x33, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x74,
|
||||
0x20, 0x2a, 0x20, 0x74, 0x20, 0x2a, 0x20, 0x28, 0x70, 0x33, 0x20, 0x2d,
|
||||
0x20, 0x70, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
|
||||
0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x20, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x61, 0x20, 0x63, 0x75, 0x62, 0x69, 0x63, 0x20, 0x42, 0xc3,
|
||||
0xa9, 0x7a, 0x69, 0x65, 0x72, 0x20, 0x28, 0x73, 0x61, 0x6d, 0x70, 0x6c,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x2b, 0x20, 0x4e, 0x65, 0x77, 0x74, 0x6f, 0x6e,
|
||||
0x20, 0x72, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x29,
|
||||
0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d,
|
||||
0x0a, 0x66, 0x6e, 0x20, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
|
||||
0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x75, 0x62, 0x69, 0x63, 0x28, 0x70, 0x3a,
|
||||
0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x20, 0x73, 0x65, 0x67, 0x3a,
|
||||
0x20, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x29, 0x20, 0x2d, 0x3e,
|
||||
0x20, 0x66, 0x33, 0x32, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6c, 0x65, 0x74, 0x20, 0x70, 0x30, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x67,
|
||||
0x2e, 0x70, 0x30, 0x3b, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x70, 0x31, 0x20,
|
||||
0x3d, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70, 0x31, 0x3b, 0x20, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x70, 0x32, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70,
|
||||
0x32, 0x3b, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x70, 0x33, 0x20, 0x3d, 0x20,
|
||||
0x73, 0x65, 0x67, 0x2e, 0x70, 0x33, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6f,
|
||||
0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x73, 0x61,
|
||||
0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x31, 0x36, 0x75, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x62, 0x65,
|
||||
0x73, 0x74, 0x5f, 0x74, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x30, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x62, 0x65, 0x73,
|
||||
0x74, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x65, 0x32,
|
||||
0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20,
|
||||
0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x75, 0x3b,
|
||||
0x20, 0x69, 0x20, 0x3c, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73,
|
||||
0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x20,
|
||||
0x3d, 0x20, 0x66, 0x33, 0x32, 0x28, 0x69, 0x29, 0x20, 0x2f, 0x20, 0x66,
|
||||
0x33, 0x32, 0x28, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x2d,
|
||||
0x20, 0x31, 0x75, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x71, 0x20, 0x3d, 0x20, 0x65,
|
||||
0x76, 0x61, 0x6c, 0x5f, 0x63, 0x75, 0x62, 0x69, 0x63, 0x28, 0x74, 0x2c,
|
||||
0x20, 0x70, 0x30, 0x2c, 0x20, 0x70, 0x31, 0x2c, 0x20, 0x70, 0x32, 0x2c,
|
||||
0x20, 0x70, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x64, 0x20, 0x3d, 0x20, 0x64,
|
||||
0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x2c, 0x20, 0x71,
|
||||
0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x69, 0x66, 0x20, 0x64, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f,
|
||||
0x64, 0x69, 0x73, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x65, 0x73, 0x74,
|
||||
0x5f, 0x64, 0x69, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x62, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x2f, 0x2f, 0x20, 0x4e, 0x65, 0x77, 0x74, 0x6f, 0x6e, 0x20, 0x72,
|
||||
0x65, 0x66, 0x69, 0x6e, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x64,
|
||||
0x20, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x28, 0x6d,
|
||||
0x61, 0x78, 0x20, 0x34, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61,
|
||||
0x72, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28,
|
||||
0x62, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c,
|
||||
0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x74, 0x65,
|
||||
0x72, 0x20, 0x3d, 0x20, 0x30, 0x75, 0x3b, 0x20, 0x69, 0x74, 0x65, 0x72,
|
||||
0x20, 0x3c, 0x20, 0x34, 0x75, 0x3b, 0x20, 0x69, 0x74, 0x65, 0x72, 0x2b,
|
||||
0x2b, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x42, 0x20, 0x3d, 0x20, 0x65, 0x76,
|
||||
0x61, 0x6c, 0x5f, 0x63, 0x75, 0x62, 0x69, 0x63, 0x28, 0x74, 0x2c, 0x20,
|
||||
0x70, 0x30, 0x2c, 0x20, 0x70, 0x31, 0x2c, 0x20, 0x70, 0x32, 0x2c, 0x20,
|
||||
0x70, 0x33, 0x29, 0x20, 0x2d, 0x20, 0x70, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x42, 0x70,
|
||||
0x20, 0x3d, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x63, 0x75, 0x62, 0x69,
|
||||
0x63, 0x5f, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65,
|
||||
0x28, 0x74, 0x2c, 0x20, 0x70, 0x30, 0x2c, 0x20, 0x70, 0x31, 0x2c, 0x20,
|
||||
0x70, 0x32, 0x2c, 0x20, 0x70, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x66, 0x20,
|
||||
0x3d, 0x20, 0x64, 0x6f, 0x74, 0x28, 0x42, 0x2c, 0x20, 0x42, 0x70, 0x29,
|
||||
0x3b, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0xc2, 0xbd, 0x20, 0x64, 0x65,
|
||||
0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x6f, 0x66, 0x20,
|
||||
0x7c, 0x42, 0x7c, 0xc2, 0xb2, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x64, 0x66, 0x20, 0x3d, 0x20,
|
||||
0x64, 0x6f, 0x74, 0x28, 0x42, 0x70, 0x2c, 0x20, 0x42, 0x70, 0x29, 0x20,
|
||||
0x2b, 0x20, 0x64, 0x6f, 0x74, 0x28, 0x42, 0x2c, 0x20, 0x33, 0x2e, 0x30,
|
||||
0x20, 0x2a, 0x20, 0x28, 0x70, 0x32, 0x20, 0x2d, 0x20, 0x70, 0x31, 0x20,
|
||||
0x2b, 0x20, 0x28, 0x70, 0x33, 0x20, 0x2d, 0x20, 0x70, 0x32, 0x20, 0x2d,
|
||||
0x20, 0x70, 0x32, 0x20, 0x2b, 0x20, 0x70, 0x31, 0x29, 0x20, 0x2a, 0x20,
|
||||
0x32, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x74, 0x29, 0x29, 0x3b, 0x20, 0x2f,
|
||||
0x2f, 0x20, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64,
|
||||
0x20, 0x32, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x61,
|
||||
0x62, 0x73, 0x28, 0x64, 0x66, 0x29, 0x20, 0x3c, 0x20, 0x31, 0x65, 0x2d,
|
||||
0x31, 0x32, 0x20, 0x7b, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x20,
|
||||
0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x74, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x3d, 0x20, 0x66, 0x20,
|
||||
0x2f, 0x20, 0x64, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70,
|
||||
0x28, 0x74, 0x20, 0x2d, 0x20, 0x73, 0x74, 0x65, 0x70, 0x2c, 0x20, 0x30,
|
||||
0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x61, 0x62,
|
||||
0x73, 0x28, 0x73, 0x74, 0x65, 0x70, 0x29, 0x20, 0x3c, 0x20, 0x31, 0x65,
|
||||
0x2d, 0x36, 0x20, 0x7b, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x20,
|
||||
0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x71, 0x5f, 0x66, 0x69, 0x6e, 0x61,
|
||||
0x6c, 0x20, 0x3d, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x63, 0x75, 0x62,
|
||||
0x69, 0x63, 0x28, 0x74, 0x2c, 0x20, 0x70, 0x30, 0x2c, 0x20, 0x70, 0x31,
|
||||
0x2c, 0x20, 0x70, 0x32, 0x2c, 0x20, 0x70, 0x33, 0x29, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64,
|
||||
0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x2c, 0x20, 0x71,
|
||||
0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x74, 0x69,
|
||||
0x63, 0x61, 0x6c, 0x20, 0x63, 0x75, 0x62, 0x69, 0x63, 0x20, 0x72, 0x6f,
|
||||
0x6f, 0x74, 0x20, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x20, 0x28, 0x66,
|
||||
0x6f, 0x72, 0x20, 0x79, 0x2d, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x69, 0x6e,
|
||||
0x67, 0x29, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e,
|
||||
0x73, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
|
||||
0x72, 0x65, 0x61, 0x6c, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x5b, 0x30, 0x2c, 0x31, 0x5d, 0x2c, 0x20, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x73,
|
||||
0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x28, 0x75, 0x70, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x33, 0x29, 0x2e, 0x0d, 0x0a, 0x66, 0x6e, 0x20, 0x73, 0x6f,
|
||||
0x6c, 0x76, 0x65, 0x5f, 0x63, 0x75, 0x62, 0x69, 0x63, 0x5f, 0x69, 0x6e,
|
||||
0x5f, 0x30, 0x31, 0x28, 0x63, 0x33, 0x3a, 0x20, 0x66, 0x33, 0x32, 0x2c,
|
||||
0x20, 0x63, 0x32, 0x3a, 0x20, 0x66, 0x33, 0x32, 0x2c, 0x20, 0x63, 0x31,
|
||||
0x3a, 0x20, 0x66, 0x33, 0x32, 0x2c, 0x20, 0x63, 0x30, 0x3a, 0x20, 0x66,
|
||||
0x33, 0x32, 0x2c, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x3a, 0x20, 0x70,
|
||||
0x74, 0x72, 0x3c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c,
|
||||
0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3c, 0x66, 0x33, 0x32, 0x2c, 0x20,
|
||||
0x33, 0x3e, 0x3e, 0x29, 0x20, 0x2d, 0x3e, 0x20, 0x75, 0x33, 0x32, 0x20,
|
||||
0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4e, 0x6f,
|
||||
0x72, 0x6d, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x3a, 0x20, 0x63, 0x33, 0x20,
|
||||
0x2a, 0x20, 0x74, 0x5e, 0x33, 0x20, 0x2b, 0x20, 0x63, 0x32, 0x20, 0x2a,
|
||||
0x20, 0x74, 0x5e, 0x32, 0x20, 0x2b, 0x20, 0x63, 0x31, 0x20, 0x2a, 0x20,
|
||||
0x74, 0x20, 0x2b, 0x20, 0x63, 0x30, 0x20, 0x3d, 0x20, 0x30, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x61, 0x62, 0x73, 0x28, 0x63,
|
||||
0x33, 0x29, 0x20, 0x3c, 0x20, 0x31, 0x65, 0x2d, 0x39, 0x20, 0x7b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20,
|
||||
0x51, 0x75, 0x61, 0x64, 0x72, 0x61, 0x74, 0x69, 0x63, 0x20, 0x66, 0x61,
|
||||
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x61, 0x62, 0x73, 0x28, 0x63,
|
||||
0x32, 0x29, 0x20, 0x3c, 0x20, 0x31, 0x65, 0x2d, 0x39, 0x20, 0x7b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x69, 0x66, 0x20, 0x61, 0x62, 0x73, 0x28, 0x63, 0x31, 0x29, 0x20,
|
||||
0x3c, 0x20, 0x31, 0x65, 0x2d, 0x39, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74,
|
||||
0x75, 0x72, 0x6e, 0x20, 0x30, 0x75, 0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x74, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x2d, 0x63, 0x30, 0x20, 0x2f,
|
||||
0x20, 0x63, 0x31, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x20, 0x3e,
|
||||
0x3d, 0x20, 0x30, 0x2e, 0x30, 0x20, 0x26, 0x26, 0x20, 0x74, 0x20, 0x3c,
|
||||
0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x28, 0x2a, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x29, 0x5b, 0x30, 0x5d,
|
||||
0x20, 0x3d, 0x20, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72,
|
||||
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x75, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x30, 0x75, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
|
||||
0x20, 0x64, 0x69, 0x73, 0x63, 0x20, 0x3d, 0x20, 0x63, 0x31, 0x20, 0x2a,
|
||||
0x20, 0x63, 0x31, 0x20, 0x2d, 0x20, 0x34, 0x2e, 0x30, 0x20, 0x2a, 0x20,
|
||||
0x63, 0x32, 0x20, 0x2a, 0x20, 0x63, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x64, 0x69, 0x73,
|
||||
0x63, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x20, 0x7b, 0x20, 0x72, 0x65,
|
||||
0x74, 0x75, 0x72, 0x6e, 0x20, 0x30, 0x75, 0x3b, 0x20, 0x7d, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20,
|
||||
0x73, 0x64, 0x20, 0x3d, 0x20, 0x73, 0x71, 0x72, 0x74, 0x28, 0x64, 0x69,
|
||||
0x73, 0x63, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x30, 0x20, 0x3d, 0x20, 0x28,
|
||||
0x2d, 0x63, 0x31, 0x20, 0x2b, 0x20, 0x73, 0x64, 0x29, 0x20, 0x2f, 0x20,
|
||||
0x28, 0x32, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x63, 0x32, 0x29, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
|
||||
0x20, 0x74, 0x31, 0x20, 0x3d, 0x20, 0x28, 0x2d, 0x63, 0x31, 0x20, 0x2d,
|
||||
0x20, 0x73, 0x64, 0x29, 0x20, 0x2f, 0x20, 0x28, 0x32, 0x2e, 0x30, 0x20,
|
||||
0x2a, 0x20, 0x63, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x20, 0x3d, 0x20, 0x30, 0x75, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x30, 0x20, 0x3e,
|
||||
0x3d, 0x20, 0x30, 0x2e, 0x30, 0x20, 0x26, 0x26, 0x20, 0x74, 0x30, 0x20,
|
||||
0x3c, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x7b, 0x20, 0x28, 0x2a, 0x72,
|
||||
0x6f, 0x6f, 0x74, 0x73, 0x29, 0x5b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5d,
|
||||
0x20, 0x3d, 0x20, 0x74, 0x30, 0x3b, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x2b, 0x2b, 0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x31, 0x20, 0x3e, 0x3d, 0x20,
|
||||
0x30, 0x2e, 0x30, 0x20, 0x26, 0x26, 0x20, 0x74, 0x31, 0x20, 0x3c, 0x3d,
|
||||
0x20, 0x31, 0x2e, 0x30, 0x20, 0x7b, 0x20, 0x28, 0x2a, 0x72, 0x6f, 0x6f,
|
||||
0x74, 0x73, 0x29, 0x5b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5d, 0x20, 0x3d,
|
||||
0x20, 0x74, 0x31, 0x3b, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2b, 0x2b,
|
||||
0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x70, 0x72,
|
||||
0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x63, 0x75, 0x62, 0x69, 0x63, 0x3a,
|
||||
0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x78, 0x20, 0x2d,
|
||||
0x20, 0x63, 0x32, 0x2f, 0x28, 0x33, 0x2a, 0x63, 0x33, 0x29, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x20, 0x3d, 0x20,
|
||||
0x63, 0x32, 0x20, 0x2f, 0x20, 0x63, 0x33, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x63, 0x31,
|
||||
0x20, 0x2f, 0x20, 0x63, 0x33, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6c, 0x65, 0x74, 0x20, 0x63, 0x20, 0x3d, 0x20, 0x63, 0x30, 0x20, 0x2f,
|
||||
0x20, 0x63, 0x33, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x70, 0x20, 0x3d, 0x20, 0x62, 0x20, 0x2d, 0x20, 0x61, 0x20,
|
||||
0x2a, 0x20, 0x61, 0x20, 0x2f, 0x20, 0x33, 0x2e, 0x30, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x71, 0x20, 0x3d, 0x20,
|
||||
0x32, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x61, 0x20,
|
||||
0x2a, 0x20, 0x61, 0x20, 0x2f, 0x20, 0x32, 0x37, 0x2e, 0x30, 0x20, 0x2d,
|
||||
0x20, 0x61, 0x20, 0x2a, 0x20, 0x62, 0x20, 0x2f, 0x20, 0x33, 0x2e, 0x30,
|
||||
0x20, 0x2b, 0x20, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x74, 0x20, 0x64, 0x69, 0x73, 0x63, 0x20, 0x3d, 0x20, 0x71, 0x20,
|
||||
0x2a, 0x20, 0x71, 0x20, 0x2f, 0x20, 0x34, 0x2e, 0x30, 0x20, 0x2b, 0x20,
|
||||
0x70, 0x20, 0x2a, 0x20, 0x70, 0x20, 0x2a, 0x20, 0x70, 0x20, 0x2f, 0x20,
|
||||
0x32, 0x37, 0x2e, 0x30, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x76, 0x61, 0x72, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d,
|
||||
0x20, 0x30, 0x75, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x73, 0x68, 0x69, 0x66, 0x74, 0x20, 0x3d, 0x20, 0x61, 0x20,
|
||||
0x2f, 0x20, 0x33, 0x2e, 0x30, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x69, 0x66, 0x20, 0x64, 0x69, 0x73, 0x63, 0x20, 0x3e, 0x20,
|
||||
0x30, 0x2e, 0x30, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x73, 0x64, 0x20, 0x3d, 0x20,
|
||||
0x73, 0x71, 0x72, 0x74, 0x28, 0x64, 0x69, 0x73, 0x63, 0x29, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
|
||||
0x20, 0x75, 0x20, 0x3d, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x2d, 0x71,
|
||||
0x2f, 0x32, 0x2e, 0x30, 0x20, 0x2b, 0x20, 0x73, 0x64, 0x29, 0x20, 0x2a,
|
||||
0x20, 0x70, 0x6f, 0x77, 0x28, 0x61, 0x62, 0x73, 0x28, 0x2d, 0x71, 0x2f,
|
||||
0x32, 0x2e, 0x30, 0x20, 0x2b, 0x20, 0x73, 0x64, 0x29, 0x2c, 0x20, 0x31,
|
||||
0x2e, 0x30, 0x2f, 0x33, 0x2e, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x20,
|
||||
0x3d, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x2d, 0x71, 0x2f, 0x32, 0x2e,
|
||||
0x30, 0x20, 0x2d, 0x20, 0x73, 0x64, 0x29, 0x20, 0x2a, 0x20, 0x70, 0x6f,
|
||||
0x77, 0x28, 0x61, 0x62, 0x73, 0x28, 0x2d, 0x71, 0x2f, 0x32, 0x2e, 0x30,
|
||||
0x20, 0x2d, 0x20, 0x73, 0x64, 0x29, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x2f,
|
||||
0x33, 0x2e, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x78, 0x31, 0x20, 0x3d, 0x20,
|
||||
0x75, 0x20, 0x2b, 0x20, 0x76, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x20, 0x3d, 0x20,
|
||||
0x78, 0x31, 0x20, 0x2d, 0x20, 0x73, 0x68, 0x69, 0x66, 0x74, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
|
||||
0x74, 0x20, 0x3e, 0x3d, 0x20, 0x30, 0x2e, 0x30, 0x20, 0x26, 0x26, 0x20,
|
||||
0x74, 0x20, 0x3c, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x7b, 0x20, 0x28,
|
||||
0x2a, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x29, 0x5b, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x5d, 0x20, 0x3d, 0x20, 0x74, 0x3b, 0x20, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x2b, 0x2b, 0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x64, 0x69,
|
||||
0x73, 0x63, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x2e, 0x30, 0x20, 0x7b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
|
||||
0x20, 0x75, 0x20, 0x3d, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x28, 0x2d, 0x71,
|
||||
0x2f, 0x32, 0x2e, 0x30, 0x29, 0x20, 0x2a, 0x20, 0x70, 0x6f, 0x77, 0x28,
|
||||
0x61, 0x62, 0x73, 0x28, 0x2d, 0x71, 0x2f, 0x32, 0x2e, 0x30, 0x29, 0x2c,
|
||||
0x20, 0x31, 0x2e, 0x30, 0x2f, 0x33, 0x2e, 0x30, 0x29, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20,
|
||||
0x78, 0x31, 0x20, 0x3d, 0x20, 0x32, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x75,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x74, 0x20, 0x78, 0x32, 0x20, 0x3d, 0x20, 0x2d, 0x75, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
|
||||
0x20, 0x74, 0x31, 0x20, 0x3d, 0x20, 0x78, 0x31, 0x20, 0x2d, 0x20, 0x73,
|
||||
0x68, 0x69, 0x66, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x32, 0x20, 0x3d, 0x20,
|
||||
0x78, 0x32, 0x20, 0x2d, 0x20, 0x73, 0x68, 0x69, 0x66, 0x74, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
|
||||
0x74, 0x31, 0x20, 0x3e, 0x3d, 0x20, 0x30, 0x2e, 0x30, 0x20, 0x26, 0x26,
|
||||
0x20, 0x74, 0x31, 0x20, 0x3c, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x7b,
|
||||
0x20, 0x28, 0x2a, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x29, 0x5b, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x5d, 0x20, 0x3d, 0x20, 0x74, 0x31, 0x3b, 0x20, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x2b, 0x2b, 0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x74, 0x32,
|
||||
0x20, 0x3e, 0x3d, 0x20, 0x30, 0x2e, 0x30, 0x20, 0x26, 0x26, 0x20, 0x74,
|
||||
0x32, 0x20, 0x3c, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x7b, 0x20, 0x28,
|
||||
0x2a, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x29, 0x5b, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x5d, 0x20, 0x3d, 0x20, 0x74, 0x32, 0x3b, 0x20, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x2b, 0x2b, 0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x70,
|
||||
0x68, 0x69, 0x20, 0x3d, 0x20, 0x61, 0x63, 0x6f, 0x73, 0x28, 0x20, 0x2d,
|
||||
0x71, 0x20, 0x2f, 0x20, 0x28, 0x32, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x73,
|
||||
0x71, 0x72, 0x74, 0x28, 0x2d, 0x70, 0x2a, 0x70, 0x2a, 0x70, 0x2f, 0x32,
|
||||
0x37, 0x2e, 0x30, 0x29, 0x29, 0x20, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x72, 0x20,
|
||||
0x3d, 0x20, 0x32, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x73, 0x71, 0x72, 0x74,
|
||||
0x28, 0x2d, 0x70, 0x2f, 0x33, 0x2e, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28,
|
||||
0x76, 0x61, 0x72, 0x20, 0x6b, 0x20, 0x3d, 0x20, 0x30, 0x75, 0x3b, 0x20,
|
||||
0x6b, 0x20, 0x3c, 0x20, 0x33, 0x75, 0x3b, 0x20, 0x6b, 0x2b, 0x2b, 0x29,
|
||||
0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x78, 0x20, 0x3d, 0x20,
|
||||
0x72, 0x20, 0x2a, 0x20, 0x63, 0x6f, 0x73, 0x28, 0x28, 0x70, 0x68, 0x69,
|
||||
0x20, 0x2b, 0x20, 0x32, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x33, 0x2e, 0x31,
|
||||
0x34, 0x31, 0x35, 0x39, 0x32, 0x36, 0x35, 0x33, 0x35, 0x20, 0x2a, 0x20,
|
||||
0x66, 0x33, 0x32, 0x28, 0x6b, 0x29, 0x29, 0x20, 0x2f, 0x20, 0x33, 0x2e,
|
||||
0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x20, 0x3d,
|
||||
0x20, 0x78, 0x20, 0x2d, 0x20, 0x73, 0x68, 0x69, 0x66, 0x74, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x69, 0x66, 0x20, 0x74, 0x20, 0x3e, 0x3d, 0x20, 0x30, 0x2e, 0x30,
|
||||
0x20, 0x26, 0x26, 0x20, 0x74, 0x20, 0x3c, 0x3d, 0x20, 0x31, 0x2e, 0x30,
|
||||
0x20, 0x7b, 0x20, 0x28, 0x2a, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x29, 0x5b,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5d, 0x20, 0x3d, 0x20, 0x74, 0x3b, 0x20,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2b, 0x2b, 0x3b, 0x20, 0x7d, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
|
||||
0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x0d,
|
||||
0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x57, 0x69, 0x6e, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x75, 0x62,
|
||||
0x69, 0x63, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x66,
|
||||
0x6e, 0x20, 0x72, 0x61, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73,
|
||||
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x63, 0x75, 0x62, 0x69,
|
||||
0x63, 0x28, 0x70, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x20,
|
||||
0x73, 0x65, 0x67, 0x3a, 0x20, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x29, 0x20, 0x2d, 0x3e, 0x20, 0x69, 0x33, 0x32, 0x20, 0x7b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x57, 0x65, 0x20, 0x63, 0x61,
|
||||
0x73, 0x74, 0x20, 0x61, 0x20, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e,
|
||||
0x74, 0x61, 0x6c, 0x20, 0x72, 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d,
|
||||
0x20, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x2b, 0x78, 0x3b, 0x20, 0x66, 0x69,
|
||||
0x6e, 0x64, 0x20, 0x74, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x79,
|
||||
0x28, 0x74, 0x29, 0x20, 0x3d, 0x20, 0x70, 0x2e, 0x79, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x79, 0x30, 0x20, 0x3d, 0x20,
|
||||
0x73, 0x65, 0x67, 0x2e, 0x70, 0x30, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x70,
|
||||
0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
|
||||
0x20, 0x79, 0x31, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70, 0x31,
|
||||
0x2e, 0x79, 0x20, 0x2d, 0x20, 0x70, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x79, 0x32, 0x20, 0x3d, 0x20,
|
||||
0x73, 0x65, 0x67, 0x2e, 0x70, 0x32, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x70,
|
||||
0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
|
||||
0x20, 0x79, 0x33, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70, 0x33,
|
||||
0x2e, 0x79, 0x20, 0x2d, 0x20, 0x70, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x79, 0x28, 0x74, 0x29,
|
||||
0x20, 0x3d, 0x20, 0x28, 0x31, 0x2d, 0x74, 0x29, 0x5e, 0x33, 0x2a, 0x79,
|
||||
0x30, 0x20, 0x2b, 0x20, 0x33, 0x28, 0x31, 0x2d, 0x74, 0x29, 0x5e, 0x32,
|
||||
0x20, 0x74, 0x20, 0x2a, 0x20, 0x79, 0x31, 0x20, 0x2b, 0x20, 0x33, 0x28,
|
||||
0x31, 0x2d, 0x74, 0x29, 0x20, 0x74, 0x5e, 0x32, 0x20, 0x2a, 0x20, 0x79,
|
||||
0x32, 0x20, 0x2b, 0x20, 0x74, 0x5e, 0x33, 0x20, 0x2a, 0x20, 0x79, 0x33,
|
||||
0x20, 0x3d, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f,
|
||||
0x20, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x6c, 0x79,
|
||||
0x6e, 0x6f, 0x6d, 0x69, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x33, 0x20, 0x74,
|
||||
0x5e, 0x33, 0x20, 0x2b, 0x20, 0x63, 0x32, 0x20, 0x74, 0x5e, 0x32, 0x20,
|
||||
0x2b, 0x20, 0x63, 0x31, 0x20, 0x74, 0x20, 0x2b, 0x20, 0x63, 0x30, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x30, 0x20,
|
||||
0x3d, 0x20, 0x79, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x74, 0x20, 0x63, 0x31, 0x20, 0x3d, 0x20, 0x33, 0x2e, 0x30, 0x20,
|
||||
0x2a, 0x20, 0x28, 0x79, 0x31, 0x20, 0x2d, 0x20, 0x79, 0x30, 0x29, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x32,
|
||||
0x20, 0x3d, 0x20, 0x33, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x28, 0x79, 0x32,
|
||||
0x20, 0x2d, 0x20, 0x32, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x79, 0x31, 0x20,
|
||||
0x2b, 0x20, 0x79, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6c, 0x65, 0x74, 0x20, 0x63, 0x33, 0x20, 0x3d, 0x20, 0x79, 0x33, 0x20,
|
||||
0x2d, 0x20, 0x33, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x79, 0x32, 0x20, 0x2b,
|
||||
0x20, 0x33, 0x2e, 0x30, 0x20, 0x2a, 0x20, 0x79, 0x31, 0x20, 0x2d, 0x20,
|
||||
0x79, 0x30, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76,
|
||||
0x61, 0x72, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x3a, 0x20, 0x61, 0x72,
|
||||
0x72, 0x61, 0x79, 0x3c, 0x66, 0x33, 0x32, 0x2c, 0x20, 0x33, 0x3e, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x75,
|
||||
0x6d, 0x20, 0x3d, 0x20, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x5f, 0x63, 0x75,
|
||||
0x62, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x5f, 0x30, 0x31, 0x28, 0x63, 0x33,
|
||||
0x2c, 0x20, 0x63, 0x32, 0x2c, 0x20, 0x63, 0x31, 0x2c, 0x20, 0x63, 0x30,
|
||||
0x2c, 0x20, 0x26, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x29, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x77, 0x69, 0x6e, 0x64,
|
||||
0x20, 0x3d, 0x20, 0x30, 0x69, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x3d,
|
||||
0x20, 0x30, 0x75, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6e, 0x75, 0x6d,
|
||||
0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x20,
|
||||
0x3d, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x5b, 0x69, 0x5d, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
|
||||
0x20, 0x78, 0x20, 0x3d, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x63, 0x75,
|
||||
0x62, 0x69, 0x63, 0x28, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70,
|
||||
0x30, 0x2c, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70, 0x31, 0x2c, 0x20, 0x73,
|
||||
0x65, 0x67, 0x2e, 0x70, 0x32, 0x2c, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70,
|
||||
0x33, 0x29, 0x2e, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x78, 0x20, 0x3e, 0x20, 0x70, 0x2e,
|
||||
0x78, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x64, 0x79, 0x20,
|
||||
0x3d, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x63, 0x75, 0x62, 0x69, 0x63,
|
||||
0x5f, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65, 0x28,
|
||||
0x74, 0x2c, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70, 0x30, 0x2c, 0x20, 0x73,
|
||||
0x65, 0x67, 0x2e, 0x70, 0x31, 0x2c, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70,
|
||||
0x32, 0x2c, 0x20, 0x73, 0x65, 0x67, 0x2e, 0x70, 0x33, 0x29, 0x2e, 0x79,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x64, 0x79, 0x20, 0x3e, 0x20, 0x30,
|
||||
0x2e, 0x30, 0x20, 0x7b, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x20, 0x2b, 0x3d,
|
||||
0x20, 0x31, 0x69, 0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65,
|
||||
0x20, 0x69, 0x66, 0x20, 0x64, 0x79, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30,
|
||||
0x20, 0x7b, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x20, 0x2d, 0x3d, 0x20, 0x31,
|
||||
0x69, 0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x77,
|
||||
0x69, 0x6e, 0x64, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f,
|
||||
0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x20, 0x4d, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74,
|
||||
0x65, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x40, 0x63, 0x6f,
|
||||
0x6d, 0x70, 0x75, 0x74, 0x65, 0x20, 0x40, 0x77, 0x6f, 0x72, 0x6b, 0x67,
|
||||
0x72, 0x6f, 0x75, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x38, 0x2c,
|
||||
0x20, 0x38, 0x29, 0x0d, 0x0a, 0x66, 0x6e, 0x20, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x28, 0x40, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x28, 0x77, 0x6f,
|
||||
0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x29, 0x20,
|
||||
0x77, 0x67, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x33, 0x3c, 0x75, 0x33, 0x32,
|
||||
0x3e, 0x2c, 0x20, 0x2f, 0x2f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x77,
|
||||
0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x69, 0x73, 0x20,
|
||||
0x61, 0x20, 0x74, 0x69, 0x6c, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x40, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e,
|
||||
0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x63,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x29, 0x20, 0x6c, 0x6f,
|
||||
0x63, 0x61, 0x6c, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x33, 0x3c, 0x75, 0x33,
|
||||
0x32, 0x3e, 0x29, 0x20, 0x2f, 0x2f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20,
|
||||
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, 0x69,
|
||||
0x78, 0x65, 0x6c, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6c, 0x65, 0x74, 0x20, 0x74, 0x69, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x78,
|
||||
0x20, 0x3d, 0x20, 0x77, 0x67, 0x2e, 0x78, 0x20, 0x2f, 0x20, 0x31, 0x36,
|
||||
0x75, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20,
|
||||
0x74, 0x69, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x69, 0x6c, 0x65, 0x73,
|
||||
0x5b, 0x74, 0x69, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x78, 0x5d, 0x3b, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x70,
|
||||
0x78, 0x20, 0x3d, 0x20, 0x28, 0x77, 0x67, 0x2e, 0x78, 0x20, 0x25, 0x20,
|
||||
0x31, 0x36, 0x75, 0x29, 0x20, 0x2a, 0x20, 0x38, 0x75, 0x20, 0x2b, 0x20,
|
||||
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x70, 0x79, 0x20, 0x3d, 0x20, 0x77,
|
||||
0x67, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x38, 0x75, 0x20, 0x2b, 0x20, 0x6c,
|
||||
0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x70, 0x78, 0x20, 0x3e, 0x3d,
|
||||
0x20, 0x54, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x20, 0x7c,
|
||||
0x7c, 0x20, 0x70, 0x79, 0x20, 0x3e, 0x3d, 0x20, 0x54, 0x49, 0x4c, 0x45,
|
||||
0x5f, 0x53, 0x49, 0x5a, 0x45, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
|
||||
0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x76, 0x20, 0x3d,
|
||||
0x20, 0x28, 0x76, 0x65, 0x63, 0x32, 0x66, 0x28, 0x66, 0x33, 0x32, 0x28,
|
||||
0x70, 0x78, 0x29, 0x2c, 0x20, 0x66, 0x33, 0x32, 0x28, 0x70, 0x79, 0x29,
|
||||
0x29, 0x20, 0x2b, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x20, 0x2f, 0x20, 0x66,
|
||||
0x33, 0x32, 0x28, 0x54, 0x49, 0x4c, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45,
|
||||
0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20,
|
||||
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x78, 0x28,
|
||||
0x74, 0x69, 0x6c, 0x65, 0x2e, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x5f, 0x6d,
|
||||
0x69, 0x6e, 0x2c, 0x20, 0x74, 0x69, 0x6c, 0x65, 0x2e, 0x77, 0x6f, 0x72,
|
||||
0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x2c, 0x20, 0x75, 0x76, 0x29, 0x3b,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20,
|
||||
0x6d, 0x69, 0x6e, 0x44, 0x69, 0x73, 0x74, 0x3a, 0x20, 0x66, 0x33, 0x32,
|
||||
0x20, 0x3d, 0x20, 0x31, 0x65, 0x32, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x73, 0x64, 0x66, 0x3a, 0x20, 0x66,
|
||||
0x33, 0x32, 0x20, 0x3d, 0x20, 0x31, 0x65, 0x32, 0x30, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x77, 0x69, 0x6e, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x3a, 0x20, 0x69, 0x33, 0x32, 0x20, 0x3d, 0x20, 0x30,
|
||||
0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72,
|
||||
0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x30, 0x75,
|
||||
0x3b, 0x20, 0x73, 0x20, 0x3c, 0x20, 0x74, 0x69, 0x6c, 0x65, 0x2e, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x20, 0x73, 0x2b, 0x2b, 0x29, 0x20, 0x7b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f,
|
||||
0x20, 0x55, 0x73, 0x65, 0x20, 0x61, 0x20, 0x70, 0x72, 0x65, 0x2d, 0x63,
|
||||
0x75, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x73, 0x68, 0x61, 0x70, 0x65, 0x20,
|
||||
0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x70, 0x65, 0x72, 0x20, 0x74, 0x69,
|
||||
0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, 0x2d, 0x70, 0x69, 0x78,
|
||||
0x65, 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e,
|
||||
0x67, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b,
|
||||
0x74, 0x69, 0x6c, 0x65, 0x2e, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20,
|
||||
0x2b, 0x20, 0x73, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x66, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x69, 0x73, 0x20,
|
||||
0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x20, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x61, 0x6e,
|
||||
0x20, 0x77, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x63,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x69, 0x72, 0x63, 0x6c,
|
||||
0x65, 0x73, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x69, 0x66, 0x28, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3c, 0x20, 0x74,
|
||||
0x69, 0x6c, 0x65, 0x2e, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x5f, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x20,
|
||||
0x3d, 0x20, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x73, 0x5b, 0x69, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x5d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x64, 0x66, 0x20, 0x3d,
|
||||
0x20, 0x6d, 0x69, 0x6e, 0x28, 0x73, 0x64, 0x66, 0x2c, 0x20, 0x6c, 0x65,
|
||||
0x6e, 0x67, 0x74, 0x68, 0x28, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x2d,
|
||||
0x20, 0x63, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x29, 0x20, 0x2d,
|
||||
0x20, 0x63, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65,
|
||||
0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x73, 0x68, 0x61, 0x70, 0x65, 0x20,
|
||||
0x3d, 0x20, 0x73, 0x68, 0x61, 0x70, 0x65, 0x73, 0x5b, 0x69, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2a, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x62, 0x62, 0x6f, 0x78, 0x5f, 0x6d, 0x69, 0x6e, 0x20, 0x3d,
|
||||
0x20, 0x73, 0x68, 0x61, 0x70, 0x65, 0x2e, 0x62, 0x62, 0x6f, 0x78, 0x5f,
|
||||
0x6d, 0x69, 0x6e, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x62, 0x62,
|
||||
0x6f, 0x78, 0x5f, 0x6d, 0x61, 0x78, 0x20, 0x3d, 0x20, 0x73, 0x68, 0x61,
|
||||
0x70, 0x65, 0x2e, 0x62, 0x62, 0x6f, 0x78, 0x5f, 0x6d, 0x61, 0x78, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x64, 0x78, 0x20, 0x3d, 0x20, 0x6d,
|
||||
0x61, 0x78, 0x28, 0x62, 0x62, 0x6f, 0x78, 0x5f, 0x6d, 0x69, 0x6e, 0x2e,
|
||||
0x78, 0x20, 0x2d, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x78, 0x2c,
|
||||
0x20, 0x6d, 0x61, 0x78, 0x28, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x77, 0x6f,
|
||||
0x72, 0x6c, 0x64, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x62, 0x62, 0x6f, 0x78,
|
||||
0x5f, 0x6d, 0x61, 0x78, 0x2e, 0x78, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x74, 0x20, 0x64, 0x79, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x28,
|
||||
0x62, 0x62, 0x6f, 0x78, 0x5f, 0x6d, 0x69, 0x6e, 0x2e, 0x79, 0x20, 0x2d,
|
||||
0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x79, 0x2c, 0x20, 0x6d, 0x61,
|
||||
0x78, 0x28, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
|
||||
0x2e, 0x79, 0x20, 0x2d, 0x20, 0x62, 0x62, 0x6f, 0x78, 0x5f, 0x6d, 0x61,
|
||||
0x78, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20,
|
||||
0x64, 0x69, 0x73, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x62, 0x6f, 0x78, 0x20,
|
||||
0x3d, 0x20, 0x73, 0x71, 0x72, 0x74, 0x28, 0x64, 0x78, 0x20, 0x2a, 0x20,
|
||||
0x64, 0x78, 0x20, 0x2b, 0x20, 0x64, 0x79, 0x20, 0x2a, 0x20, 0x64, 0x79,
|
||||
0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x64, 0x69, 0x73, 0x74, 0x5f,
|
||||
0x74, 0x6f, 0x5f, 0x62, 0x6f, 0x78, 0x20, 0x3e, 0x3d, 0x20, 0x6d, 0x69,
|
||||
0x6e, 0x44, 0x69, 0x73, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x3b, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x7d, 0x2a, 0x2f, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x50, 0x72,
|
||||
0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x65,
|
||||
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x73, 0x68, 0x61, 0x70, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72,
|
||||
0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x73, 0x68,
|
||||
0x61, 0x70, 0x65, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x65,
|
||||
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x73,
|
||||
0x68, 0x61, 0x70, 0x65, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73,
|
||||
0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x2b, 0x20, 0x73, 0x68, 0x61,
|
||||
0x70, 0x65, 0x2e, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x73, 0x65,
|
||||
0x67, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73,
|
||||
0x5b, 0x69, 0x5d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x64, 0x20, 0x3d, 0x20, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x75, 0x62, 0x69, 0x63, 0x28,
|
||||
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2c, 0x20, 0x73, 0x65, 0x67, 0x29, 0x3b,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x44, 0x69, 0x73,
|
||||
0x74, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x6d, 0x69, 0x6e, 0x44,
|
||||
0x69, 0x73, 0x74, 0x2c, 0x20, 0x64, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x2b, 0x3d, 0x20, 0x72, 0x61, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x63, 0x75, 0x62,
|
||||
0x69, 0x63, 0x28, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2c, 0x20, 0x73, 0x65,
|
||||
0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c,
|
||||
0x65, 0x63, 0x74, 0x28, 0x31, 0x2e, 0x30, 0x2c, 0x20, 0x2d, 0x31, 0x2e,
|
||||
0x30, 0x2c, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x21,
|
||||
0x3d, 0x20, 0x30, 0x69, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x64, 0x66, 0x20,
|
||||
0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x73, 0x64, 0x66, 0x2c, 0x20, 0x73,
|
||||
0x69, 0x67, 0x6e, 0x20, 0x2a, 0x20, 0x6d, 0x69, 0x6e, 0x44, 0x69, 0x73,
|
||||
0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
|
||||
0x53, 0x74, 0x6f, 0x72, 0x65, 0x28, 0x73, 0x64, 0x66, 0x5f, 0x62, 0x75,
|
||||
0x66, 0x66, 0x65, 0x72, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x75,
|
||||
0x33, 0x32, 0x28, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x78, 0x29, 0x2c,
|
||||
0x20, 0x75, 0x33, 0x32, 0x28, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x79,
|
||||
0x29, 0x29, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x28, 0x73, 0x64,
|
||||
0x66, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c,
|
||||
0x20, 0x31, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d
|
||||
};
|
||||
unsigned int src_shaders_compute_wgsl_len = 8194;
|
||||
47
src/generated/display.h
Normal file
47
src/generated/display.h
Normal file
@@ -0,0 +1,47 @@
|
||||
unsigned char src_shaders_display_wgsl[] = {
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x55, 0x6e, 0x69, 0x66, 0x6f,
|
||||
0x72, 0x6d, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x2c, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x75, 0x33,
|
||||
0x32, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x76, 0x70, 0x3a,
|
||||
0x20, 0x6d, 0x61, 0x74, 0x34, 0x78, 0x34, 0x66, 0x2c, 0x0d, 0x0a, 0x7d,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x30,
|
||||
0x29, 0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x30,
|
||||
0x29, 0x20, 0x76, 0x61, 0x72, 0x3c, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x3e, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x3a,
|
||||
0x20, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x3b, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x31, 0x29, 0x20,
|
||||
0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x29, 0x20,
|
||||
0x76, 0x61, 0x72, 0x20, 0x73, 0x64, 0x66, 0x20, 0x3a, 0x20, 0x74, 0x65,
|
||||
0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x32, 0x64, 0x3c, 0x66, 0x33, 0x32,
|
||||
0x3e, 0x3b, 0x0d, 0x0a, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x31,
|
||||
0x29, 0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x31,
|
||||
0x29, 0x20, 0x76, 0x61, 0x72, 0x20, 0x73, 0x64, 0x66, 0x5f, 0x73, 0x61,
|
||||
0x6d, 0x70, 0x6c, 0x65, 0x72, 0x20, 0x3a, 0x20, 0x73, 0x61, 0x6d, 0x70,
|
||||
0x6c, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x76, 0x65, 0x72,
|
||||
0x74, 0x65, 0x78, 0x20, 0x66, 0x6e, 0x20, 0x76, 0x73, 0x5f, 0x6d, 0x61,
|
||||
0x69, 0x6e, 0x28, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x28, 0x30, 0x29, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x29, 0x20, 0x2d, 0x3e, 0x20,
|
||||
0x40, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x28, 0x70, 0x6f, 0x73,
|
||||
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66,
|
||||
0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74,
|
||||
0x75, 0x72, 0x6e, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x28, 0x70, 0x6f,
|
||||
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c,
|
||||
0x20, 0x31, 0x2e, 0x30, 0x29, 0x20, 0x2a, 0x20, 0x75, 0x6e, 0x69, 0x66,
|
||||
0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x6d, 0x76, 0x70, 0x3b, 0x0d, 0x0a, 0x7d,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x20, 0x66, 0x6e, 0x20, 0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x28, 0x40, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x28, 0x70, 0x6f,
|
||||
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x70, 0x6f, 0x73, 0x69,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x29,
|
||||
0x20, 0x2d, 0x3e, 0x20, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x28, 0x30, 0x29, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x0d, 0x0a,
|
||||
0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
|
||||
0x6e, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x53, 0x61, 0x6d,
|
||||
0x70, 0x6c, 0x65, 0x28, 0x73, 0x64, 0x66, 0x2c, 0x20, 0x73, 0x64, 0x66,
|
||||
0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x2c, 0x20, 0x70, 0x6f,
|
||||
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x78, 0x79, 0x29, 0x3b, 0x0d,
|
||||
0x0a, 0x7d
|
||||
};
|
||||
unsigned int src_shaders_display_wgsl_len = 518;
|
||||
@@ -1,95 +0,0 @@
|
||||
unsigned char src_shaders_shape_wgsl[] = {
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x56, 0x73, 0x55, 0x6e, 0x69,
|
||||
0x66, 0x6f, 0x72, 0x6d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d,
|
||||
0x76, 0x70, 0x3a, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x78, 0x34, 0x66, 0x2c,
|
||||
0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20,
|
||||
0x53, 0x68, 0x61, 0x70, 0x65, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
||||
0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x78, 0x34,
|
||||
0x66, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x73, 0x65, 0x5f,
|
||||
0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66,
|
||||
0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3a,
|
||||
0x20, 0x75, 0x33, 0x32, 0x2c, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74,
|
||||
0x72, 0x75, 0x63, 0x74, 0x20, 0x56, 0x73, 0x49, 0x6e, 0x20, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x28, 0x30, 0x29, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x0a, 0x7d, 0x3b,
|
||||
0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x56, 0x73, 0x32,
|
||||
0x46, 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x40, 0x62, 0x75,
|
||||
0x69, 0x6c, 0x74, 0x69, 0x6e, 0x28, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x29, 0x20, 0x70, 0x6f, 0x73, 0x3a, 0x20, 0x76, 0x65, 0x63,
|
||||
0x34, 0x66, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x40, 0x6c, 0x6f, 0x63,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x30, 0x29, 0x20, 0x40, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x69,
|
||||
0x6e, 0x65, 0x61, 0x72, 0x29, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
|
||||
0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x2c, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a,
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x46, 0x73, 0x4f, 0x75, 0x74,
|
||||
0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x40, 0x6c, 0x6f, 0x63, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x28, 0x30, 0x29, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
|
||||
0x72, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x2c, 0x0a, 0x7d, 0x3b,
|
||||
0x0a, 0x0a, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x30,
|
||||
0x29, 0x20, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x30, 0x29, 0x20,
|
||||
0x76, 0x61, 0x72, 0x3c, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3e,
|
||||
0x20, 0x76, 0x73, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73,
|
||||
0x3a, 0x20, 0x56, 0x73, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3b,
|
||||
0x0a, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x31, 0x29,
|
||||
0x20, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x30, 0x29, 0x20, 0x76,
|
||||
0x61, 0x72, 0x3c, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x20,
|
||||
0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x3a, 0x20, 0x53, 0x68, 0x61, 0x70, 0x65, 0x55, 0x6e, 0x69, 0x66,
|
||||
0x6f, 0x72, 0x6d, 0x3b, 0x0a, 0x0a, 0x40, 0x76, 0x65, 0x72, 0x74, 0x65,
|
||||
0x78, 0x20, 0x66, 0x6e, 0x20, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x20, 0x56, 0x73, 0x49, 0x6e,
|
||||
0x29, 0x20, 0x2d, 0x3e, 0x20, 0x56, 0x73, 0x32, 0x46, 0x73, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x75, 0x74,
|
||||
0x70, 0x75, 0x74, 0x3a, 0x20, 0x56, 0x73, 0x32, 0x46, 0x73, 0x3b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x6c,
|
||||
0x64, 0x5f, 0x70, 0x6f, 0x73, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34,
|
||||
0x66, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x70, 0x6f, 0x73, 0x69,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x79,
|
||||
0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x20,
|
||||
0x2a, 0x20, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x66,
|
||||
0x6f, 0x72, 0x6d, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75,
|
||||
0x74, 0x2e, 0x70, 0x6f, 0x73, 0x20, 0x3d, 0x20, 0x77, 0x6f, 0x72, 0x6c,
|
||||
0x64, 0x5f, 0x70, 0x6f, 0x73, 0x20, 0x2a, 0x20, 0x76, 0x73, 0x5f, 0x75,
|
||||
0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x6d, 0x76, 0x70, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x68, 0x61,
|
||||
0x70, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x32, 0x75, 0x29, 0x20,
|
||||
0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75,
|
||||
0x74, 0x70, 0x75, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d,
|
||||
0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x28, 0x31, 0x2e, 0x30, 0x2c, 0x20,
|
||||
0x30, 0x2e, 0x38, 0x34, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x31,
|
||||
0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65,
|
||||
0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x68, 0x61, 0x70,
|
||||
0x65, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x73, 0x74,
|
||||
0x61, 0x74, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x75, 0x29, 0x20, 0x7b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74,
|
||||
0x70, 0x75, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20,
|
||||
0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f,
|
||||
0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x62, 0x61, 0x73, 0x65,
|
||||
0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x2a, 0x20, 0x31, 0x2e, 0x35,
|
||||
0x2c, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x28, 0x30, 0x2e, 0x30, 0x29,
|
||||
0x2c, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x28, 0x31, 0x2e, 0x30, 0x29,
|
||||
0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73,
|
||||
0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x20, 0x3d, 0x20, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, 0x75, 0x6e, 0x69,
|
||||
0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f,
|
||||
0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75,
|
||||
0x74, 0x70, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x40, 0x66, 0x72,
|
||||
0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6e, 0x20, 0x66, 0x73,
|
||||
0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a,
|
||||
0x20, 0x56, 0x73, 0x32, 0x46, 0x73, 0x29, 0x20, 0x2d, 0x3e, 0x20, 0x46,
|
||||
0x73, 0x4f, 0x75, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76,
|
||||
0x61, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3a, 0x20, 0x46,
|
||||
0x73, 0x4f, 0x75, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75,
|
||||
0x74, 0x70, 0x75, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d,
|
||||
0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
|
||||
0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a
|
||||
};
|
||||
unsigned int src_shaders_shape_wgsl_len = 1103;
|
||||
@@ -1,145 +0,0 @@
|
||||
unsigned char src_shaders_sprite_wgsl[] = {
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x53, 0x70, 0x72, 0x69, 0x74,
|
||||
0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x74,
|
||||
0x72, 0x69, 0x78, 0x3a, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x78, 0x34, 0x66,
|
||||
0x2c, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63,
|
||||
0x74, 0x20, 0x56, 0x73, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20,
|
||||
0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x76, 0x70, 0x3a, 0x20,
|
||||
0x6d, 0x61, 0x74, 0x34, 0x78, 0x34, 0x66, 0x2c, 0x0d, 0x0a, 0x7d, 0x3b,
|
||||
0x0d, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x56, 0x73, 0x49,
|
||||
0x20, 0x7b, 0x20, 0x2f, 0x2f, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20,
|
||||
0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74,
|
||||
0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x40, 0x62, 0x75, 0x69, 0x6c, 0x74,
|
||||
0x69, 0x6e, 0x28, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f,
|
||||
0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x2c, 0x0d, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x28, 0x30, 0x29, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28,
|
||||
0x31, 0x29, 0x20, 0x75, 0x76, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66,
|
||||
0x2c, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63,
|
||||
0x74, 0x20, 0x56, 0x73, 0x32, 0x46, 0x73, 0x20, 0x7b, 0x20, 0x2f, 0x2f,
|
||||
0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65,
|
||||
0x72, 0x20, 0x74, 0x6f, 0x20, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x40, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x28, 0x70,
|
||||
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x70, 0x6f, 0x73,
|
||||
0x3a, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x2c, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28,
|
||||
0x30, 0x29, 0x20, 0x40, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c,
|
||||
0x61, 0x74, 0x65, 0x28, 0x6c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x29, 0x20,
|
||||
0x75, 0x76, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x0d, 0x0a,
|
||||
0x7d, 0x3b, 0x0d, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x46,
|
||||
0x73, 0x4f, 0x20, 0x7b, 0x20, 0x2f, 0x2f, 0x46, 0x72, 0x61, 0x67, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x6f,
|
||||
0x75, 0x74, 0x70, 0x75, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x40,
|
||||
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x30, 0x29, 0x20,
|
||||
0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66,
|
||||
0x2c, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x62, 0x69,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x29, 0x20, 0x40, 0x67, 0x72,
|
||||
0x6f, 0x75, 0x70, 0x28, 0x30, 0x29, 0x20, 0x76, 0x61, 0x72, 0x3c, 0x75,
|
||||
0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x20, 0x76, 0x73, 0x5f, 0x75,
|
||||
0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x3a, 0x20, 0x56, 0x73, 0x55,
|
||||
0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3b, 0x0d, 0x0a, 0x40, 0x62, 0x69,
|
||||
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x29, 0x20, 0x40, 0x67, 0x72,
|
||||
0x6f, 0x75, 0x70, 0x28, 0x31, 0x29, 0x20, 0x76, 0x61, 0x72, 0x20, 0x74,
|
||||
0x65, 0x78, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f,
|
||||
0x32, 0x64, 0x3c, 0x66, 0x33, 0x32, 0x3e, 0x3b, 0x0d, 0x0a, 0x40, 0x62,
|
||||
0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x31, 0x29, 0x20, 0x40, 0x67,
|
||||
0x72, 0x6f, 0x75, 0x70, 0x28, 0x31, 0x29, 0x20, 0x76, 0x61, 0x72, 0x20,
|
||||
0x73, 0x61, 0x6d, 0x70, 0x3a, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
|
||||
0x72, 0x3b, 0x0d, 0x0a, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67,
|
||||
0x28, 0x32, 0x29, 0x20, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x31,
|
||||
0x29, 0x20, 0x76, 0x61, 0x72, 0x3c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
|
||||
0x65, 0x3e, 0x20, 0x73, 0x70, 0x72, 0x69, 0x74, 0x65, 0x73, 0x3a, 0x20,
|
||||
0x61, 0x72, 0x72, 0x61, 0x79, 0x3c, 0x53, 0x70, 0x72, 0x69, 0x74, 0x65,
|
||||
0x3e, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x76, 0x65, 0x72, 0x74, 0x65,
|
||||
0x78, 0x20, 0x66, 0x6e, 0x20, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x20, 0x56, 0x73, 0x49, 0x29,
|
||||
0x20, 0x2d, 0x3e, 0x20, 0x56, 0x73, 0x32, 0x46, 0x73, 0x20, 0x7b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x75, 0x74,
|
||||
0x70, 0x75, 0x74, 0x3a, 0x20, 0x56, 0x73, 0x32, 0x46, 0x73, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f,
|
||||
0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x70, 0x6f, 0x73, 0x20, 0x3d, 0x20,
|
||||
0x76, 0x65, 0x63, 0x34, 0x66, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2e,
|
||||
0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x78, 0x2c, 0x20,
|
||||
0x69, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x2e, 0x79, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x20,
|
||||
0x2a, 0x20, 0x73, 0x70, 0x72, 0x69, 0x74, 0x65, 0x73, 0x5b, 0x69, 0x6e,
|
||||
0x70, 0x75, 0x74, 0x2e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
|
||||
0x5d, 0x2e, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, 0x2a, 0x20, 0x76,
|
||||
0x73, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2e, 0x6d,
|
||||
0x76, 0x70, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74,
|
||||
0x70, 0x75, 0x74, 0x2e, 0x75, 0x76, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x2e, 0x75, 0x76, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74,
|
||||
0x70, 0x75, 0x74, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f,
|
||||
0x2f, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, 0x61, 0x20,
|
||||
0x33, 0x32, 0x62, 0x69, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x63,
|
||||
0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x28, 0x68, 0x65, 0x78, 0x20, 0x72, 0x65,
|
||||
0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x29, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x6e, 0x6f, 0x72,
|
||||
0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x76, 0x65, 0x63, 0x34,
|
||||
0x66, 0x0d, 0x0a, 0x2f, 0x2a, 0x66, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x76,
|
||||
0x65, 0x72, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x29, 0x20, 0x2d, 0x3e, 0x20,
|
||||
0x76, 0x65, 0x63, 0x34, 0x66, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x6c, 0x65, 0x74, 0x20, 0x72, 0x3a, 0x20, 0x66, 0x33, 0x32, 0x20,
|
||||
0x3d, 0x20, 0x66, 0x33, 0x32, 0x28, 0x28, 0x28, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x20, 0x3e, 0x3e, 0x20, 0x20, 0x30, 0x29, 0x20, 0x26, 0x20, 0x30,
|
||||
0x78, 0x66, 0x66, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6c, 0x65, 0x74, 0x20, 0x67, 0x3a, 0x20, 0x66, 0x33, 0x32, 0x20, 0x3d,
|
||||
0x20, 0x66, 0x33, 0x32, 0x28, 0x28, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74,
|
||||
0x20, 0x3e, 0x3e, 0x20, 0x20, 0x38, 0x29, 0x20, 0x26, 0x20, 0x30, 0x78,
|
||||
0x66, 0x66, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
|
||||
0x65, 0x74, 0x20, 0x62, 0x3a, 0x20, 0x66, 0x33, 0x32, 0x20, 0x3d, 0x20,
|
||||
0x66, 0x33, 0x32, 0x28, 0x28, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20,
|
||||
0x3e, 0x3e, 0x20, 0x31, 0x36, 0x29, 0x20, 0x26, 0x20, 0x30, 0x78, 0x66,
|
||||
0x66, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
|
||||
0x74, 0x20, 0x61, 0x3a, 0x20, 0x66, 0x33, 0x32, 0x20, 0x3d, 0x20, 0x66,
|
||||
0x33, 0x32, 0x28, 0x28, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x3e,
|
||||
0x3e, 0x20, 0x32, 0x34, 0x29, 0x20, 0x26, 0x20, 0x30, 0x78, 0x66, 0x66,
|
||||
0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72,
|
||||
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x65, 0x63, 0x34, 0x66, 0x28,
|
||||
0x72, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x67, 0x20, 0x2f,
|
||||
0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x62, 0x20, 0x2f, 0x20, 0x32, 0x35,
|
||||
0x35, 0x2c, 0x20, 0x61, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b,
|
||||
0x0d, 0x0a, 0x7d, 0x2a, 0x2f, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x47, 0x65,
|
||||
0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
|
||||
0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x69, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55,
|
||||
0x56, 0x0d, 0x0a, 0x2f, 0x2a, 0x66, 0x6e, 0x20, 0x69, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x28, 0x75,
|
||||
0x76, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x32, 0x66, 0x2c, 0x20, 0x77, 0x69,
|
||||
0x64, 0x74, 0x68, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x2c, 0x20, 0x68, 0x65,
|
||||
0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x29, 0x20, 0x2d,
|
||||
0x3e, 0x20, 0x75, 0x33, 0x32, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x6c, 0x65, 0x74, 0x20, 0x78, 0x3a, 0x20, 0x75, 0x33, 0x32, 0x20,
|
||||
0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x66, 0x6c, 0x6f, 0x6f,
|
||||
0x72, 0x28, 0x75, 0x76, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x66, 0x33, 0x32,
|
||||
0x28, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x29, 0x2c, 0x20, 0x30, 0x2c,
|
||||
0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x79, 0x3a, 0x20, 0x75, 0x33, 0x32,
|
||||
0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x66, 0x6c, 0x6f,
|
||||
0x6f, 0x72, 0x28, 0x75, 0x76, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x66, 0x33,
|
||||
0x32, 0x28, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x29, 0x2c, 0x20,
|
||||
0x30, 0x2c, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
|
||||
0x79, 0x20, 0x2a, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x2b, 0x20,
|
||||
0x78, 0x3b, 0x0d, 0x0a, 0x7d, 0x2a, 0x2f, 0x0d, 0x0a, 0x0d, 0x0a, 0x40,
|
||||
0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6e, 0x20,
|
||||
0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x3a, 0x20, 0x56, 0x73, 0x32, 0x46, 0x73, 0x29, 0x20, 0x2d, 0x3e,
|
||||
0x20, 0x46, 0x73, 0x4f, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x76, 0x61, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3a, 0x20,
|
||||
0x46, 0x73, 0x4f, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
|
||||
0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x20, 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x53, 0x61,
|
||||
0x6d, 0x70, 0x6c, 0x65, 0x28, 0x74, 0x65, 0x78, 0x2c, 0x20, 0x73, 0x61,
|
||||
0x6d, 0x70, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x75, 0x76,
|
||||
0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
|
||||
0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3b,
|
||||
0x0d, 0x0a, 0x7d
|
||||
};
|
||||
unsigned int src_shaders_sprite_wgsl_len = 1695;
|
||||
254
src/history.h
254
src/history.h
@@ -1,254 +0,0 @@
|
||||
#ifndef HISTORY_H
|
||||
#define HISTORY_H
|
||||
|
||||
#include "api.h"
|
||||
|
||||
// Each property kind we can undo/redo independently
|
||||
typedef enum {
|
||||
HIST_POSITION,
|
||||
HIST_SCALE,
|
||||
HIST_ROTATION,
|
||||
HIST_COLOR,
|
||||
} hist_prop_t;
|
||||
|
||||
// One property change on one shape (old → new)
|
||||
typedef struct hist_change_t {
|
||||
int shape_index;
|
||||
hist_prop_t prop;
|
||||
float old_val[4];
|
||||
float new_val[4];
|
||||
} hist_change_t;
|
||||
|
||||
// A history entry is one or more changes batched together.
|
||||
// Single-property edits = 1 change. Whole-selection edits = N changes.
|
||||
typedef struct hist_entry_t {
|
||||
hist_change_t *changes;
|
||||
int count;
|
||||
} hist_entry_t;
|
||||
|
||||
#define HIST_MAX 64
|
||||
|
||||
typedef struct history_t {
|
||||
hist_entry_t entries[HIST_MAX];
|
||||
int count;
|
||||
int current; // index of last applied entry, -1 = initial state
|
||||
|
||||
// Pending edit session (one ImGui widget interaction)
|
||||
bool capturing;
|
||||
int pending_shape_idx;
|
||||
hist_prop_t pending_prop;
|
||||
float pending_old[4];
|
||||
} history_t;
|
||||
|
||||
// -- internal helpers --
|
||||
|
||||
/**
|
||||
* Read the current value of a single property from a shape.
|
||||
*
|
||||
* @param s shape to read from
|
||||
* @param prop which property (HIST_POSITION, HIST_SCALE, etc.)
|
||||
* @param out receives the value, zero-padded to 4 floats
|
||||
*/
|
||||
static void hist_read_prop(shape_t *s, hist_prop_t prop, float out[4]) {
|
||||
memset(out, 0, sizeof(float[4]));
|
||||
switch (prop) {
|
||||
case HIST_POSITION: out[0] = s->cx; out[1] = s->cy; break;
|
||||
case HIST_SCALE: out[0] = s->sx; out[1] = s->sy; break;
|
||||
case HIST_ROTATION: out[0] = s->rotation; break;
|
||||
case HIST_COLOR: memcpy(out, s->uniform.base_color, sizeof(float[4])); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a value to a single property of a shape. Does NOT regenerate buffers.
|
||||
*
|
||||
* @param s shape to modify in-place
|
||||
* @param prop which property to set
|
||||
* @param val new value (4 floats, zero-padded for smaller properties)
|
||||
*/
|
||||
static void hist_apply_prop(shape_t *s, hist_prop_t prop, const float val[4]) {
|
||||
switch (prop) {
|
||||
case HIST_POSITION: s->cx = val[0]; s->cy = val[1]; break;
|
||||
case HIST_SCALE: s->sx = val[0]; s->sy = val[1]; break;
|
||||
case HIST_ROTATION: s->rotation = val[0]; break;
|
||||
case HIST_COLOR: memcpy(s->uniform.base_color, val, sizeof(float[4])); break;
|
||||
}
|
||||
}
|
||||
|
||||
// -- history API --
|
||||
|
||||
/**
|
||||
* Zero-initialize the history stack. Call once during app init.
|
||||
*
|
||||
* @param h history to initialize
|
||||
*/
|
||||
static void history_init(history_t *h) {
|
||||
memset(h, 0, sizeof(*h));
|
||||
h->current = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free all heap memory held by the history stack. Call during app shutdown.
|
||||
*
|
||||
* @param h history to destroy
|
||||
*/
|
||||
static void history_destroy(history_t *h) {
|
||||
for (int i = 0; i < h->count; i++) {
|
||||
if (h->entries[i].changes) FREE(h->entries[i].changes);
|
||||
}
|
||||
memset(h, 0, sizeof(*h));
|
||||
h->current = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a completed entry onto the stack, discarding any redo branch.
|
||||
* Takes ownership of entry.changes (must be heap-allocated with ALLOC).
|
||||
* Used internally by begin_edit/end_edit, or directly for batch edits.
|
||||
*
|
||||
* @param h history stack
|
||||
* @param entry entry to push (changes array is consumed, not copied)
|
||||
*/
|
||||
static void history_push_entry(history_t *h, hist_entry_t entry) {
|
||||
while (h->count > h->current + 1) {
|
||||
h->count--;
|
||||
if (h->entries[h->count].changes) {
|
||||
FREE(h->entries[h->count].changes);
|
||||
h->entries[h->count].changes = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (h->count >= HIST_MAX) {
|
||||
if (h->entries[0].changes) FREE(h->entries[0].changes);
|
||||
memmove(&h->entries[0], &h->entries[1],
|
||||
(h->count - 1) * sizeof(hist_entry_t));
|
||||
h->count--;
|
||||
h->current--;
|
||||
}
|
||||
|
||||
h->entries[h->count] = entry;
|
||||
h->count++;
|
||||
h->current = h->count - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin capturing an edit session. Snapshots the current value of one property.
|
||||
* If a prior session is still open (e.g. user switched widgets in the same frame),
|
||||
* it is finalized and pushed first.
|
||||
* Call when igIsItemActivated() is true after an ImGui widget.
|
||||
*
|
||||
* @param h history stack
|
||||
* @param shapes the shapes vector (used to read current values)
|
||||
* @param shape_idx index of the shape being edited
|
||||
* @param prop which property is about to change
|
||||
*/
|
||||
static void history_begin_edit(history_t *h, vector_t *shapes,
|
||||
int shape_idx, hist_prop_t prop) {
|
||||
if (h->capturing) {
|
||||
shape_t *s = (shape_t*) vec_get(shapes, h->pending_shape_idx);
|
||||
float new_val[4];
|
||||
hist_read_prop(s, h->pending_prop, new_val);
|
||||
if (memcmp(h->pending_old, new_val, sizeof(float[4])) != 0) {
|
||||
hist_change_t change = {
|
||||
.shape_index = h->pending_shape_idx,
|
||||
.prop = h->pending_prop,
|
||||
};
|
||||
memcpy(change.old_val, h->pending_old, sizeof(float[4]));
|
||||
memcpy(change.new_val, new_val, sizeof(float[4]));
|
||||
hist_entry_t entry = { .changes = NULL, .count = 1 };
|
||||
entry.changes = (hist_change_t*) ALLOC(sizeof(hist_change_t));
|
||||
*entry.changes = change;
|
||||
history_push_entry(h, entry);
|
||||
}
|
||||
h->capturing = false;
|
||||
}
|
||||
|
||||
h->capturing = true;
|
||||
h->pending_shape_idx = shape_idx;
|
||||
h->pending_prop = prop;
|
||||
shape_t *s = (shape_t*) vec_get(shapes, shape_idx);
|
||||
hist_read_prop(s, prop, h->pending_old);
|
||||
}
|
||||
|
||||
/**
|
||||
* End the current edit session and push an entry if the value changed.
|
||||
* Safe to call when no session is active (no-op).
|
||||
* Call when igIsAnyItemActive() transitions from true to false.
|
||||
*
|
||||
* @param h history stack
|
||||
* @param shapes the shapes vector (used to read final values)
|
||||
*/
|
||||
static void history_end_edit(history_t *h, vector_t *shapes) {
|
||||
if (!h->capturing) return;
|
||||
|
||||
shape_t *s = (shape_t*) vec_get(shapes, h->pending_shape_idx);
|
||||
float new_val[4];
|
||||
hist_read_prop(s, h->pending_prop, new_val);
|
||||
|
||||
if (memcmp(h->pending_old, new_val, sizeof(float[4])) != 0) {
|
||||
hist_change_t change = {
|
||||
.shape_index = h->pending_shape_idx,
|
||||
.prop = h->pending_prop,
|
||||
};
|
||||
memcpy(change.old_val, h->pending_old, sizeof(float[4]));
|
||||
memcpy(change.new_val, new_val, sizeof(float[4]));
|
||||
hist_entry_t entry = { .changes = NULL, .count = 1 };
|
||||
entry.changes = (hist_change_t*) ALLOC(sizeof(hist_change_t));
|
||||
*entry.changes = change;
|
||||
history_push_entry(h, entry);
|
||||
}
|
||||
h->capturing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply every change in an entry to the shapes vector and regenerate buffers.
|
||||
*
|
||||
* @param entry the history entry to apply
|
||||
* @param shapes the shapes vector to modify
|
||||
* @param forward true to use new_val (redo), false to use old_val (undo)
|
||||
*/
|
||||
static void history_apply_entry(hist_entry_t *entry, vector_t *shapes, bool forward) {
|
||||
for (int i = 0; i < entry->count; i++) {
|
||||
hist_change_t *c = &entry->changes[i];
|
||||
if (c->shape_index >= shapes->count) continue;
|
||||
shape_t *s = (shape_t*) vec_get(shapes, c->shape_index);
|
||||
hist_apply_prop(s, c->prop, forward ? c->new_val : c->old_val);
|
||||
shape_regenerate(s);
|
||||
shape_set_state(s, s->hovered, s->selected);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the most recent history entry.
|
||||
*
|
||||
* @param h history stack
|
||||
* @param shapes the shapes vector to revert
|
||||
* @param selected_count out-parameter for updated selection count (currently passed through)
|
||||
* @return true if state was changed, false if nothing to undo
|
||||
*/
|
||||
static bool history_undo(history_t *h, vector_t *shapes, int *selected_count) {
|
||||
if (h->current < 0) return false;
|
||||
|
||||
history_apply_entry(&h->entries[h->current], shapes, false);
|
||||
h->current--;
|
||||
(void)selected_count;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redo the next history entry.
|
||||
*
|
||||
* @param h history stack
|
||||
* @param shapes the shapes vector to advance
|
||||
* @param selected_count out-parameter (currently passed through)
|
||||
* @return true if state was changed, false if nothing to redo
|
||||
*/
|
||||
static bool history_redo(history_t *h, vector_t *shapes, int *selected_count) {
|
||||
if (h->current + 1 >= h->count) return false;
|
||||
|
||||
h->current++;
|
||||
history_apply_entry(&h->entries[h->current], shapes, true);
|
||||
(void)selected_count;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
1697
src/main.c
1697
src/main.c
File diff suppressed because it is too large
Load Diff
36
src/pool.h
Normal file
36
src/pool.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "api.h"
|
||||
|
||||
#define MAX_BUFFER_SIZE 1024 * 1024 * 1024 // 1GB
|
||||
|
||||
static void pool_buffer_grow(sg_buffer buffer, uint32_t stripe, uint32_t count, void* data)
|
||||
{
|
||||
size_t size = sg_query_buffer_size(buffer);
|
||||
if(size == MAX_BUFFER_SIZE) return sg_update_buffer(buffer, &(sg_range) { data, MAX_BUFFER_SIZE });
|
||||
if(size < stripe * count)
|
||||
{
|
||||
sg_buffer_desc desc = sg_query_buffer_desc(buffer);
|
||||
while(desc.size < stripe * count) desc.size = fmaxf(MAX_BUFFER_SIZE, size * 2);
|
||||
|
||||
sg_uninit_buffer(buffer);
|
||||
sg_init_buffer(buffer, &desc);
|
||||
}
|
||||
|
||||
sg_update_buffer(buffer, &(sg_range) { data, stripe * count });
|
||||
}
|
||||
static void pool_view_grow(sg_view view, uint32_t stripe, uint32_t count, void* data)
|
||||
{
|
||||
sg_buffer buffer = sg_query_view_buffer(view);
|
||||
|
||||
size_t size = sg_query_buffer_size(buffer);
|
||||
if(size == MAX_BUFFER_SIZE) return sg_update_buffer(buffer, &(sg_range) { data, MAX_BUFFER_SIZE });
|
||||
if(size < stripe * count)
|
||||
{
|
||||
sg_buffer_desc desc = sg_query_buffer_desc(buffer);
|
||||
while(desc.size < stripe * count) desc.size = fmaxf(MAX_BUFFER_SIZE, size * 2);
|
||||
|
||||
sg_uninit_buffer(buffer);
|
||||
sg_init_buffer(buffer, &desc);
|
||||
}
|
||||
|
||||
sg_update_buffer(buffer, &(sg_range) { data, stripe * count });
|
||||
}
|
||||
107
src/rand.h
107
src/rand.h
@@ -1,107 +0,0 @@
|
||||
#ifndef RAND_H
|
||||
#define RAND_H
|
||||
|
||||
#include "api.h"
|
||||
|
||||
static uint32_t seed;
|
||||
|
||||
static uint32_t xorshift32(void);
|
||||
static void rand_seed(uint32_t _seed);
|
||||
static uint32_t next_int(void);
|
||||
static uint32_t next_int_max(uint32_t max);
|
||||
static uint32_t next_int_minmax(uint32_t min, uint32_t max);
|
||||
static float next_float(void);
|
||||
static float next_float_max(float max);
|
||||
static float next_float_minmax(float min, float max);
|
||||
|
||||
/**
|
||||
* Xorshift32 PRNG core. Advances the global seed and returns the new value.
|
||||
*
|
||||
* @return pseudo-random 32-bit integer
|
||||
*/
|
||||
static uint32_t xorshift32(void)
|
||||
{
|
||||
seed ^= seed<<13;
|
||||
seed ^= seed>>17;
|
||||
seed ^= seed<<5;
|
||||
return seed;
|
||||
}
|
||||
/**
|
||||
* Seed the global PRNG state. Zero is ignored (caller should pass a non-zero
|
||||
* seed). Runs the generator once after seeding to mix the state.
|
||||
*
|
||||
* @param _seed non-zero 32-bit seed value
|
||||
*/
|
||||
static void rand_seed(uint32_t _seed)
|
||||
{
|
||||
if(_seed == 0)
|
||||
return;
|
||||
|
||||
seed = _seed;
|
||||
xorshift32();
|
||||
}
|
||||
/**
|
||||
* Return a random integer in [0, UINT32_MAX].
|
||||
*
|
||||
* @return pseudo-random 32-bit integer
|
||||
*/
|
||||
static uint32_t next_int(void)
|
||||
{
|
||||
return xorshift32();
|
||||
}
|
||||
/**
|
||||
* Return a random integer in [0, max].
|
||||
*
|
||||
* @param max inclusive upper bound
|
||||
* @return pseudo-random integer
|
||||
*/
|
||||
static uint32_t next_int_max(uint32_t max)
|
||||
{
|
||||
return (uint32_t) floorf(xorshift32() / (float) UINT32_MAX * max);
|
||||
}
|
||||
/**
|
||||
* Return a random integer in [min, max].
|
||||
*
|
||||
* @param min inclusive lower bound
|
||||
* @param max inclusive upper bound
|
||||
* @return pseudo-random integer
|
||||
*/
|
||||
static uint32_t next_int_minmax(uint32_t min, uint32_t max)
|
||||
{
|
||||
const float x = (float) xorshift32() / UINT32_MAX;
|
||||
//(1.0f - Time) * A + Time * B
|
||||
return (1.0f - x) * min + x * max;
|
||||
}
|
||||
/**
|
||||
* Return a random float in [0, 1].
|
||||
*
|
||||
* @return pseudo-random float
|
||||
*/
|
||||
static float next_float(void)
|
||||
{
|
||||
return (float) xorshift32() / UINT32_MAX;
|
||||
}
|
||||
/**
|
||||
* Return a random float in [0, max].
|
||||
*
|
||||
* @param max inclusive upper bound
|
||||
* @return pseudo-random float
|
||||
*/
|
||||
static float next_float_max(float max)
|
||||
{
|
||||
return (float) xorshift32() / UINT32_MAX * max;
|
||||
}
|
||||
/**
|
||||
* Return a random float in [min, max].
|
||||
*
|
||||
* @param min inclusive lower bound
|
||||
* @param max inclusive upper bound
|
||||
* @return pseudo-random float
|
||||
*/
|
||||
static float next_float_minmax(float min, float max)
|
||||
{
|
||||
const float x = (float) xorshift32() / UINT32_MAX;
|
||||
return (1.0f - x) * min + x * max;
|
||||
}
|
||||
|
||||
#endif
|
||||
235
src/shaders/compute.wgsl
Normal file
235
src/shaders/compute.wgsl
Normal file
@@ -0,0 +1,235 @@
|
||||
struct Segment {
|
||||
p0: vec2f,
|
||||
p1: vec2f,
|
||||
p2: vec2f,
|
||||
p3: vec2f,
|
||||
}
|
||||
struct ShapeMeta {
|
||||
start_segment: u32, //Offset in the segments buffer
|
||||
segment_count: u32,
|
||||
bbox_min: vec2f,
|
||||
bbox_max: vec2f,
|
||||
}
|
||||
struct Circle {
|
||||
center: vec2f,
|
||||
radius: f32,
|
||||
}
|
||||
struct Tile {
|
||||
world_min: vec2f,
|
||||
world_max: vec2f,
|
||||
offset: u32,
|
||||
circle_count: u32,
|
||||
count: u32,
|
||||
};
|
||||
|
||||
@group(1) @binding(0) var<storage> segments: array<Segment>;
|
||||
@group(1) @binding(1) var<storage> shapes: array<ShapeMeta>;
|
||||
@group(1) @binding(2) var<storage> circles: array<Circle>;
|
||||
@group(1) @binding(3) var<storage> tiles: array<Tile>;
|
||||
@group(1) @binding(4) var<storage> indices: array<u32>;
|
||||
@group(1) @binding(5) var sdf_buffer: texture_storage_2d<r16float, write>;
|
||||
|
||||
override TILE_SIZE: u32 = 256u;
|
||||
|
||||
// ---------- Cubic Bézier helpers ----------
|
||||
fn eval_cubic(t: f32, p0: vec2f, p1: vec2f, p2: vec2f, p3: vec2f) -> vec2f {
|
||||
let mt = 1.0 - t;
|
||||
let mt2 = mt * mt;
|
||||
let t2 = t * t;
|
||||
return mt2 * mt * p0 + 3.0 * mt2 * t * p1 + 3.0 * mt * t2 * p2 + t2 * t * p3;
|
||||
}
|
||||
|
||||
fn eval_cubic_derivative(t: f32, p0: vec2f, p1: vec2f, p2: vec2f, p3: vec2f) -> vec2f {
|
||||
let mt = 1.0 - t;
|
||||
return 3.0 * mt * mt * (p1 - p0) + 6.0 * mt * t * (p2 - p1) + 3.0 * t * t * (p3 - p2);
|
||||
}
|
||||
|
||||
// ---------- Distance to a cubic Bézier (sampling + Newton refinement) ----------
|
||||
fn distance_to_cubic(p: vec2f, seg: Segment) -> f32 {
|
||||
let p0 = seg.p0; let p1 = seg.p1; let p2 = seg.p2; let p3 = seg.p3;
|
||||
|
||||
// Uniform sampling to find a good starting t
|
||||
let samples = 16u;
|
||||
var best_t = 0.0;
|
||||
var best_dist = 1e20;
|
||||
for (var i = 0u; i < samples; i++) {
|
||||
let t = f32(i) / f32(samples - 1u);
|
||||
let q = eval_cubic(t, p0, p1, p2, p3);
|
||||
let d = distance(p, q);
|
||||
if d < best_dist {
|
||||
best_dist = d;
|
||||
best_t = t;
|
||||
}
|
||||
}
|
||||
|
||||
// Newton refinement on the squared distance (max 4 iterations)
|
||||
var t = clamp(best_t, 0.0, 1.0);
|
||||
for (var iter = 0u; iter < 4u; iter++) {
|
||||
let B = eval_cubic(t, p0, p1, p2, p3) - p;
|
||||
let Bp = eval_cubic_derivative(t, p0, p1, p2, p3);
|
||||
let f = dot(B, Bp); // ½ derivative of |B|²
|
||||
let df = dot(Bp, Bp) + dot(B, 3.0 * (p2 - p1 + (p3 - p2 - p2 + p1) * 2.0 * t)); // simplified 2nd deriv
|
||||
if abs(df) < 1e-12 { break; }
|
||||
let step = f / df;
|
||||
t = clamp(t - step, 0.0, 1.0);
|
||||
if abs(step) < 1e-6 { break; }
|
||||
}
|
||||
let q_final = eval_cubic(t, p0, p1, p2, p3);
|
||||
return distance(p, q_final);
|
||||
}
|
||||
|
||||
// ---------- Analytical cubic root solver (for y-crossing) ----------
|
||||
// Returns number of real roots in [0,1], stored in roots array (up to 3).
|
||||
fn solve_cubic_in_01(c3: f32, c2: f32, c1: f32, c0: f32, roots: ptr<function, array<f32, 3>>) -> u32 {
|
||||
// Normalise: c3 * t^3 + c2 * t^2 + c1 * t + c0 = 0
|
||||
if abs(c3) < 1e-9 {
|
||||
// Quadratic fallback
|
||||
if abs(c2) < 1e-9 {
|
||||
if abs(c1) < 1e-9 { return 0u; }
|
||||
let t = -c0 / c1;
|
||||
if t >= 0.0 && t <= 1.0 {
|
||||
(*roots)[0] = t;
|
||||
return 1u;
|
||||
}
|
||||
return 0u;
|
||||
}
|
||||
let disc = c1 * c1 - 4.0 * c2 * c0;
|
||||
if disc < 0.0 { return 0u; }
|
||||
let sd = sqrt(disc);
|
||||
let t0 = (-c1 + sd) / (2.0 * c2);
|
||||
let t1 = (-c1 - sd) / (2.0 * c2);
|
||||
var count = 0u;
|
||||
if t0 >= 0.0 && t0 <= 1.0 { (*roots)[count] = t0; count++; }
|
||||
if t1 >= 0.0 && t1 <= 1.0 { (*roots)[count] = t1; count++; }
|
||||
return count;
|
||||
}
|
||||
|
||||
// Depressed cubic: let t = x - c2/(3*c3)
|
||||
let a = c2 / c3;
|
||||
let b = c1 / c3;
|
||||
let c = c0 / c3;
|
||||
let p = b - a * a / 3.0;
|
||||
let q = 2.0 * a * a * a / 27.0 - a * b / 3.0 + c;
|
||||
let disc = q * q / 4.0 + p * p * p / 27.0;
|
||||
|
||||
var count = 0u;
|
||||
let shift = a / 3.0;
|
||||
|
||||
if disc > 0.0 {
|
||||
let sd = sqrt(disc);
|
||||
let u = sign(-q/2.0 + sd) * pow(abs(-q/2.0 + sd), 1.0/3.0);
|
||||
let v = sign(-q/2.0 - sd) * pow(abs(-q/2.0 - sd), 1.0/3.0);
|
||||
let x1 = u + v;
|
||||
let t = x1 - shift;
|
||||
if t >= 0.0 && t <= 1.0 { (*roots)[count] = t; count++; }
|
||||
} else if disc == 0.0 {
|
||||
let u = sign(-q/2.0) * pow(abs(-q/2.0), 1.0/3.0);
|
||||
let x1 = 2.0 * u;
|
||||
let x2 = -u;
|
||||
let t1 = x1 - shift;
|
||||
let t2 = x2 - shift;
|
||||
if t1 >= 0.0 && t1 <= 1.0 { (*roots)[count] = t1; count++; }
|
||||
if t2 >= 0.0 && t2 <= 1.0 { (*roots)[count] = t2; count++; }
|
||||
} else {
|
||||
let phi = acos( -q / (2.0 * sqrt(-p*p*p/27.0)) );
|
||||
let r = 2.0 * sqrt(-p/3.0);
|
||||
for (var k = 0u; k < 3u; k++) {
|
||||
let x = r * cos((phi + 2.0 * 3.1415926535 * f32(k)) / 3.0);
|
||||
let t = x - shift;
|
||||
if t >= 0.0 && t <= 1.0 { (*roots)[count] = t; count++; }
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// ---------- Winding number contribution from one cubic segment ----------
|
||||
fn ray_intersections_cubic(p: vec2f, seg: Segment) -> i32 {
|
||||
// We cast a horizontal ray from p to +x; find t where y(t) = p.y
|
||||
let y0 = seg.p0.y - p.y;
|
||||
let y1 = seg.p1.y - p.y;
|
||||
let y2 = seg.p2.y - p.y;
|
||||
let y3 = seg.p3.y - p.y;
|
||||
|
||||
// y(t) = (1-t)^3*y0 + 3(1-t)^2 t * y1 + 3(1-t) t^2 * y2 + t^3 * y3 = 0
|
||||
// Expand polynomial: c3 t^3 + c2 t^2 + c1 t + c0
|
||||
let c0 = y0;
|
||||
let c1 = 3.0 * (y1 - y0);
|
||||
let c2 = 3.0 * (y2 - 2.0 * y1 + y0);
|
||||
let c3 = y3 - 3.0 * y2 + 3.0 * y1 - y0;
|
||||
|
||||
var roots: array<f32, 3>;
|
||||
let num = solve_cubic_in_01(c3, c2, c1, c0, &roots);
|
||||
var wind = 0i;
|
||||
for (var i = 0u; i < num; i++) {
|
||||
let t = roots[i];
|
||||
let x = eval_cubic(t, seg.p0, seg.p1, seg.p2, seg.p3).x;
|
||||
if x > p.x {
|
||||
let dy = eval_cubic_derivative(t, seg.p0, seg.p1, seg.p2, seg.p3).y;
|
||||
if dy > 0.0 { wind += 1i; }
|
||||
else if dy < 0.0 { wind -= 1i; }
|
||||
}
|
||||
}
|
||||
return wind;
|
||||
}
|
||||
|
||||
// ---------- Main compute shader ----------
|
||||
@compute @workgroup_size(8, 8)
|
||||
fn main(@builtin(workgroup_id) wg: vec3<u32>, // each workgroup is a tile
|
||||
@builtin(local_invocation_id) local: vec3<u32>) // each local invocation is a pixel
|
||||
{
|
||||
let tile_idx = wg.x / 16u;
|
||||
let tile = tiles[tile_idx];
|
||||
|
||||
let px = (wg.x % 16u) * 8u + local.x;
|
||||
let py = wg.y * 8u + local.y;
|
||||
|
||||
if (px >= TILE_SIZE || py >= TILE_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
let uv = (vec2f(f32(px), f32(py)) + 0.5) / f32(TILE_SIZE);
|
||||
let world = mix(tile.world_min, tile.world_max, uv);
|
||||
|
||||
var minDist: f32 = 1e20;
|
||||
var sdf: f32 = 1e20;
|
||||
var winding: i32 = 0;
|
||||
|
||||
for (var s = 0u; s < tile.count; s++) {
|
||||
// Use a pre-culled shape range per tile to reduce the per-pixel processing time
|
||||
let index = indices[tile.offset + s];
|
||||
|
||||
// If the index is lower than the circle count, it mean we are processing circles
|
||||
if(index < tile.circle_count)
|
||||
{
|
||||
let c = circles[index];
|
||||
sdf = min(sdf, length(world - c.center) - c.radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
let shape = shapes[index];
|
||||
|
||||
/*let bbox_min = shape.bbox_min;
|
||||
let bbox_max = shape.bbox_max;
|
||||
let dx = max(bbox_min.x - world.x, max(0.0, world.x - bbox_max.x));
|
||||
let dy = max(bbox_min.y - world.y, max(0.0, world.y - bbox_max.y));
|
||||
let dist_to_box = sqrt(dx * dx + dy * dy);
|
||||
if dist_to_box >= minDist {
|
||||
continue;
|
||||
}*/
|
||||
|
||||
// Process all segments of the shape
|
||||
for (var i = shape.start_segment; i < shape.start_segment + shape.segment_count; i++) {
|
||||
let seg = segments[i];
|
||||
let d = distance_to_cubic(world, seg);
|
||||
minDist = min(minDist, d);
|
||||
|
||||
winding += ray_intersections_cubic(world, seg);
|
||||
}
|
||||
|
||||
let sign = select(1.0, -1.0, winding != 0i);
|
||||
sdf = min(sdf, sign * minDist);
|
||||
}
|
||||
}
|
||||
|
||||
textureStore(sdf_buffer, vec2(u32(world.x), u32(world.y)), vec4f(sdf, 0.0, 0.0, 1.0));
|
||||
}
|
||||
20
src/shaders/display.wgsl
Normal file
20
src/shaders/display.wgsl
Normal file
@@ -0,0 +1,20 @@
|
||||
struct Uniforms {
|
||||
time: u32,
|
||||
frame: u32,
|
||||
mvp: mat4x4f,
|
||||
}
|
||||
|
||||
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
|
||||
|
||||
@group(1) @binding(0) var sdf : texture_2d<f32>;
|
||||
@group(1) @binding(1) var sdf_sampler : sampler;
|
||||
|
||||
@vertex fn vs_main(@location(0) position: vec2f) -> @builtin(position) vec4f
|
||||
{
|
||||
return vec4f(position, 0.0, 1.0) * uniforms.mvp;
|
||||
}
|
||||
|
||||
@fragment fn fs_main(@builtin(position) position: vec4f) -> @location(0) vec4f
|
||||
{
|
||||
return textureSample(sdf, sdf_sampler, position.xy);
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
struct VsUniform {
|
||||
mvp: mat4x4f,
|
||||
};
|
||||
|
||||
struct ShapeUniform {
|
||||
transform: mat4x4f,
|
||||
base_color: vec4f,
|
||||
state: u32,
|
||||
};
|
||||
|
||||
struct VsIn {
|
||||
@location(0) position: vec2f,
|
||||
};
|
||||
|
||||
struct Vs2Fs {
|
||||
@builtin(position) pos: vec4f,
|
||||
@location(0) @interpolate(linear) color: vec4f,
|
||||
};
|
||||
|
||||
struct FsOut {
|
||||
@location(0) color: vec4f,
|
||||
};
|
||||
|
||||
@binding(0) @group(0) var<uniform> vs_uniforms: VsUniform;
|
||||
@binding(1) @group(0) var<uniform> shape_uniform: ShapeUniform;
|
||||
|
||||
@vertex fn vs_main(input: VsIn) -> Vs2Fs {
|
||||
var output: Vs2Fs;
|
||||
let world_pos = vec4f(input.position.x, input.position.y, 0.0, 1.0) * shape_uniform.transform;
|
||||
output.pos = world_pos * vs_uniforms.mvp;
|
||||
if (shape_uniform.state == 2u) {
|
||||
output.color = vec4f(1.0, 0.84, 0.0, 1.0);
|
||||
} else if (shape_uniform.state == 1u) {
|
||||
output.color = clamp(shape_uniform.base_color * 1.5, vec4f(0.0), vec4f(1.0));
|
||||
} else {
|
||||
output.color = shape_uniform.base_color;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@fragment fn fs_main(input: Vs2Fs) -> FsOut {
|
||||
var output: FsOut;
|
||||
output.color = input.color;
|
||||
return output;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
struct Sprite {
|
||||
matrix: mat4x4f,
|
||||
};
|
||||
struct VsUniform {
|
||||
mvp: mat4x4f,
|
||||
};
|
||||
struct VsI { //Vertex shader input
|
||||
@builtin(instance_index) instance: u32,
|
||||
@location(0) position: vec2f,
|
||||
@location(1) uv: vec2f,
|
||||
};
|
||||
struct Vs2Fs { //Vertex shader to Fragment shader
|
||||
@builtin(position) pos: vec4f,
|
||||
@location(0) @interpolate(linear) uv: vec2f,
|
||||
};
|
||||
struct FsO { //Fragment shader output
|
||||
@location(0) color: vec4f,
|
||||
};
|
||||
|
||||
@binding(0) @group(0) var<uniform> vs_uniforms: VsUniform;
|
||||
@binding(0) @group(1) var tex: texture_2d<f32>;
|
||||
@binding(1) @group(1) var samp: sampler;
|
||||
@binding(2) @group(1) var<storage> sprites: array<Sprite>;
|
||||
|
||||
@vertex fn vs_main(input: VsI) -> Vs2Fs {
|
||||
var output: Vs2Fs;
|
||||
|
||||
output.pos = vec4f(input.position.x, input.position.y, 0, 0) * sprites[input.instance].matrix * vs_uniforms.mvp;
|
||||
output.uv = input.uv;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// Convert a 32bit uint color (hex representation) into a normalized vec4f
|
||||
/*fn convertColor(input: u32) -> vec4f {
|
||||
let r: f32 = f32(((input >> 0) & 0xff));
|
||||
let g: f32 = f32(((input >> 8) & 0xff));
|
||||
let b: f32 = f32(((input >> 16) & 0xff));
|
||||
let a: f32 = f32(((input >> 24) & 0xff));
|
||||
|
||||
return vec4f(r / 255, g / 255, b / 255, a / 255);
|
||||
}*/
|
||||
// Get the texture array index from the UV
|
||||
/*fn indexFromCoord(uv: vec2f, width: u32, height: u32) -> u32 {
|
||||
let x: u32 = clamp(floor(uv.x * f32(width)), 0, width);
|
||||
let y: u32 = clamp(floor(uv.y * f32(height)), 0, height);
|
||||
return y * width + x;
|
||||
}*/
|
||||
|
||||
@fragment fn fs_main(input: Vs2Fs) -> FsO {
|
||||
var output: FsO;
|
||||
|
||||
output.color = textureSample(tex, samp, input.uv);
|
||||
|
||||
return output;
|
||||
}
|
||||
720
src/shape.h
720
src/shape.h
@@ -1,433 +1,363 @@
|
||||
#ifndef SHAPE_H
|
||||
#define SHAPE_H
|
||||
|
||||
#include "api.h"
|
||||
|
||||
typedef struct shape_vertex_t {
|
||||
float x, y;
|
||||
} shape_vertex_t;
|
||||
typedef struct uvec2 { uint32_t x, y; } uvec2;
|
||||
typedef struct vec2 { float x, y; } vec2;
|
||||
|
||||
typedef struct shape_uniform_t {
|
||||
mat4 transform;
|
||||
float base_color[4];
|
||||
uint32_t state;
|
||||
uint8_t _pad[12];
|
||||
} shape_uniform_t;
|
||||
typedef struct ubox_t {
|
||||
uint32_t min_x, min_y, max_x, max_y;
|
||||
} ubox_t;
|
||||
typedef struct box_t {
|
||||
float min_x, min_y, max_x, max_y;
|
||||
} box_t;
|
||||
|
||||
typedef enum shape_kind_t {
|
||||
SHAPE_CIRCLE,
|
||||
SHAPE_STAR,
|
||||
} shape_kind_t;
|
||||
#define BOX_INTERSECTS(a, b) !(b.min_x > a.max_x \
|
||||
|| b.max_x < a.min_x \
|
||||
|| b.min_y > a.max_y \
|
||||
|| b.max_y < a.min_y)
|
||||
|
||||
typedef struct shape_t {
|
||||
shape_vertex_t *verts;
|
||||
uint16_t *indices;
|
||||
#define CIRCLE_INTERSECTS(box, circle) !(circle.center.x - circle.radius > box.max_x \
|
||||
|| circle.center.x + circle.radius < box.min_x \
|
||||
|| circle.center.y - circle.radius > box.max_y \
|
||||
|| circle.center.y + circle.radius < box.min_y)
|
||||
|
||||
typedef struct segment_t {
|
||||
vec2 p0, p1, p2, p3; // cubic Bézier: start, control1, control2, end
|
||||
} segment_t;
|
||||
|
||||
typedef struct shape_meta_t {
|
||||
uint32_t start_segment; // index into global segments array
|
||||
uint32_t segment_count; // number of segments forming this closed loop
|
||||
box_t aabb;
|
||||
} shape_meta_t;
|
||||
|
||||
typedef struct circle_t {
|
||||
vec2 center;
|
||||
float radius;
|
||||
} circle_t;
|
||||
|
||||
#define TILE_SIZE 256 // texels per tile
|
||||
|
||||
#define TILE_COUNT(size) (uint32_t)ceilf(size.x / TILE_SIZE) * (uint32_t)ceilf(size.y / TILE_SIZE)
|
||||
|
||||
#define INITIAL_SHAPE_SIZE 256
|
||||
#define INITIAL_SEGMENTS_SIZE 8192
|
||||
#define INITIAL_CIRCLE_SIZE 1024
|
||||
#define INITIAL_INDICES_SIZE 16384
|
||||
|
||||
// Tile metadata for targetted updates
|
||||
typedef struct tile_task_t {
|
||||
box_t bounds;
|
||||
uint32_t offset;
|
||||
uint32_t circle_count;
|
||||
uint32_t count;
|
||||
} tile_task_t;
|
||||
|
||||
typedef struct scene_t {
|
||||
vec2 world_size;
|
||||
|
||||
struct {
|
||||
uint32_t num_shapes;
|
||||
uint32_t max_shapes;
|
||||
shape_meta_t* shapes;
|
||||
|
||||
uint32_t num_segments;
|
||||
uint32_t max_segments;
|
||||
segment_t* segments;
|
||||
} shapes;
|
||||
|
||||
struct {
|
||||
uint32_t num_circles;
|
||||
uint32_t max_circles;
|
||||
circle_t* circles;
|
||||
} circles;
|
||||
|
||||
struct {
|
||||
tile_task_t* tiles; // Array of tiles metadata for the compute buffer
|
||||
bool* tile_dirty; // Array of tiles state, since this info don't needs to be uploaded to the GPU, it is stored separately
|
||||
|
||||
uint32_t max_indices;
|
||||
uint32_t num_indices;
|
||||
uint32_t num_verts;
|
||||
sg_buffer vbuf;
|
||||
sg_buffer ibuf;
|
||||
shape_uniform_t uniform;
|
||||
bool hovered;
|
||||
bool selected;
|
||||
uint32_t* indices; // Array of shapes/circles indices per tile, pre culled on the CPU side
|
||||
} cache;
|
||||
|
||||
shape_kind_t kind;
|
||||
float cx, cy;
|
||||
float sx, sy;
|
||||
float rotation;
|
||||
int star_points;
|
||||
float star_inner_ratio;
|
||||
int last_update_frame;
|
||||
} shape_t;
|
||||
sg_view texture; //Layer count depends on the world size so the texture has to be allocate on the scene side
|
||||
|
||||
#define SHAPE_HOVER_PX 6.0f
|
||||
bool shape_dirty, segment_dirty, circle_dirty;
|
||||
} scene_t;
|
||||
|
||||
static sg_pipeline shape_pipeline;
|
||||
static sg_pipeline overlay_pipeline;
|
||||
static sg_shader shape_shader;
|
||||
static int g_shape_frame_id;
|
||||
// Initialise a scene_t with a given capacity for shapes and segments.
|
||||
static uint32_t scene_init(scene_t* s, vec2 world_size) {
|
||||
s->shapes.num_shapes = 0;
|
||||
s->shapes.max_shapes = INITIAL_SHAPE_SIZE;
|
||||
s->shapes.shapes = (shape_meta_t*) emmalloc_malloc(INITIAL_SHAPE_SIZE * sizeof(shape_meta_t));
|
||||
|
||||
static void shape_begin_frame(void)
|
||||
{
|
||||
g_shape_frame_id++;
|
||||
}
|
||||
s->shapes.num_segments = 0;
|
||||
s->shapes.max_segments = INITIAL_SEGMENTS_SIZE;
|
||||
s->shapes.segments = (segment_t*) emmalloc_malloc(INITIAL_SEGMENTS_SIZE * sizeof(segment_t));
|
||||
|
||||
/**
|
||||
* Create the shape shader, shape pipeline (line strip), and overlay pipeline
|
||||
* (triangles). Call once during app init before drawing any shapes.
|
||||
*/
|
||||
static void shape_init_pipeline(void)
|
||||
{
|
||||
shape_shader = sg_make_shader(&(sg_shader_desc) {
|
||||
.vertex_func = {
|
||||
.source = (const char*) src_shaders_shape_wgsl,
|
||||
.entry = "vs_main",
|
||||
s->circles.num_circles = 0;
|
||||
s->circles.max_circles = INITIAL_SEGMENTS_SIZE;
|
||||
s->circles.circles = (circle_t*) emmalloc_malloc(INITIAL_CIRCLE_SIZE * sizeof(circle_t));
|
||||
|
||||
const uint32_t tile_count_x = (uint32_t)ceilf(world_size.x / TILE_SIZE), tile_count_y = (uint32_t)ceilf(world_size.y / TILE_SIZE);
|
||||
const uint32_t tile_count = tile_count_x * tile_count_y;
|
||||
s->cache.tiles = (tile_task_t*) emmalloc_malloc(sizeof(tile_task_t) * tile_count);
|
||||
s->cache.tile_dirty = (bool*) emmalloc_malloc(sizeof(bool) * tile_count);
|
||||
|
||||
uint32_t idx = 0;
|
||||
for(uint32_t y = 0; y < tile_count_y; y++)
|
||||
{
|
||||
for(uint32_t x = 0; x < tile_count_x; x++)
|
||||
{
|
||||
s->cache.tile_dirty[idx] = true;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
s->cache.max_indices = INITIAL_INDICES_SIZE;
|
||||
s->cache.num_indices = 0;
|
||||
s->cache.indices = (uint32_t*) emmalloc_malloc(sizeof(uint32_t) * INITIAL_INDICES_SIZE);
|
||||
|
||||
s->world_size = world_size;
|
||||
s->texture = sg_make_view(&(sg_view_desc) {
|
||||
.label = "SDF tiles view",
|
||||
.storage_image = {
|
||||
.image = sg_make_image(&(sg_image_desc) {
|
||||
.width = (uint32_t) ceilf(world_size.x),
|
||||
.height = (uint32_t) ceilf(world_size.y),
|
||||
.label = "SDF tiles texture",
|
||||
.pixel_format = SG_PIXELFORMAT_R16F,
|
||||
.type = SG_IMAGETYPE_2D,
|
||||
.usage = { .storage_image = true },
|
||||
}),
|
||||
},
|
||||
.fragment_func = {
|
||||
.source = (const char*) src_shaders_shape_wgsl,
|
||||
.entry = "fs_main",
|
||||
},
|
||||
.uniform_blocks = {
|
||||
[0] = {
|
||||
.size = sizeof(mat4),
|
||||
.stage = SG_SHADERSTAGE_VERTEX,
|
||||
.wgsl_group0_binding_n = 0,
|
||||
},
|
||||
[1] = {
|
||||
.size = sizeof(shape_uniform_t),
|
||||
.stage = SG_SHADERSTAGE_VERTEX,
|
||||
.wgsl_group0_binding_n = 1,
|
||||
},
|
||||
},
|
||||
.attrs = {
|
||||
[0] = { .base_type = SG_SHADERATTRBASETYPE_FLOAT },
|
||||
},
|
||||
.label = "Shape shader",
|
||||
});
|
||||
|
||||
shape_pipeline = sg_make_pipeline(&(sg_pipeline_desc) {
|
||||
.shader = shape_shader,
|
||||
.index_type = SG_INDEXTYPE_UINT16,
|
||||
.primitive_type = SG_PRIMITIVETYPE_LINE_STRIP,
|
||||
.layout.attrs = {
|
||||
[0].format = SG_VERTEXFORMAT_FLOAT2,
|
||||
},
|
||||
.label = "Shape pipeline",
|
||||
});
|
||||
|
||||
overlay_pipeline = sg_make_pipeline(&(sg_pipeline_desc) {
|
||||
.shader = shape_shader,
|
||||
.index_type = SG_INDEXTYPE_UINT16,
|
||||
.primitive_type = SG_PRIMITIVETYPE_TRIANGLES,
|
||||
.layout.attrs = {
|
||||
[0].format = SG_VERTEXFORMAT_FLOAT2,
|
||||
},
|
||||
.label = "Overlay pipeline",
|
||||
});
|
||||
if (!s->shapes.shapes || !s->shapes.segments || !s->circles.circles || !s->cache.indices || !s->cache.tiles || !s->cache.tile_dirty) return 0; // allocation failure
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the shape shader and both pipelines. Call during app shutdown.
|
||||
*/
|
||||
static void shape_shutdown_pipeline(void)
|
||||
{
|
||||
sg_destroy_pipeline(shape_pipeline);
|
||||
sg_destroy_pipeline(overlay_pipeline);
|
||||
sg_destroy_shader(shape_shader);
|
||||
}
|
||||
#define COORD_TO_INDEX(x, y, scene) y * ceilf(s->world_size.x / TILE_SIZE) + x
|
||||
|
||||
/**
|
||||
* Return the number of line segments for a circle of the given radius.
|
||||
* Clamped to [8, 128]; scales roughly with circumference.
|
||||
*
|
||||
* @param r circle radius in world units
|
||||
* @return segment count
|
||||
*/
|
||||
static int shape_calc_segments(float r)
|
||||
static void scene_compute_culling(scene_t* s, tile_task_t* task)
|
||||
{
|
||||
int n = (int)(fabsf(r) * 0.5f) + 16;
|
||||
if (n < 8) n = 8;
|
||||
if (n > 128) n = 128;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default state for a newly created shape: identity transform, base color,
|
||||
* not hovered, not selected.
|
||||
*
|
||||
* @param s shape to initialize
|
||||
* @param color RGBA base color (copied)
|
||||
*/
|
||||
static void shape_init_common(shape_t *s, const float color[4])
|
||||
{
|
||||
s->hovered = false;
|
||||
s->selected = false;
|
||||
memcpy(s->uniform.base_color, color, sizeof(float[4]));
|
||||
s->uniform.state = 0;
|
||||
memset(s->uniform._pad, 0, sizeof(s->uniform._pad));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the per-shape transform matrix from cx, cy, rotation.
|
||||
* Uses R(-angle) so the shader's row-vector convention matches the existing
|
||||
* world-space vertex computation.
|
||||
*/
|
||||
static void shape_build_transform(shape_t *s)
|
||||
{
|
||||
mat4 T, R, S, RS;
|
||||
glm_translate_make(T, (vec3){s->cx, s->cy, 0.0f});
|
||||
glm_rotate_make(R, -s->rotation, (vec3){0.0f, 0.0f, 1.0f});
|
||||
glm_scale_make(S, (vec3){s->sx, s->sy, 1.0f});
|
||||
glm_mat4_mul(R, S, RS);
|
||||
glm_mat4_mul(T, RS, s->uniform.transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create GPU vertex and index buffers from the shape's current verts/indices.
|
||||
*
|
||||
* @param s shape (must have verts and indices allocated)
|
||||
*/
|
||||
static void shape_make_buffers(shape_t *s)
|
||||
{
|
||||
s->vbuf = sg_make_buffer(&(sg_buffer_desc) {
|
||||
.size = s->num_indices * sizeof(shape_vertex_t),
|
||||
.usage = { .stream_update = true },
|
||||
.label = "Shape vertices",
|
||||
});
|
||||
sg_update_buffer(s->vbuf, &(sg_range){s->verts, s->num_indices * sizeof(shape_vertex_t)});
|
||||
s->ibuf = sg_make_buffer(&(sg_buffer_desc) {
|
||||
.usage = { .index_buffer = true },
|
||||
.data = { s->indices, s->num_indices * sizeof(uint16_t) },
|
||||
.label = "Shape indices",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy GPU buffers and free vertex/index arrays for a single shape.
|
||||
*
|
||||
* @param s shape to tear down
|
||||
*/
|
||||
static void shape_shutdown(shape_t *s)
|
||||
{
|
||||
sg_destroy_buffer(s->vbuf);
|
||||
sg_destroy_buffer(s->ibuf);
|
||||
FREE(s->verts);
|
||||
FREE(s->indices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild vertex and index data from the shape's current parameters (position,
|
||||
* scale, rotation, kind), then recreate GPU buffers. Call after any parameter
|
||||
* change.
|
||||
*
|
||||
* @param s shape to regenerate
|
||||
*/
|
||||
static void shape_regenerate(shape_t *s)
|
||||
{
|
||||
int n, count;
|
||||
if (s->kind == SHAPE_CIRCLE) {
|
||||
int segs = shape_calc_segments(s->sx);
|
||||
n = segs;
|
||||
count = segs + 1;
|
||||
} else {
|
||||
n = s->star_points * 2;
|
||||
count = n + 1;
|
||||
task->count = 0;
|
||||
for(uint32_t i = 0; i < s->circles.num_circles; i++)
|
||||
{
|
||||
if(CIRCLE_INTERSECTS(task->bounds, s->circles.circles[i]))
|
||||
{
|
||||
if(s->cache.num_indices >= s->cache.max_indices)
|
||||
{
|
||||
s->cache.max_indices *= 2;
|
||||
s->cache.indices = emmalloc_realloc(s->cache.indices, s->cache.max_indices * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
bool resized = ((uint32_t)count != s->num_indices);
|
||||
if (resized) {
|
||||
sg_destroy_buffer(s->vbuf);
|
||||
sg_destroy_buffer(s->ibuf);
|
||||
FREE(s->verts);
|
||||
FREE(s->indices);
|
||||
s->verts = (shape_vertex_t*) ALLOC(count * sizeof(shape_vertex_t));
|
||||
s->indices = (uint16_t*) ALLOC(count * sizeof(uint16_t));
|
||||
s->cache.indices[s->cache.num_indices++] = i;
|
||||
task->count++;
|
||||
}
|
||||
|
||||
if (s->kind == SHAPE_CIRCLE) {
|
||||
int segs = n;
|
||||
for (int i = 0; i < segs; i++) {
|
||||
float a = (float)i / (float)segs * 2.0f * GLM_PIf - GLM_PI_2f;
|
||||
s->verts[i] = (shape_vertex_t) { cosf(a), sinf(a) };
|
||||
}
|
||||
s->verts[segs] = s->verts[0];
|
||||
} else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
float a = (float)i / (float)n * 2.0f * GLM_PIf - GLM_PI_2f;
|
||||
float r = (i & 1) ? s->star_inner_ratio : 1.0f;
|
||||
s->verts[i] = (shape_vertex_t) { cosf(a) * r, sinf(a) * r };
|
||||
task->circle_count = task->count;
|
||||
for(uint32_t i = 0; i < s->shapes.num_shapes; i++)
|
||||
{
|
||||
if(BOX_INTERSECTS(task->bounds, s->shapes.shapes[i].aabb))
|
||||
{
|
||||
if(s->cache.num_indices >= s->cache.max_indices)
|
||||
{
|
||||
s->cache.max_indices *= 2;
|
||||
s->cache.indices = emmalloc_realloc(s->cache.indices, s->cache.max_indices * sizeof(uint32_t));
|
||||
}
|
||||
s->verts[n] = s->verts[0];
|
||||
s->cache.indices[s->cache.num_indices++] = i;
|
||||
task->count++;
|
||||
}
|
||||
|
||||
s->num_indices = (uint32_t)count;
|
||||
s->num_verts = (uint32_t)n;
|
||||
for (int i = 0; i <= n; i++) s->indices[i] = (uint16_t)i;
|
||||
|
||||
shape_build_transform(s);
|
||||
|
||||
if (resized) {
|
||||
shape_make_buffers(s);
|
||||
s->last_update_frame = g_shape_frame_id;
|
||||
} else if (s->last_update_frame != g_shape_frame_id) {
|
||||
sg_update_buffer(s->vbuf, &(sg_range){s->verts, (size_t)count * sizeof(shape_vertex_t)});
|
||||
s->last_update_frame = g_shape_frame_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update hovered/selected flags and the shader uniform state.
|
||||
* State is 0=normal, 1=hovered (brightened), 2=selected (green).
|
||||
*
|
||||
* @param s shape to update
|
||||
* @param hovered true if cursor is over the shape
|
||||
* @param selected true if shape is in the selection set
|
||||
*/
|
||||
static void shape_set_state(shape_t *s, bool hovered, bool selected)
|
||||
// Find the proper LOD, the relevant tiles then run the culling process for the dirty tiles and upload data to the GPU for SDF rendering
|
||||
static uint32_t scene_process_tiles(scene_t* s, float pan_x, float pan_y, float zoom, sg_bindings* bindings)
|
||||
{
|
||||
s->hovered = hovered;
|
||||
s->selected = selected;
|
||||
s->uniform.state = selected ? 2u : (hovered ? 1u : 0u);
|
||||
}
|
||||
const float width = (float)sapp_width(), height = (float) sapp_height();
|
||||
const float wpp = fmaxf(s->world_size.y / zoom / height, s->world_size.x / zoom / width); //World point per pixel
|
||||
|
||||
/**
|
||||
* Ray-casting point-in-polygon test. Handles arbitrary non-self-intersecting
|
||||
* polygons.
|
||||
*
|
||||
* @param px point X in world space
|
||||
* @param py point Y in world space
|
||||
* @param verts polygon vertices
|
||||
* @param n vertex count
|
||||
* @return true if the point is inside the polygon
|
||||
*/
|
||||
static bool point_in_polygon(float px, float py, shape_vertex_t *verts, uint32_t n)
|
||||
{
|
||||
bool inside = false;
|
||||
for (uint32_t i = 0, j = n - 1; i < n; j = i++) {
|
||||
float xi = verts[i].x, yi = verts[i].y;
|
||||
float xj = verts[j].x, yj = verts[j].y;
|
||||
if ((yi > py) != (yj > py) && px < (xj - xi) * (py - yi) / (yj - yi) + xi)
|
||||
inside = !inside;
|
||||
float view_w = width * wpp, view_h = height * wpp;
|
||||
box_t frustum = {
|
||||
.min_x = ceilf((pan_x - view_w * 0.5) / TILE_SIZE),
|
||||
.min_y = ceilf((pan_y - view_h * 0.5) / TILE_SIZE),
|
||||
.max_x = ceilf((pan_x + view_w * 0.5) / TILE_SIZE),
|
||||
.max_y = ceilf((pan_y + view_h * 0.5) / TILE_SIZE)
|
||||
};
|
||||
|
||||
uint32_t dirty_tile_count = 0, offset = 0;
|
||||
for(uint32_t y = frustum.min_y; y < frustum.max_y; y++)
|
||||
{
|
||||
for(uint32_t x = frustum.min_x; x < frustum.max_x; x++)
|
||||
{
|
||||
uint32_t idx = COORD_TO_INDEX(x, y, s);
|
||||
if(s->cache.tile_dirty[idx])
|
||||
{
|
||||
tile_task_t* task = &s->cache.tiles[dirty_tile_count++];
|
||||
task->bounds.min_x = x * TILE_SIZE;
|
||||
task->bounds.min_y = y * TILE_SIZE;
|
||||
task->bounds.max_x = fminf((x + 1) * TILE_SIZE, s->world_size.x);
|
||||
task->bounds.max_y = fminf((y + 1) * TILE_SIZE, s->world_size.y);
|
||||
|
||||
task->offset = offset;
|
||||
scene_compute_culling(s, task);
|
||||
offset += task->count;
|
||||
|
||||
s->cache.tile_dirty[idx] = false;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a world-space point hits this shape. Transforms the query
|
||||
* to local space (verts are now stored relative to origin), then tests
|
||||
* polygon containment and edge proximity.
|
||||
*
|
||||
* @param s shape to test
|
||||
* @param wx point X in world space
|
||||
* @param wy point Y in world space
|
||||
* @param world_tol hit tolerance in world units
|
||||
* @return true if the point hits the shape
|
||||
*/
|
||||
static bool shape_hit_test(shape_t *s, float wx, float wy, float world_tol)
|
||||
{
|
||||
float sc = cosf(s->rotation), ss = sinf(s->rotation);
|
||||
float dx = wx - s->cx, dy = wy - s->cy;
|
||||
float lx = (dx * sc + dy * ss) / s->sx;
|
||||
float ly = (-dx * ss + dy * sc) / s->sy;
|
||||
float min_scale = fminf(fabsf(s->sx), fabsf(s->sy));
|
||||
float local_tol = world_tol / (min_scale > 0.0001f ? min_scale : 1.0f);
|
||||
float tol_sq = local_tol * local_tol;
|
||||
|
||||
if (point_in_polygon(lx, ly, s->verts, s->num_verts))
|
||||
return true;
|
||||
|
||||
for (uint32_t i = 0, j = s->num_verts - 1; i < s->num_verts; j = i++) {
|
||||
float ax = s->verts[i].x, ay = s->verts[i].y;
|
||||
float bx = s->verts[j].x, by = s->verts[j].y;
|
||||
float abx = bx - ax, aby = by - ay;
|
||||
float len_sq = abx * abx + aby * aby;
|
||||
if (len_sq < 0.0001f) continue;
|
||||
float t = ((lx - ax) * abx + (ly - ay) * aby) / len_sq;
|
||||
t = fmaxf(0.0f, fminf(1.0f, t));
|
||||
float cx = ax + t * abx, cy = ay + t * aby;
|
||||
float ddx = lx - cx, ddy = ly - cy;
|
||||
if (ddx * ddx + ddy * ddy <= tol_sq) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a draw call for this shape using the shape line-strip pipeline.
|
||||
*
|
||||
* @param s shape to draw
|
||||
* @param mvp model-view-projection matrix (from compute_mvp)
|
||||
*/
|
||||
static void shape_draw(shape_t *s, const mat4 *mvp)
|
||||
{
|
||||
sg_apply_uniforms(0, &SG_RANGE(*mvp));
|
||||
sg_apply_uniforms(1, &SG_RANGE(s->uniform));
|
||||
sg_apply_bindings(&(sg_bindings) {
|
||||
.vertex_buffers[0] = s->vbuf,
|
||||
.index_buffer = s->ibuf,
|
||||
});
|
||||
sg_draw(0, s->num_indices, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a circle shape (returned by value). Allocates verts/indices and GPU
|
||||
* buffers. The number of line segments adapts to radius.
|
||||
*
|
||||
* @param x center X in world space
|
||||
* @param y center Y in world space
|
||||
* @param r radius in world units
|
||||
* @param color RGBA base color
|
||||
* @return fully initialized shape_t
|
||||
*/
|
||||
static shape_t shape_circle(float x, float y, float r, const float color[4])
|
||||
{
|
||||
shape_t s;
|
||||
s.kind = SHAPE_CIRCLE;
|
||||
s.cx = x; s.cy = y;
|
||||
s.sx = r; s.sy = r;
|
||||
s.rotation = 0.0f;
|
||||
|
||||
int segs = shape_calc_segments(r);
|
||||
int count = segs + 1;
|
||||
s.verts = (shape_vertex_t*) ALLOC(count * sizeof(shape_vertex_t));
|
||||
s.indices = (uint16_t*) ALLOC(count * sizeof(uint16_t));
|
||||
|
||||
for (int i = 0; i < segs; i++) {
|
||||
float a = (float)i / (float)segs * 2.0f * GLM_PIf - GLM_PI_2f;
|
||||
s.verts[i] = (shape_vertex_t) { cosf(a), sinf(a) };
|
||||
}
|
||||
s.verts[segs] = s.verts[0];
|
||||
for (int i = 0; i <= segs; i++) s.indices[i] = (uint16_t)i;
|
||||
s.num_indices = (uint32_t)count;
|
||||
s.num_verts = (uint32_t)segs;
|
||||
|
||||
shape_init_common(&s, color);
|
||||
shape_build_transform(&s);
|
||||
shape_make_buffers(&s);
|
||||
return s;
|
||||
return dirty_tile_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a star shape (returned by value). Alternates between outer_r and
|
||||
* inner_r at each vertex, producing a star with the given number of points.
|
||||
* Allocates verts/indices and GPU buffers.
|
||||
*
|
||||
* @param x center X in world space
|
||||
* @param y center Y in world space
|
||||
* @param outer_r outer radius in world units
|
||||
* @param inner_r inner radius in world units
|
||||
* @param points number of star points
|
||||
* @param color RGBA base color
|
||||
* @return fully initialized shape_t
|
||||
*/
|
||||
static shape_t shape_star(float x, float y, float outer_r, float inner_r,
|
||||
int points, const float color[4])
|
||||
{
|
||||
shape_t s;
|
||||
s.kind = SHAPE_STAR;
|
||||
s.cx = x; s.cy = y;
|
||||
s.sx = outer_r; s.sy = outer_r;
|
||||
s.rotation = 0.0f;
|
||||
s.star_points = points;
|
||||
s.star_inner_ratio = inner_r / outer_r;
|
||||
|
||||
int n = points * 2;
|
||||
int count = n + 1;
|
||||
s.verts = (shape_vertex_t*) ALLOC(count * sizeof(shape_vertex_t));
|
||||
s.indices = (uint16_t*) ALLOC(count * sizeof(uint16_t));
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
float a = (float)i / (float)n * 2.0f * GLM_PIf - GLM_PI_2f;
|
||||
float r = (i & 1) ? s.star_inner_ratio : 1.0f;
|
||||
s.verts[i] = (shape_vertex_t) { cosf(a) * r, sinf(a) * r };
|
||||
// Append a segment, returns its index. (Reallocs if needed, simplified.)
|
||||
static uint32_t scene_add_segment(scene_t* s, segment_t seg) {
|
||||
if (s->shapes.num_segments >= s->shapes.max_segments) {
|
||||
int new_cap = s->shapes.max_segments * 2;
|
||||
segment_t* tmp = (segment_t*) realloc(s->shapes.segments, new_cap * sizeof(segment_t));
|
||||
if (!tmp) return -1;
|
||||
s->shapes.segments = tmp;
|
||||
s->shapes.max_segments = new_cap;
|
||||
}
|
||||
s.verts[n] = s.verts[0];
|
||||
for (int i = 0; i <= n; i++) s.indices[i] = (uint16_t)i;
|
||||
s.num_indices = (uint32_t)count;
|
||||
s.num_verts = (uint32_t)n;
|
||||
int idx = s->shapes.num_segments++;
|
||||
s->shapes.segments[idx] = seg;
|
||||
|
||||
shape_init_common(&s, color);
|
||||
shape_build_transform(&s);
|
||||
shape_make_buffers(&s);
|
||||
return s;
|
||||
return idx;
|
||||
}
|
||||
|
||||
#endif
|
||||
// Append a shape (meta data) and return its index.
|
||||
static uint32_t scene_add_shape(scene_t* s, shape_meta_t meta) {
|
||||
if (s->shapes.num_shapes >= s->shapes.max_shapes) {
|
||||
int new_cap = s->shapes.max_shapes * 2;
|
||||
shape_meta_t* tmp = (shape_meta_t*) emmalloc_realloc(s->shapes.shapes, new_cap * sizeof(shape_meta_t));
|
||||
if (!tmp) return -1;
|
||||
s->shapes.shapes = tmp;
|
||||
s->shapes.max_shapes = new_cap;
|
||||
}
|
||||
int idx = s->shapes.num_shapes++;
|
||||
s->shapes.shapes[idx] = meta;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static uint32_t scene_shutdown(scene_t* s) {
|
||||
emmalloc_free(s->shapes.segments);
|
||||
emmalloc_free(s->shapes.shapes);
|
||||
emmalloc_free(s->circles.circles);
|
||||
|
||||
emmalloc_free(s->cache.indices);
|
||||
emmalloc_free(s->cache.tiles);
|
||||
emmalloc_free(s->cache.tile_dirty);
|
||||
|
||||
emmalloc_free(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Compute axis-aligned bounding box for a set of segments (used after adding a shape).
|
||||
static void compute_bbox(segment_t* segs, uint32_t start, uint32_t count, float* minx, float* miny, float* maxx, float* maxy) {
|
||||
float mx = 1e30f, my = 1e30f, Mx = -1e30f, My = -1e30f;
|
||||
for (int i = 0; i < count; i++) {
|
||||
segment_t s = segs[start + i];
|
||||
float xs[4] = {s.p0.x, s.p1.x, s.p2.x, s.p3.x};
|
||||
float ys[4] = {s.p0.y, s.p1.y, s.p2.y, s.p3.y};
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (xs[j] < mx) mx = xs[j];
|
||||
if (xs[j] > Mx) Mx = xs[j];
|
||||
if (ys[j] < my) my = ys[j];
|
||||
if (ys[j] > My) My = ys[j];
|
||||
}
|
||||
}
|
||||
*minx = mx; *miny = my; *maxx = Mx; *maxy = My;
|
||||
}
|
||||
|
||||
// Add an axis‑aligned rectangle centred at `center` with given width and height.
|
||||
// Returns the shape index, or -1 on error.
|
||||
uint32_t add_rectangle(scene_t* s, vec2 center, vec2 size) {
|
||||
float hw = size.x * 0.5f, hh = size.y * 0.5f;
|
||||
vec2 corners[4] = {
|
||||
{center.x - hw, center.y - hh}, // bottom‑left
|
||||
{center.x + hw, center.y - hh}, // bottom‑right
|
||||
{center.x + hw, center.y + hh}, // top‑right
|
||||
{center.x - hw, center.y + hh} // top‑left
|
||||
};
|
||||
|
||||
// Four straight segments, control points = the corners themselves.
|
||||
segment_t segs[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int next = (i + 1) % 4;
|
||||
segs[i].p0 = corners[i];
|
||||
segs[i].p1 = corners[i]; // start = control1 → straight line
|
||||
segs[i].p2 = corners[next]; // control2 = end
|
||||
segs[i].p3 = corners[next];
|
||||
}
|
||||
|
||||
int start = scene_add_segment(s, segs[0]);
|
||||
if (start < 0) return -1;
|
||||
for (int i = 1; i < 4; i++)
|
||||
if (scene_add_segment(s, segs[i]) < 0) return -1;
|
||||
|
||||
shape_meta_t meta;
|
||||
meta.start_segment = start;
|
||||
meta.segment_count = 4;
|
||||
meta.aabb = (box_t) { center.x - hw, center.y - hh, center.x + hw, center.y + hh };
|
||||
return scene_add_shape(s, meta);
|
||||
}
|
||||
|
||||
// Add a circle centred at `center` with given radius.
|
||||
// approximated by 4 cubic Bézier segments (one per quadrant).
|
||||
// Returns shape index or -1.
|
||||
uint32_t add_circle_as_shape(scene_t* s, vec2 center, float radius) {
|
||||
const float k = 0.552284749831f; // magic constant for 90° arc (4/3 * (sqrt(2)-1))
|
||||
float rk = radius * k;
|
||||
|
||||
// Start at rightmost point (0°), moving counter‑clockwise.
|
||||
vec2 p0 = {center.x + radius, center.y};
|
||||
|
||||
// Quadrant 1 (0° to 90°): from right to top
|
||||
segment_t seg1;
|
||||
seg1.p0 = p0;
|
||||
seg1.p1 = (vec2) {p0.x, p0.y + rk};
|
||||
seg1.p2 = (vec2) {center.x + rk, center.y + radius};
|
||||
seg1.p3 = (vec2) {center.x, center.y + radius};
|
||||
|
||||
// Quadrant 2 (90° to 180°): top to left
|
||||
segment_t seg2;
|
||||
seg2.p0 = seg1.p3;
|
||||
seg2.p1 = (vec2) {center.x - rk, center.y + radius};
|
||||
seg2.p2 = (vec2) {center.x - radius, center.y + rk};
|
||||
seg2.p3 = (vec2) {center.x - radius, center.y};
|
||||
|
||||
// Quadrant 3 (180° to 270°): left to bottom
|
||||
segment_t seg3;
|
||||
seg3.p0 = seg2.p3;
|
||||
seg3.p1 = (vec2) {center.x - radius, center.y - rk};
|
||||
seg3.p2 = (vec2) {center.x - rk, center.y - radius};
|
||||
seg3.p3 = (vec2) {center.x, center.y - radius};
|
||||
|
||||
// Quadrant 4 (270° to 360°): bottom to right
|
||||
segment_t seg4;
|
||||
seg4.p0 = seg3.p3;
|
||||
seg4.p1 = (vec2) {center.x + rk, center.y - radius};
|
||||
seg4.p2 = (vec2) {center.x + radius, center.y - rk};
|
||||
seg4.p3 = p0; // closes back to rightmost point
|
||||
|
||||
int start = scene_add_segment(s, seg1);
|
||||
if (start < 0) return -1;
|
||||
if (scene_add_segment(s, seg2) < 0) return -1;
|
||||
if (scene_add_segment(s, seg3) < 0) return -1;
|
||||
if (scene_add_segment(s, seg4) < 0) return -1;
|
||||
|
||||
shape_meta_t meta;
|
||||
meta.start_segment = start;
|
||||
meta.segment_count = 4;
|
||||
compute_bbox(s->shapes.segments, start, 4, &meta.aabb.min_x, &meta.aabb.min_y, &meta.aabb.max_x, &meta.aabb.max_y);
|
||||
return scene_add_shape(s, meta);
|
||||
}
|
||||
|
||||
uint32_t add_circle(scene_t* s, vec2 center, float radius) {
|
||||
s->circles.circles[s->circles.num_circles++] = (circle_t) { center, radius };
|
||||
|
||||
return s->circles.num_circles - 1;
|
||||
}
|
||||
233
src/spatial.h
233
src/spatial.h
@@ -1,233 +0,0 @@
|
||||
#ifndef SPATIAL_H
|
||||
#define SPATIAL_H
|
||||
|
||||
#include "api.h"
|
||||
|
||||
// Tunable constants
|
||||
#define SPATIAL_CELL_SIZE 250.0f
|
||||
#define SPATIAL_HASH_BITS 8
|
||||
#define SPATIAL_HASH_SIZE (1 << SPATIAL_HASH_BITS)
|
||||
#define SPATIAL_QUERY_RANGE 1
|
||||
|
||||
typedef struct {
|
||||
int shape_idx;
|
||||
float min_x, min_y, max_x, max_y;
|
||||
} spatial_entry_t;
|
||||
|
||||
typedef struct {
|
||||
bool occupied;
|
||||
int cx, cy;
|
||||
spatial_entry_t *entries;
|
||||
int count;
|
||||
int capacity;
|
||||
} spatial_slot_t;
|
||||
|
||||
typedef struct {
|
||||
spatial_slot_t slots[SPATIAL_HASH_SIZE];
|
||||
bool dirty;
|
||||
} spatial_grid_t;
|
||||
|
||||
static int spatial_hash(int cx, int cy)
|
||||
{
|
||||
return (cx * 73856093) ^ (cy * 19349663);
|
||||
}
|
||||
|
||||
static void spatial_compute_aabb(shape_t *s, float *min_x, float *min_y,
|
||||
float *max_x, float *max_y)
|
||||
{
|
||||
float cos_r = cosf(s->rotation);
|
||||
float sin_r = sinf(s->rotation);
|
||||
float hx = fabsf(cos_r) * s->sx + fabsf(sin_r) * s->sy;
|
||||
float hy = fabsf(sin_r) * s->sx + fabsf(cos_r) * s->sy;
|
||||
*min_x = s->cx - hx;
|
||||
*min_y = s->cy - hy;
|
||||
*max_x = s->cx + hx;
|
||||
*max_y = s->cy + hy;
|
||||
}
|
||||
|
||||
static void spatial_init(spatial_grid_t *grid)
|
||||
{
|
||||
memset(grid, 0, sizeof(*grid));
|
||||
grid->dirty = true;
|
||||
}
|
||||
|
||||
static void spatial_mark_dirty(spatial_grid_t *grid)
|
||||
{
|
||||
grid->dirty = true;
|
||||
}
|
||||
|
||||
static void spatial_destroy(spatial_grid_t *grid)
|
||||
{
|
||||
for (int i = 0; i < SPATIAL_HASH_SIZE; i++) {
|
||||
if (grid->slots[i].entries) FREE(grid->slots[i].entries);
|
||||
}
|
||||
memset(grid, 0, sizeof(*grid));
|
||||
}
|
||||
|
||||
static void spatial_rebuild(spatial_grid_t *grid, vector_t *shapes)
|
||||
{
|
||||
if (!grid->dirty) return;
|
||||
grid->dirty = false;
|
||||
|
||||
int n = shapes->count;
|
||||
|
||||
// Phase 0: clear occupied flags
|
||||
for (int i = 0; i < SPATIAL_HASH_SIZE; i++) {
|
||||
grid->slots[i].occupied = false;
|
||||
grid->slots[i].count = 0;
|
||||
}
|
||||
|
||||
if (n == 0) return;
|
||||
|
||||
// Phase 1: count shapes per cell
|
||||
for (int i = 0; i < n; i++) {
|
||||
shape_t *s = (shape_t*) vec_get(shapes, i);
|
||||
int ccx = (int) floorf(s->cx / SPATIAL_CELL_SIZE);
|
||||
int ccy = (int) floorf(s->cy / SPATIAL_CELL_SIZE);
|
||||
|
||||
int idx = spatial_hash(ccx, ccy) & (SPATIAL_HASH_SIZE - 1);
|
||||
while (grid->slots[idx].occupied) {
|
||||
if (grid->slots[idx].cx == ccx && grid->slots[idx].cy == ccy) break;
|
||||
idx = (idx + 1) & (SPATIAL_HASH_SIZE - 1);
|
||||
}
|
||||
|
||||
if (!grid->slots[idx].occupied) {
|
||||
grid->slots[idx].occupied = true;
|
||||
grid->slots[idx].cx = ccx;
|
||||
grid->slots[idx].cy = ccy;
|
||||
}
|
||||
grid->slots[idx].count++;
|
||||
}
|
||||
|
||||
// Phase 2: allocate entry arrays based on count
|
||||
for (int i = 0; i < SPATIAL_HASH_SIZE; i++) {
|
||||
if (!grid->slots[i].occupied) continue;
|
||||
if (grid->slots[i].count > grid->slots[i].capacity) {
|
||||
if (grid->slots[i].entries) FREE(grid->slots[i].entries);
|
||||
grid->slots[i].entries = (spatial_entry_t*) ALLOC(
|
||||
(size_t) grid->slots[i].count * sizeof(spatial_entry_t));
|
||||
grid->slots[i].capacity = grid->slots[i].count;
|
||||
}
|
||||
grid->slots[i].count = 0; // reset for fill phase
|
||||
}
|
||||
|
||||
// Phase 3: fill entries
|
||||
for (int i = 0; i < n; i++) {
|
||||
shape_t *s = (shape_t*) vec_get(shapes, i);
|
||||
int ccx = (int) floorf(s->cx / SPATIAL_CELL_SIZE);
|
||||
int ccy = (int) floorf(s->cy / SPATIAL_CELL_SIZE);
|
||||
|
||||
int idx = spatial_hash(ccx, ccy) & (SPATIAL_HASH_SIZE - 1);
|
||||
while (!(grid->slots[idx].occupied &&
|
||||
grid->slots[idx].cx == ccx && grid->slots[idx].cy == ccy)) {
|
||||
idx = (idx + 1) & (SPATIAL_HASH_SIZE - 1);
|
||||
}
|
||||
|
||||
spatial_entry_t *e = &grid->slots[idx].entries[grid->slots[idx].count++];
|
||||
e->shape_idx = i;
|
||||
spatial_compute_aabb(s, &e->min_x, &e->min_y, &e->max_x, &e->max_y);
|
||||
}
|
||||
}
|
||||
|
||||
static int spatial_query_point(spatial_grid_t *grid, vector_t *shapes,
|
||||
float wx, float wy, float world_tol)
|
||||
{
|
||||
int ccx = (int) floorf(wx / SPATIAL_CELL_SIZE);
|
||||
int ccy = (int) floorf(wy / SPATIAL_CELL_SIZE);
|
||||
|
||||
for (int dz = -SPATIAL_QUERY_RANGE; dz <= SPATIAL_QUERY_RANGE; dz++) {
|
||||
for (int dw = -SPATIAL_QUERY_RANGE; dw <= SPATIAL_QUERY_RANGE; dw++) {
|
||||
int cell_x = ccx + dz;
|
||||
int cell_y = ccy + dw;
|
||||
|
||||
int idx = spatial_hash(cell_x, cell_y) & (SPATIAL_HASH_SIZE - 1);
|
||||
int probe_start = idx;
|
||||
|
||||
do {
|
||||
if (!grid->slots[idx].occupied) break;
|
||||
|
||||
if (grid->slots[idx].cx == cell_x && grid->slots[idx].cy == cell_y) {
|
||||
for (int e = 0; e < grid->slots[idx].count; e++) {
|
||||
spatial_entry_t *entry = &grid->slots[idx].entries[e];
|
||||
|
||||
if (wx < entry->min_x - world_tol ||
|
||||
wx > entry->max_x + world_tol ||
|
||||
wy < entry->min_y - world_tol ||
|
||||
wy > entry->max_y + world_tol)
|
||||
continue;
|
||||
|
||||
shape_t *s = (shape_t*) vec_get(shapes, entry->shape_idx);
|
||||
if (shape_hit_test(s, wx, wy, world_tol))
|
||||
return entry->shape_idx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
idx = (idx + 1) & (SPATIAL_HASH_SIZE - 1);
|
||||
} while (idx != probe_start);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int spatial_query_rect_select(spatial_grid_t *grid, vector_t *shapes,
|
||||
float min_x, float min_y,
|
||||
float max_x, float max_y)
|
||||
{
|
||||
for (int i = 0; i < shapes->count; i++) {
|
||||
((shape_t*) vec_get(shapes, i))->selected = false;
|
||||
}
|
||||
int selected_count = 0;
|
||||
|
||||
int min_cx = (int) floorf(min_x / SPATIAL_CELL_SIZE);
|
||||
int min_cy = (int) floorf(min_y / SPATIAL_CELL_SIZE);
|
||||
int max_cx = (int) floorf(max_x / SPATIAL_CELL_SIZE);
|
||||
int max_cy = (int) floorf(max_y / SPATIAL_CELL_SIZE);
|
||||
|
||||
for (int cell_x = min_cx; cell_x <= max_cx; cell_x++) {
|
||||
for (int cell_y = min_cy; cell_y <= max_cy; cell_y++) {
|
||||
int idx = spatial_hash(cell_x, cell_y) & (SPATIAL_HASH_SIZE - 1);
|
||||
int probe_start = idx;
|
||||
|
||||
do {
|
||||
if (!grid->slots[idx].occupied) break;
|
||||
|
||||
if (grid->slots[idx].cx == cell_x && grid->slots[idx].cy == cell_y) {
|
||||
for (int e = 0; e < grid->slots[idx].count; e++) {
|
||||
spatial_entry_t *entry = &grid->slots[idx].entries[e];
|
||||
|
||||
if (entry->max_x < min_x || entry->min_x > max_x ||
|
||||
entry->max_y < min_y || entry->min_y > max_y)
|
||||
continue;
|
||||
|
||||
shape_t *s = (shape_t*) vec_get(shapes, entry->shape_idx);
|
||||
if (s->selected) continue;
|
||||
|
||||
bool hit = (s->cx >= min_x && s->cx <= max_x &&
|
||||
s->cy >= min_y && s->cy <= max_y);
|
||||
float sc = cosf(s->rotation), ss = sinf(s->rotation);
|
||||
for (uint32_t v = 0; !hit && v < s->num_verts; v++) {
|
||||
float lx = s->verts[v].x * s->sx;
|
||||
float ly = s->verts[v].y * s->sy;
|
||||
float wx = s->cx + lx * sc - ly * ss;
|
||||
float wy = s->cy + lx * ss + ly * sc;
|
||||
if (wx >= min_x && wx <= max_x &&
|
||||
wy >= min_y && wy <= max_y)
|
||||
hit = true;
|
||||
}
|
||||
if (hit) {
|
||||
s->selected = true;
|
||||
selected_count++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
idx = (idx + 1) & (SPATIAL_HASH_SIZE - 1);
|
||||
} while (idx != probe_start);
|
||||
}
|
||||
}
|
||||
return selected_count;
|
||||
}
|
||||
|
||||
#endif
|
||||
104
src/util.h
104
src/util.h
@@ -1,104 +0,0 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct vector_t {
|
||||
uint8_t *data;
|
||||
int count;
|
||||
int capacity;
|
||||
int stride;
|
||||
} vector_t;
|
||||
|
||||
/**
|
||||
* Zero-initialize a vector with the given element stride.
|
||||
*
|
||||
* @param v vector to initialize
|
||||
* @param stride byte size of each element
|
||||
*/
|
||||
static void vec_init(vector_t *v, int stride) {
|
||||
memset(v, 0, sizeof(*v));
|
||||
v->stride = stride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow the vector's backing array to at least min_capacity elements.
|
||||
* Doubles capacity (starting at 8) or uses min_capacity, whichever is larger.
|
||||
*
|
||||
* @param v vector to grow
|
||||
* @param min_capacity minimum element count required
|
||||
*/
|
||||
static void vec_grow(vector_t *v, int min_capacity) {
|
||||
int new_cap = v->capacity ? v->capacity * 2 : 8;
|
||||
if (new_cap < min_capacity) new_cap = min_capacity;
|
||||
uint8_t *new_data = (uint8_t*) ALLOC(new_cap * v->stride);
|
||||
if (v->data) {
|
||||
memcpy(new_data, v->data, v->count * v->stride);
|
||||
FREE(v->data);
|
||||
}
|
||||
v->data = new_data;
|
||||
v->capacity = new_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an uninitialized element to the end of the vector. Grows if needed.
|
||||
*
|
||||
* @param v vector to push into
|
||||
* @return pointer to the new (uninitialized) element
|
||||
*/
|
||||
static void *vec_push(vector_t *v) {
|
||||
if (v->count >= v->capacity) vec_grow(v, v->count + 1);
|
||||
return v->data + (v->count++) * v->stride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the last element from the vector (decrements count, no free).
|
||||
*
|
||||
* @param v vector to pop from
|
||||
*/
|
||||
static void vec_pop(vector_t *v) {
|
||||
if (v->count > 0) v->count--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the element at index by swapping in the last element (O(1)).
|
||||
* Order is not preserved.
|
||||
*
|
||||
* @param v vector to remove from
|
||||
* @param index index of the element to remove
|
||||
*/
|
||||
static void vec_remove(vector_t *v, int index) {
|
||||
if (index < 0 || index >= v->count) return;
|
||||
if (index < v->count - 1) {
|
||||
memcpy(v->data + index * v->stride,
|
||||
v->data + (v->count - 1) * v->stride,
|
||||
v->stride);
|
||||
}
|
||||
v->count--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to the element at index (no bounds check).
|
||||
*
|
||||
* @param v vector to access
|
||||
* @param index element index
|
||||
* @return pointer to the element
|
||||
*/
|
||||
static void *vec_get(vector_t *v, int index) {
|
||||
return v->data + index * v->stride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the backing array and reset the vector to empty.
|
||||
*
|
||||
* @param v vector to free
|
||||
*/
|
||||
static void vec_free(vector_t *v) {
|
||||
if (v->data) FREE(v->data);
|
||||
v->data = NULL;
|
||||
v->count = 0;
|
||||
v->capacity = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user