Compare commits
No commits in common. "master" and "v2_incenter" have entirely different histories.
master
...
v2_incente
|
@ -9,11 +9,7 @@ working_data/
|
|||
nssm_log.log
|
||||
sysroot/
|
||||
*.DS_Store
|
||||
*.vscode
|
||||
*.vscode/*
|
||||
*.dSYM
|
||||
run_tree/data/live_data
|
||||
run_tree/osx/*
|
||||
run_tree/win32/*
|
||||
run_tree/wasm/*
|
||||
run_tree/webgl/*
|
||||
run_tree/raspi/*
|
||||
build_local.sh
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "C++ Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"windows": {
|
||||
"program": "${workspaceRoot}/run_tree/win32/intel/debug/lumenarium",
|
||||
},
|
||||
"osx": {
|
||||
"program": "${workspaceRoot}/run_tree/osx/arm64/debug/lumenarium",
|
||||
"MIMode": "lldb"
|
||||
},
|
||||
"linux": {
|
||||
"program": "${workspaceRoot}/run_tree/raspi/intel/debug/lumenarium",
|
||||
},
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"logging": {
|
||||
"moduleLoad": false,
|
||||
"programOutput": true,
|
||||
"trace": false
|
||||
},
|
||||
"showDisplayString": false,
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceRoot}/run_tree",
|
||||
"environment": [],
|
||||
"externalConsole": false, // set true to enable keyboard input
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"lumenarium_osx_file.h": "c",
|
||||
"__bit_reference": "cpp",
|
||||
"__functional_base": "cpp",
|
||||
"__node_handle": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"bitset": "cpp",
|
||||
"chrono": "cpp",
|
||||
"__memory": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"limits": "cpp",
|
||||
"optional": "cpp",
|
||||
"ratio": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"vector": "cpp",
|
||||
"memory": "cpp",
|
||||
"dyld.h": "c",
|
||||
"lumenarium_first.h": "c",
|
||||
"__locale": "c",
|
||||
"lumenarium_editor_opengl.h": "c",
|
||||
"complex": "c",
|
||||
"locale": "c",
|
||||
"string": "c",
|
||||
"lumenarium_editor_sculpture_visualizer_shaders.h": "c",
|
||||
"lumenarium_shared_file_async_work_on_job.h": "c",
|
||||
"lumenarium_engine_assembly.h": "c",
|
||||
"lumenarium_engine_output.h": "c",
|
||||
"ios": "cpp",
|
||||
"lumenarium_os.h": "c",
|
||||
"__hash_table": "c",
|
||||
"__split_buffer": "c",
|
||||
"array": "c",
|
||||
"initializer_list": "c",
|
||||
"string_view": "c",
|
||||
"unordered_map": "c",
|
||||
"typeinfo": "c",
|
||||
"cmath": "c",
|
||||
"lumenarium_editor_geometry.h": "c",
|
||||
"question_3.h": "c",
|
||||
"question_14.h": "c",
|
||||
"incenter_user_space.h": "c"
|
||||
},
|
||||
"C_Cpp.errorSquiggles": "Disabled"
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"type": "shell",
|
||||
"windows": {
|
||||
"command": "git-bash ./build/build.sh",
|
||||
"args": ["debug", "win32", "intel" ],
|
||||
},
|
||||
"osx": {
|
||||
"command": "./build/build.sh",
|
||||
"args": ["debug", "osx", "arm64", ],
|
||||
//"args": ["debug", "osx", "intel", ],
|
||||
},
|
||||
"linux": {
|
||||
"command": "./build/build.sh",
|
||||
"args": ["debug", "raspi", "intel" ],
|
||||
},
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": {
|
||||
"owner": "cpp",
|
||||
"fileLocation": [
|
||||
"relative",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"pattern": {
|
||||
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"severity": 4,
|
||||
"message": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
40
README.md
40
README.md
|
@ -1,32 +1,34 @@
|
|||
# Lumenarium by Foldhaus
|
||||

|
||||

|
||||
|
||||
## Build Lumenarium
|
||||
Build Dependencies:
|
||||
- clang
|
||||
- bash
|
||||
- Note for Windows Users: You can still run bash scripts using git-bash (my recommendation) or WSL
|
||||
Building Lumenarium requires having MSVC installed (sorry, Windows only for now!).
|
||||
1. clone the repo onto your computer
|
||||
2. Run the appropriate build batch file
|
||||
- for Windows: use `build\build_app_msvc_win32_debug.bat`
|
||||
- other platforms coming soon
|
||||
3. Build scripts will output executables into the app_run_tree directory, by platform
|
||||
|
||||
To build Lumenarium:
|
||||
1. Clone the repo onto your computer
|
||||
2. Run `build\build.sh` with the appropriate platform, architecture, and release mode flags
|
||||
- Example: `build\build.sh debug osx arm64`
|
||||
- You can see the full list of supported flags by running `build\build.sh` with no arguments
|
||||
3. Build scripts will output executables into the run_tree directory.
|
||||
- The above example will output the following executable: `run_tree\osx\arm64\debug\lumenarium`
|
||||
## Run Lumenarium
|
||||
Windows - Debug
|
||||
1. Run `app_run_tree\win32_msvc\debug\win32_foldhaus.exe`
|
||||
|
||||
This repository features a .vscode directory which has been set up with a build task and launch.json to work out of the box.
|
||||
- *Note: I have not been able to test the configuration on Windows or Linux. Feel free to open a PR if you find something is wrong with the vscode setup*
|
||||
If you want to run in headless mode:
|
||||
1. Run `app_run_tree\win32_msvc\debug\win32_foldhaus.exe -headless`
|
||||
|
||||
## Debug Lumenarium
|
||||
### Windows
|
||||
Building in debug mode outputs pdb file info that can be read by Visual Studio or RemedyBG (preferred debugging solution, but ymmv). You can just open the exe in either application and it'll find the pdb file in the same directory
|
||||
|
||||
## What Is Lumenarium?
|
||||
Lumenarium is our custom build light and motion control software. It allows us to design light and motion patterns for our sculptures, visualize the output long before the sculpture is built, and iterate in real time to achieve the best visual results quickly.
|
||||
|
||||
Lumenarium has been used in several sculptures in museums, permanent installations, and at Burning Man. Lumenarium was developed in collaboration with [Foldhaus](https://www.foldhaus.com). The current iteration of Lumenarium was developed while working on Incenter for Burning Man '22.
|
||||
|
||||
## Features
|
||||
*NOTE: These were features from an earlier version of Lumenarium and are still being ported over to the v2 codebase*
|
||||
[Foldhaus can be found here.](https://www.foldhaus.com)
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
The following features are under active development for integration in Lumenarium
|
||||
* [Sculpture File Format](#sculpture-file-format)
|
||||
* [DMX Output](#dmx-output)
|
||||
|
@ -43,7 +45,7 @@ Documentation coming soon.
|
|||
|
||||
***
|
||||
### DMX Output
|
||||
Lumenarium supports sACN output, and ArtNet is in development, via a DMX system which underlies them both.
|
||||
Lumenarium supports SACN output, and ArtNet is in development, via a DMX system which underlies them both.
|
||||
|
||||
***
|
||||
### Live Visualization
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Project Admin Stuff
|
||||
|
||||
## Priorities
|
||||
|
||||
1. Upgrade Lumenarium's plumbing
|
||||
2. Begin work on Incenter
|
||||
|
||||
## TODO
|
||||
|
||||
1. Upgrade Lumenarium's plumbing
|
||||
x. switch over to compiling with clang & bash based build scripts
|
||||
x. better platform layer separation
|
||||
3. osx and webgl layers, possibly linux?
|
||||
x. remove dll compiling, just build all in one go
|
||||
5. improve ui
|
||||
[ ] get widgets and widget ids working
|
||||
- see a trick of fate
|
||||
[ ] clip widgets to regions
|
||||
[ ] text rendering
|
||||
[ ] interaction
|
||||
[ ] layout manager
|
||||
- do layout the way youre doing styling - optional pointer to a struct
|
||||
and fallback on some global default
|
||||
|
||||
2. Incenter
|
||||
1. Sculpture generation from list of lat-long coordinates
|
||||
2.
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,56 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "digital_fire";
|
||||
layers_count: 3;
|
||||
blocks_count: 4;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 10000;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "mask1";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "mask2";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "color";
|
||||
blend: "Multiply";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 19;
|
||||
};
|
||||
layer_index: 0;
|
||||
animation_name: "Pattern_BulbMask";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 10000;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_Leafy";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 5156;
|
||||
};
|
||||
layer_index: 2;
|
||||
animation_name: "Pattern_Rainbow";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 5040;
|
||||
max: 10000;
|
||||
};
|
||||
layer_index: 2;
|
||||
animation_name: "Pattern_Wavy";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,48 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "fishy_0";
|
||||
layers_count: 3;
|
||||
blocks_count: 3;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "Color";
|
||||
blend: "Multiply";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layer_index: 2;
|
||||
animation_name: "Pattern_HueShift";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_StemSolid";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layer_index: 0;
|
||||
animation_name: "Pattern_VerticalLines";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "patchy_loading_bar_0";
|
||||
layers_count: 2;
|
||||
blocks_count: 2;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 3350;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Multiply";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_Patchy";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layer_index: 0;
|
||||
animation_name: "Pattern_GrowFadeMask";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "primary_hue_0";
|
||||
layers_count: 2;
|
||||
blocks_count: 1;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 360;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 36000;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_PrimaryHue";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "rainbow";
|
||||
layers_count: 3;
|
||||
blocks_count: 1;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 36000;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "Mask";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "Color";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 36000;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_Rainbow";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "rainbow_loading_bar_0";
|
||||
layers_count: 2;
|
||||
blocks_count: 1;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 9000;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 9000;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_RainbowLoadingBar";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "wavy_0";
|
||||
layers_count: 2;
|
||||
blocks_count: 2;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 7200;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Overwrite";
|
||||
};
|
||||
layer:{
|
||||
name: "Color";
|
||||
blend: "Multiply";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 7200;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_Wavy";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 78;
|
||||
max: 3571;
|
||||
};
|
||||
layer_index: 0;
|
||||
animation_name: "Pattern_Leafy";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "voice_anim";
|
||||
layers_count: 2;
|
||||
blocks_count: 2;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "Base";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "Add In";
|
||||
blend: "Overwrite";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layer_index: 0;
|
||||
animation_name: "Pattern_VoicePattern";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 3600;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_VoiceAddIns";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,88 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "awaken";
|
||||
layers_count: 3;
|
||||
blocks_count: 8;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 7200;
|
||||
};
|
||||
layers:{
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Add";
|
||||
};
|
||||
layer:{
|
||||
name: "[New Layer]";
|
||||
blend: "Multiply";
|
||||
};
|
||||
};
|
||||
blocks:{
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 1363;
|
||||
};
|
||||
layer_index: 0;
|
||||
animation_name: "Pattern_Leafy";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 1169;
|
||||
max: 7200;
|
||||
};
|
||||
layer_index: 0;
|
||||
animation_name: "Pattern_BulbMask";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 5525;
|
||||
max: 7200;
|
||||
};
|
||||
layer_index: 2;
|
||||
animation_name: "Pattern_Wavy";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 2135;
|
||||
max: 2555;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_None";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 2470;
|
||||
max: 7200;
|
||||
};
|
||||
layer_index: 1;
|
||||
animation_name: "Pattern_StemSolid";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 0;
|
||||
max: 1917;
|
||||
};
|
||||
layer_index: 2;
|
||||
animation_name: "Pattern_Blue";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 1823;
|
||||
max: 3803;
|
||||
};
|
||||
layer_index: 2;
|
||||
animation_name: "Pattern_RainbowLoadingBar";
|
||||
};
|
||||
block:{
|
||||
frame_range:{
|
||||
min: 3670;
|
||||
max: 5720;
|
||||
};
|
||||
layer_index: 2;
|
||||
animation_name: "Pattern_Rainbow";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
lumenarium_animation_file;
|
||||
animation_name: "off_anim";
|
||||
layers_count: 0;
|
||||
blocks_count: 0;
|
||||
playable_range:{
|
||||
min: 0;
|
||||
max: 2;
|
||||
};
|
||||
layers:{
|
||||
};
|
||||
blocks:{
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
led_strip_count 12
|
||||
|
||||
led_strip { 0, 2, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (0.000000, 0.050000, 1.000000), 346 }
|
||||
led_strip { 0, 4, 0, INTERPOLATE_POINTS, (0.500000, 0.866025, 0.000000), (0.025000, 0.043301, 1.000000), 346 }
|
||||
led_strip { 0, 6, 0, INTERPOLATE_POINTS, (0.866025, 0.499999, 0.000000), (0.043301, 0.024999, 1.000000), 346 }
|
||||
led_strip { 0, 8, 0, INTERPOLATE_POINTS, (1.000000, -0.000000, 0.000000), (0.050000, -0.000000, 1.000000), 346 }
|
||||
led_strip { 0, 10, 0, INTERPOLATE_POINTS, (0.866025, -0.500000, 0.000000), (0.043301, -0.025000, 1.000000), 346 }
|
||||
led_strip { 0, 12, 0, INTERPOLATE_POINTS, (0.500000, -0.866025, 0.000000), (0.025000, -0.043301, 1.000000), 346 }
|
||||
led_strip { 0, 14, 0, INTERPOLATE_POINTS, (-0.000000, -1.000000, 0.000000), (-0.000000, -0.050000, 1.000000), 346 }
|
||||
led_strip { 0, 7, 0, INTERPOLATE_POINTS, (-0.500000, -0.866025, 0.000000), (-0.025000, -0.043301, 1.000000), 346 }
|
||||
led_strip { 0, 8, 0, INTERPOLATE_POINTS, (-0.866025, -0.499999, 0.000000), (-0.043301, -0.024999, 1.000000), 346 }
|
||||
led_strip { 0, 9, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.050000, 0.000000, 1.000000), 346 }
|
||||
led_strip { 0, 10, 0, INTERPOLATE_POINTS, (-0.866025, 0.499999, 0.000000), (-0.043301, 0.024999, 1.000000), 346 }
|
||||
led_strip { 0, 11, 0, INTERPOLATE_POINTS, (-0.499999, 0.866025, 0.000000), (-0.024999, 0.043301, 1.000000), 346 }
|
||||
END_OF_ASSEMBLY_FILE
|
|
@ -0,0 +1,21 @@
|
|||
// NOTE(Peter): stuff this in a function and itll print out the code needed to generate a blumen
|
||||
// TODO(Peter): Modify this when you get actual blumen measurements
|
||||
MakeStringBuffer(Buffer, 256);
|
||||
v3 InnerVectors[12];
|
||||
v3 OuterVectors[12];
|
||||
for (s32 i = 0; i < 12; i++)
|
||||
{
|
||||
r32 Theta = ((r32)i / 12.0f) * 2 * PI;
|
||||
|
||||
v3 Direction = v3{GSSin(Theta), GSCos(Theta), 0};
|
||||
|
||||
InnerVectors[i] = Direction;
|
||||
OuterVectors[i] = v3{Direction.x * 0.05f, Direction.y * 0.05f, 1};
|
||||
|
||||
PrintF(&Buffer, "led_strip { 0, %d, 0, INTERPOLATE_POINTS, (%f, %f, %f), (%f, %f, %f), 70 }\n",
|
||||
i,
|
||||
InnerVectors[i].x, InnerVectors[i].y, InnerVectors[i].z,
|
||||
OuterVectors[i].x, OuterVectors[i].y, OuterVectors[i].z);
|
||||
NullTerminate(&Buffer);
|
||||
OutputDebugStringA(Buffer.Memory);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
Peter : 10000
|
||||
Andrew : 2500
|
||||
Kim : 2000
|
||||
Felicia : 1000
|
||||
Skye : 200
|
Binary file not shown.
|
@ -0,0 +1,338 @@
|
|||
|
||||
{
|
||||
neighbors: [16, 14, 12, 13, 15];
|
||||
ip: 192.168.1.200;
|
||||
x: 0;
|
||||
y: 0.525731086730957;
|
||||
z: 0.8506507873535156;
|
||||
id: 0;
|
||||
};
|
||||
{
|
||||
neighbors: [20, 17, 12, 18, 19];
|
||||
ip: 192.168.1.201;
|
||||
x: 0;
|
||||
y: -0.525731086730957;
|
||||
z: 0.8506507873535156;
|
||||
id: 1;
|
||||
};
|
||||
{
|
||||
neighbors: [24, 22, 21, 23, 25];
|
||||
ip: 192.168.1.202;
|
||||
x: 0;
|
||||
y: -0.525731086730957;
|
||||
z: -0.8506507873535156;
|
||||
id: 2;
|
||||
};
|
||||
{
|
||||
neighbors: [28, 27, 21, 26, 29];
|
||||
ip: 192.168.1.203;
|
||||
x: 0;
|
||||
y: 0.525731086730957;
|
||||
z: -0.8506507873535156;
|
||||
id: 3;
|
||||
};
|
||||
{
|
||||
neighbors: [31, 13, 17, 32, 30];
|
||||
ip: 192.168.1.204;
|
||||
x: 0.8506507873535156;
|
||||
y: 0;
|
||||
z: 0.525731086730957;
|
||||
id: 4;
|
||||
};
|
||||
{
|
||||
neighbors: [14, 34, 33, 35, 18];
|
||||
ip: 192.168.1.205;
|
||||
x: -0.8506507873535156;
|
||||
y: 0;
|
||||
z: 0.525731086730957;
|
||||
id: 5;
|
||||
};
|
||||
{
|
||||
neighbors: [36, 26, 22, 37, 33];
|
||||
ip: 192.168.1.206;
|
||||
x: -0.8506507873535156;
|
||||
y: 0;
|
||||
z: -0.525731086730957;
|
||||
id: 6;
|
||||
};
|
||||
{
|
||||
neighbors: [30, 39, 23, 27, 38];
|
||||
ip: 192.168.1.207;
|
||||
x: 0.8506507873535156;
|
||||
y: 0;
|
||||
z: -0.525731086730957;
|
||||
id: 7;
|
||||
};
|
||||
{
|
||||
neighbors: [38, 28, 40, 15, 31];
|
||||
ip: 192.168.1.208;
|
||||
x: 0.525731086730957;
|
||||
y: 0.8506507873535156;
|
||||
z: 0;
|
||||
id: 8;
|
||||
};
|
||||
{
|
||||
neighbors: [36, 34, 16, 40, 29];
|
||||
ip: 192.168.1.209;
|
||||
x: -0.525731086730957;
|
||||
y: 0.8506507873535156;
|
||||
z: 0;
|
||||
id: 9;
|
||||
};
|
||||
{
|
||||
neighbors: [35, 37, 24, 41, 19];
|
||||
ip: 192.168.1.210;
|
||||
x: -0.525731086730957;
|
||||
y: -0.8506507873535156;
|
||||
z: 0;
|
||||
id: 10;
|
||||
};
|
||||
{
|
||||
neighbors: [32, 20, 41, 25, 39];
|
||||
ip: 192.168.1.211;
|
||||
x: 0.525731086730957;
|
||||
y: -0.8506507873535156;
|
||||
z: 0;
|
||||
id: 11;
|
||||
};
|
||||
{
|
||||
neighbors: [0, 14, 18, 1, 17, 13];
|
||||
ip: 192.168.1.212;
|
||||
x: 0;
|
||||
y: 0;
|
||||
z: 1;
|
||||
id: 12;
|
||||
};
|
||||
{
|
||||
neighbors: [4, 31, 15, 0, 12, 17];
|
||||
ip: 192.168.1.213;
|
||||
x: 0.5;
|
||||
y: 0.30901700258255005;
|
||||
z: 0.80901700258255;
|
||||
id: 13;
|
||||
};
|
||||
{
|
||||
neighbors: [0, 16, 34, 5, 18, 12];
|
||||
ip: 192.168.1.214;
|
||||
x: -0.5;
|
||||
y: 0.30901700258255005;
|
||||
z: 0.80901700258255;
|
||||
id: 14;
|
||||
};
|
||||
{
|
||||
neighbors: [8, 40, 16, 0, 13, 31];
|
||||
ip: 192.168.1.215;
|
||||
x: 0.30901700258255005;
|
||||
y: 0.80901700258255;
|
||||
z: 0.5;
|
||||
id: 15;
|
||||
};
|
||||
{
|
||||
neighbors: [9, 34, 14, 0, 15, 40];
|
||||
ip: 192.168.1.216;
|
||||
x: -0.30901700258255005;
|
||||
y: 0.80901700258255;
|
||||
z: 0.5;
|
||||
id: 16;
|
||||
};
|
||||
{
|
||||
neighbors: [4, 13, 12, 1, 20, 32];
|
||||
ip: 192.168.1.217;
|
||||
x: 0.5;
|
||||
y: -0.30901700258255005;
|
||||
z: 0.80901700258255;
|
||||
id: 17;
|
||||
};
|
||||
{
|
||||
neighbors: [5, 35, 19, 1, 12, 14];
|
||||
ip: 192.168.1.218;
|
||||
x: -0.5;
|
||||
y: -0.30901700258255005;
|
||||
z: 0.80901700258255;
|
||||
id: 18;
|
||||
};
|
||||
{
|
||||
neighbors: [1, 18, 35, 10, 41, 20];
|
||||
ip: 192.168.1.219;
|
||||
x: -0.30901700258255005;
|
||||
y: -0.80901700258255;
|
||||
z: 0.5;
|
||||
id: 19;
|
||||
};
|
||||
{
|
||||
neighbors: [11, 32, 17, 1, 19, 41];
|
||||
ip: 192.168.1.220;
|
||||
x: 0.30901700258255005;
|
||||
y: -0.80901700258255;
|
||||
z: 0.5;
|
||||
id: 20;
|
||||
};
|
||||
{
|
||||
neighbors: [3, 27, 23, 2, 22, 26];
|
||||
ip: 192.168.1.221;
|
||||
x: 0;
|
||||
y: 0;
|
||||
z: -1;
|
||||
id: 21;
|
||||
};
|
||||
{
|
||||
neighbors: [6, 26, 21, 2, 24, 37];
|
||||
ip: 192.168.1.222;
|
||||
x: -0.5;
|
||||
y: -0.30901700258255005;
|
||||
z: -0.80901700258255;
|
||||
id: 22;
|
||||
};
|
||||
{
|
||||
neighbors: [7, 39, 25, 2, 21, 27];
|
||||
ip: 192.168.1.223;
|
||||
x: 0.5;
|
||||
y: -0.30901700258255005;
|
||||
z: -0.80901700258255;
|
||||
id: 23;
|
||||
};
|
||||
{
|
||||
neighbors: [10, 37, 22, 2, 25, 41];
|
||||
ip: 192.168.1.224;
|
||||
x: -0.30901700258255005;
|
||||
y: -0.80901700258255;
|
||||
z: -0.5;
|
||||
id: 24;
|
||||
};
|
||||
{
|
||||
neighbors: [11, 41, 24, 2, 23, 39];
|
||||
ip: 192.168.1.225;
|
||||
x: 0.30901700258255005;
|
||||
y: -0.80901700258255;
|
||||
z: -0.5;
|
||||
id: 25;
|
||||
};
|
||||
{
|
||||
neighbors: [3, 21, 22, 6, 36, 29];
|
||||
ip: 192.168.1.226;
|
||||
x: -0.5;
|
||||
y: 0.30901700258255005;
|
||||
z: -0.80901700258255;
|
||||
id: 26;
|
||||
};
|
||||
{
|
||||
neighbors: [3, 28, 38, 7, 23, 21];
|
||||
ip: 192.168.1.227;
|
||||
x: 0.5;
|
||||
y: 0.30901700258255005;
|
||||
z: -0.80901700258255;
|
||||
id: 27;
|
||||
};
|
||||
{
|
||||
neighbors: [8, 38, 27, 3, 29, 40];
|
||||
ip: 192.168.1.228;
|
||||
x: 0.30901700258255005;
|
||||
y: 0.80901700258255;
|
||||
z: -0.5;
|
||||
id: 28;
|
||||
};
|
||||
{
|
||||
neighbors: [9, 40, 28, 3, 26, 36];
|
||||
ip: 192.168.1.229;
|
||||
x: -0.30901700258255005;
|
||||
y: 0.80901700258255;
|
||||
z: -0.5;
|
||||
id: 29;
|
||||
};
|
||||
{
|
||||
neighbors: [7, 38, 31, 4, 32, 39];
|
||||
ip: 192.168.1.230;
|
||||
x: 1;
|
||||
y: 0;
|
||||
z: 0;
|
||||
id: 30;
|
||||
};
|
||||
{
|
||||
neighbors: [8, 15, 13, 4, 30, 38];
|
||||
ip: 192.168.1.231;
|
||||
x: 0.80901700258255;
|
||||
y: 0.5;
|
||||
z: 0.30901700258255005;
|
||||
id: 31;
|
||||
};
|
||||
{
|
||||
neighbors: [11, 39, 30, 4, 17, 20];
|
||||
ip: 192.168.1.232;
|
||||
x: 0.80901700258255;
|
||||
y: -0.5;
|
||||
z: 0.30901700258255005;
|
||||
id: 32;
|
||||
};
|
||||
{
|
||||
neighbors: [5, 34, 36, 6, 37, 35];
|
||||
ip: 192.168.1.233;
|
||||
x: -1;
|
||||
y: 0;
|
||||
z: 0;
|
||||
id: 33;
|
||||
};
|
||||
{
|
||||
neighbors: [5, 14, 16, 9, 36, 33];
|
||||
ip: 192.168.1.234;
|
||||
x: -0.80901700258255;
|
||||
y: 0.5;
|
||||
z: 0.30901700258255005;
|
||||
id: 34;
|
||||
};
|
||||
{
|
||||
neighbors: [5, 33, 37, 10, 19, 18];
|
||||
ip: 192.168.1.235;
|
||||
x: -0.80901700258255;
|
||||
y: -0.5;
|
||||
z: 0.30901700258255005;
|
||||
id: 35;
|
||||
};
|
||||
{
|
||||
neighbors: [9, 29, 26, 6, 33, 34];
|
||||
ip: 192.168.1.236;
|
||||
x: -0.80901700258255;
|
||||
y: 0.5;
|
||||
z: -0.30901700258255005;
|
||||
id: 36;
|
||||
};
|
||||
{
|
||||
neighbors: [10, 35, 33, 6, 22, 24];
|
||||
ip: 192.168.1.237;
|
||||
x: -0.80901700258255;
|
||||
y: -0.5;
|
||||
z: -0.30901700258255005;
|
||||
id: 37;
|
||||
};
|
||||
{
|
||||
neighbors: [8, 31, 30, 7, 27, 28];
|
||||
ip: 192.168.1.238;
|
||||
x: 0.80901700258255;
|
||||
y: 0.5;
|
||||
z: -0.30901700258255005;
|
||||
id: 38;
|
||||
};
|
||||
{
|
||||
neighbors: [11, 25, 23, 7, 30, 32];
|
||||
ip: 192.168.1.239;
|
||||
x: 0.80901700258255;
|
||||
y: -0.5;
|
||||
z: -0.30901700258255005;
|
||||
id: 39;
|
||||
};
|
||||
{
|
||||
neighbors: [8, 28, 29, 9, 16, 15];
|
||||
ip: 192.168.1.240;
|
||||
x: 0;
|
||||
y: 1;
|
||||
z: 0;
|
||||
id: 40;
|
||||
};
|
||||
{
|
||||
neighbors: [11, 20, 19, 10, 24, 25];
|
||||
ip: 192.168.1.241;
|
||||
x: 0;
|
||||
y: -1;
|
||||
z: 0;
|
||||
id: 41;
|
||||
};
|
||||
EOF
|
|
@ -0,0 +1,408 @@
|
|||
led_strip_count 406
|
||||
|
||||
led_strip { 0, 0, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 0, 1, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 0, 2, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 0, 3, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 0, 4, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 1, 25, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 1, 26, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 1, 27, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 1, 28, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 1, 29, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 2, 50, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 2, 51, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 2, 52, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 2, 53, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 2, 54, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 3, 75, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 3, 76, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 3, 77, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 3, 78, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 3, 79, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 4, 100, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 4, 101, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 4, 102, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 4, 103, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 4, 104, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 5, 125, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 5, 126, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 5, 127, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 5, 128, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 5, 129, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 6, 150, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 6, 151, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 6, 152, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 6, 153, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 6, 154, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 7, 175, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 7, 176, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 7, 177, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 7, 178, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 7, 179, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 8, 200, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 8, 201, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 8, 202, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 8, 203, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 8, 204, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 9, 225, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 9, 226, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 9, 227, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 9, 228, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 9, 229, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 10, 250, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 10, 251, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 10, 252, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 10, 253, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 10, 254, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 11, 275, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 11, 276, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 11, 277, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 11, 278, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 11, 279, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 12, 300, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 12, 301, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 12, 302, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 12, 303, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 12, 304, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 12, 305, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 13, 325, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 13, 326, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 13, 327, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 13, 328, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 13, 329, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 13, 330, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 14, 350, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 14, 351, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 14, 352, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 14, 353, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 14, 354, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 14, 355, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 15, 375, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 15, 376, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 15, 377, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 15, 378, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 15, 379, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 15, 380, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 16, 400, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 16, 401, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 16, 402, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 16, 403, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 16, 404, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 16, 405, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 17, 425, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 17, 426, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 17, 427, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 17, 428, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 17, 429, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 17, 430, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 18, 450, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 18, 451, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 18, 452, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 18, 453, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 18, 454, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 18, 455, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 19, 475, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 19, 476, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 19, 477, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 19, 478, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 19, 479, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 19, 480, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 20, 500, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 20, 501, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 20, 502, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 20, 503, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 20, 504, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 20, 505, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 21, 525, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 21, 526, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 21, 527, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 21, 528, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 21, 529, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 21, 530, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 22, 550, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (-0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 22, 551, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 22, 552, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 22, 553, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 22, 554, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 22, 555, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 23, 575, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 23, 576, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 23, 577, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 23, 578, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 23, 579, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 23, 580, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 24, 600, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 24, 601, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 24, 602, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 24, 603, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 24, 604, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 24, 605, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 25, 625, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 25, 626, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 25, 627, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 25, 628, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 25, 629, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 25, 630, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 26, 650, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 26, 651, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 26, 652, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 26, 653, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (-0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 26, 654, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 26, 655, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 27, 675, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 27, 676, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 27, 677, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 27, 678, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 27, 679, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 27, 680, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 28, 700, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 28, 701, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 28, 702, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 28, 703, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 28, 704, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 28, 705, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 29, 725, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 29, 726, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 29, 727, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 29, 728, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 29, 729, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 29, 730, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 30, 750, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 30, 751, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 30, 752, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 30, 753, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 30, 754, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 30, 755, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 31, 775, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 31, 776, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 31, 777, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 31, 778, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 31, 779, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 31, 780, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 32, 800, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 32, 801, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 32, 802, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 32, 803, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 32, 804, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 32, 805, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 33, 825, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 33, 826, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 33, 827, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.809017, 0.500000, -0.309017), 144 } led_strip { 33, 829, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 33, 830, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 34, 850, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 34, 851, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 34, 852, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 34, 853, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 34, 854, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 34, 855, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 35, 875, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 35, 876, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 35, 877, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 35, 878, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 35, 879, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-0.309017, -0.809017, 0.500000), 144 } led_strip { 36, 900, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 36, 901, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 36, 902, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 36, 903, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 36, 904, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 36, 905, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 37, 925, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 37, 926, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 37, 927, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 37, 928, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 37, 929, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 37, 930, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 38, 950, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 38, 951, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 38, 952, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 38, 953, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 38, 954, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 38, 955, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 39, 975, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 39, 976, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 39, 977, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 39, 978, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 39, 979, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 39, 980, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 40, 1000, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 40, 1001, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 40, 1002, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 40, 1003, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 40, 1004, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 40, 1005, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 41, 1025, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 41, 1026, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 41, 1027, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 41, 1028, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 41, 1029, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 41, 1030, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (0.309017, -0.809017, -0.500000), 144 }
|
||||
|
||||
led_strip { 0, 5, 0, INTERPOLATE_POINTS, (-0.005654, 0.530914, 0.844235), (-0.005654, 0.662347, 1.056898), 144 }
|
||||
led_strip { 0, 6, 0, INTERPOLATE_POINTS, (0.005654, 0.651981, 1.069729), (0.005654, 0.520548, 0.857067), 144 }
|
||||
led_strip { 0, 7, 0, INTERPOLATE_POINTS, (-0.009149, 0.521766, 0.849889), (-0.009149, 0.653199, 1.062552), 144 }
|
||||
led_strip { 0, 8, 0, INTERPOLATE_POINTS, (0.002160, 0.642832, 1.075384), (0.002160, 0.511399, 0.862721), 144 }
|
||||
led_strip { 1, 30, 0, INTERPOLATE_POINTS, (0.005654, -0.530914, 0.844235), (0.005654, -0.662347, 1.056898), 144 }
|
||||
led_strip { 1, 31, 0, INTERPOLATE_POINTS, (-0.005654, -0.651981, 1.069729), (-0.005654, -0.520548, 0.857067), 144 }
|
||||
led_strip { 1, 32, 0, INTERPOLATE_POINTS, (0.009149, -0.521766, 0.849889), (0.009149, -0.653199, 1.062552), 144 }
|
||||
led_strip { 1, 33, 0, INTERPOLATE_POINTS, (-0.002160, -0.642832, 1.075384), (-0.002160, -0.511399, 0.862721), 144 }
|
||||
led_strip { 2, 55, 0, INTERPOLATE_POINTS, (-0.005654, -0.530914, -0.844235), (-0.005654, -0.662347, -1.056898), 144 }
|
||||
led_strip { 2, 56, 0, INTERPOLATE_POINTS, (0.005654, -0.651981, -1.069729), (0.005654, -0.520548, -0.857067), 144 }
|
||||
led_strip { 2, 57, 0, INTERPOLATE_POINTS, (-0.009149, -0.521766, -0.849889), (-0.009149, -0.653199, -1.062552), 144 }
|
||||
led_strip { 2, 58, 0, INTERPOLATE_POINTS, (0.002160, -0.642832, -1.075384), (0.002160, -0.511399, -0.862721), 144 }
|
||||
led_strip { 3, 80, 0, INTERPOLATE_POINTS, (0.005654, 0.530914, -0.844235), (0.005654, 0.662347, -1.056898), 144 }
|
||||
led_strip { 3, 81, 0, INTERPOLATE_POINTS, (-0.005654, 0.651981, -1.069729), (-0.005654, 0.520548, -0.857067), 144 }
|
||||
led_strip { 3, 82, 0, INTERPOLATE_POINTS, (0.009149, 0.521766, -0.849889), (0.009149, 0.653199, -1.062552), 144 }
|
||||
led_strip { 3, 83, 0, INTERPOLATE_POINTS, (-0.002160, 0.642832, -1.075384), (-0.002160, 0.511399, -0.862721), 144 }
|
||||
led_strip { 4, 105, 0, INTERPOLATE_POINTS, (0.849889, 0.009149, 0.521766), (1.062552, 0.009149, 0.653199), 144 }
|
||||
led_strip { 4, 106, 0, INTERPOLATE_POINTS, (1.064075, -0.009149, 0.661129), (0.851413, -0.009149, 0.529696), 144 }
|
||||
led_strip { 4, 107, 0, INTERPOLATE_POINTS, (0.844235, 0.005654, 0.530914), (1.056898, 0.005654, 0.662347), 144 }
|
||||
led_strip { 4, 108, 0, INTERPOLATE_POINTS, (1.058421, -0.012643, 0.670278), (0.845758, -0.012643, 0.538845), 144 }
|
||||
led_strip { 5, 130, 0, INTERPOLATE_POINTS, (-0.844235, 0.005654, 0.530914), (-1.056898, 0.005654, 0.662347), 144 }
|
||||
led_strip { 5, 131, 0, INTERPOLATE_POINTS, (-1.069729, -0.005654, 0.651981), (-0.857067, -0.005654, 0.520548), 144 }
|
||||
led_strip { 5, 132, 0, INTERPOLATE_POINTS, (-0.849889, 0.009149, 0.521766), (-1.062552, 0.009149, 0.653199), 144 }
|
||||
led_strip { 5, 133, 0, INTERPOLATE_POINTS, (-1.075384, -0.002160, 0.642832), (-0.862721, -0.002160, 0.511399), 144 }
|
||||
led_strip { 6, 155, 0, INTERPOLATE_POINTS, (-0.849889, 0.009149, -0.521766), (-1.062552, 0.009149, -0.653199), 144 }
|
||||
led_strip { 6, 156, 0, INTERPOLATE_POINTS, (-1.064075, -0.009149, -0.661129), (-0.851413, -0.009149, -0.529696), 144 }
|
||||
led_strip { 6, 157, 0, INTERPOLATE_POINTS, (-0.844235, 0.005654, -0.530914), (-1.056898, 0.005654, -0.662347), 144 }
|
||||
led_strip { 6, 158, 0, INTERPOLATE_POINTS, (-1.058421, -0.012643, -0.670278), (-0.845758, -0.012643, -0.538845), 144 }
|
||||
led_strip { 7, 180, 0, INTERPOLATE_POINTS, (0.853383, 0.000000, -0.516112), (1.066046, 0.000000, -0.647545), 144 }
|
||||
led_strip { 7, 181, 0, INTERPOLATE_POINTS, (1.060581, 0.000000, -0.666783), (0.847918, 0.000000, -0.535351), 144 }
|
||||
led_strip { 7, 182, 0, INTERPOLATE_POINTS, (0.849889, -0.009149, -0.521766), (1.062552, -0.009149, -0.653199), 144 }
|
||||
led_strip { 7, 183, 0, INTERPOLATE_POINTS, (1.057086, -0.009149, -0.672437), (0.844424, -0.009149, -0.541005), 144 }
|
||||
led_strip { 8, 205, 0, INTERPOLATE_POINTS, (0.530914, 0.844235, -0.005654), (0.662347, 1.056898, -0.005654), 144 }
|
||||
led_strip { 8, 206, 0, INTERPOLATE_POINTS, (0.651981, 1.069729, 0.005654), (0.520548, 0.857067, 0.005654), 144 }
|
||||
led_strip { 8, 207, 0, INTERPOLATE_POINTS, (0.521766, 0.849889, -0.009149), (0.653199, 1.062552, -0.009149), 144 }
|
||||
led_strip { 8, 208, 0, INTERPOLATE_POINTS, (0.642832, 1.075384, 0.002160), (0.511399, 0.862721, 0.002160), 144 }
|
||||
led_strip { 9, 230, 0, INTERPOLATE_POINTS, (-0.530914, 0.844235, -0.005654), (-0.662347, 1.056898, -0.005654), 144 }
|
||||
led_strip { 9, 231, 0, INTERPOLATE_POINTS, (-0.651981, 1.069729, 0.005654), (-0.520548, 0.857067, 0.005654), 144 }
|
||||
led_strip { 9, 232, 0, INTERPOLATE_POINTS, (-0.530914, 0.844235, 0.005654), (-0.662347, 1.056898, 0.005654), 144 }
|
||||
led_strip { 9, 233, 0, INTERPOLATE_POINTS, (-0.651981, 1.069729, 0.016962), (-0.520548, 0.857067, 0.016962), 144 }
|
||||
led_strip { 10, 255, 0, INTERPOLATE_POINTS, (-0.530914, -0.844235, 0.005654), (-0.662347, -1.056898, 0.005654), 144 }
|
||||
led_strip { 10, 256, 0, INTERPOLATE_POINTS, (-0.651981, -1.069729, -0.005654), (-0.520548, -0.857067, -0.005654), 144 }
|
||||
led_strip { 10, 257, 0, INTERPOLATE_POINTS, (-0.530914, -0.844235, -0.005654), (-0.662347, -1.056898, -0.005654), 144 }
|
||||
led_strip { 10, 258, 0, INTERPOLATE_POINTS, (-0.651981, -1.069729, -0.016962), (-0.520548, -0.857067, -0.016962), 144 }
|
||||
led_strip { 11, 280, 0, INTERPOLATE_POINTS, (0.530914, -0.844235, 0.005654), (0.662347, -1.056898, 0.005654), 144 }
|
||||
led_strip { 11, 281, 0, INTERPOLATE_POINTS, (0.651981, -1.069729, -0.005654), (0.520548, -0.857067, -0.005654), 144 }
|
||||
led_strip { 11, 282, 0, INTERPOLATE_POINTS, (0.521766, -0.849889, 0.009149), (0.653199, -1.062552, 0.009149), 144 }
|
||||
led_strip { 11, 283, 0, INTERPOLATE_POINTS, (0.642832, -1.075384, -0.002160), (0.511399, -0.862721, -0.002160), 144 }
|
||||
led_strip { 12, 306, 0, INTERPOLATE_POINTS, (0.000000, 0.009619, 0.997267), (0.000000, 0.009619, 1.247267), 144 }
|
||||
led_strip { 12, 307, 0, INTERPOLATE_POINTS, (0.000000, -0.009619, 1.252733), (0.000000, -0.009619, 1.002733), 144 }
|
||||
led_strip { 12, 308, 0, INTERPOLATE_POINTS, (-0.008090, 0.005000, 0.996910), (-0.008090, 0.005000, 1.246910), 144 }
|
||||
led_strip { 12, 309, 0, INTERPOLATE_POINTS, (-0.008090, -0.014239, 1.252375), (-0.008090, -0.014239, 1.002375), 144 }
|
||||
led_strip { 13, 331, 0, INTERPOLATE_POINTS, (0.506416, 0.303363, 0.803834), (0.631416, 0.380617, 1.006088), 144 }
|
||||
led_strip { 13, 332, 0, INTERPOLATE_POINTS, (0.618584, 0.391925, 1.016455), (0.493584, 0.314671, 0.814200), 144 }
|
||||
led_strip { 13, 333, 0, INTERPOLATE_POINTS, (0.505000, 0.312107, 0.800927), (0.630000, 0.389361, 1.003181), 144 }
|
||||
led_strip { 13, 334, 0, INTERPOLATE_POINTS, (0.617168, 0.400670, 1.013548), (0.492168, 0.323415, 0.811293), 144 }
|
||||
led_strip { 14, 356, 0, INTERPOLATE_POINTS, (-0.490851, 0.312982, 0.809779), (-0.615851, 0.390236, 1.012033), 144 }
|
||||
led_strip { 14, 357, 0, INTERPOLATE_POINTS, (-0.634149, 0.382306, 1.010509), (-0.509149, 0.305052, 0.808255), 144 }
|
||||
led_strip { 14, 358, 0, INTERPOLATE_POINTS, (-0.496910, 0.317107, 0.804017), (-0.621910, 0.394361, 1.006271), 144 }
|
||||
led_strip { 14, 359, 0, INTERPOLATE_POINTS, (-0.640207, 0.386431, 1.004748), (-0.515207, 0.309177, 0.802493), 144 }
|
||||
led_strip { 15, 381, 0, INTERPOLATE_POINTS, (0.312982, 0.809779, 0.490851), (0.390236, 1.012033, 0.615851), 144 }
|
||||
led_strip { 15, 382, 0, INTERPOLATE_POINTS, (0.382306, 1.010509, 0.634149), (0.305052, 0.808255, 0.509149), 144 }
|
||||
led_strip { 15, 383, 0, INTERPOLATE_POINTS, (0.304017, 0.812107, 0.491910), (0.381271, 1.014361, 0.616910), 144 }
|
||||
led_strip { 15, 384, 0, INTERPOLATE_POINTS, (0.373341, 1.012838, 0.635207), (0.296086, 0.810584, 0.510207), 144 }
|
||||
led_strip { 16, 406, 0, INTERPOLATE_POINTS, (-0.312982, 0.809779, 0.490851), (-0.390236, 1.012033, 0.615851), 144 }
|
||||
led_strip { 16, 407, 0, INTERPOLATE_POINTS, (-0.382306, 1.010509, 0.634149), (-0.305052, 0.808255, 0.509149), 144 }
|
||||
led_strip { 16, 408, 0, INTERPOLATE_POINTS, (-0.317107, 0.804017, 0.496910), (-0.394361, 1.006271, 0.621910), 144 }
|
||||
led_strip { 16, 409, 0, INTERPOLATE_POINTS, (-0.386431, 1.004748, 0.640207), (-0.309177, 0.802493, 0.515207), 144 }
|
||||
led_strip { 17, 431, 0, INTERPOLATE_POINTS, (0.506416, -0.303363, 0.803834), (0.631416, -0.380617, 1.006088), 144 }
|
||||
led_strip { 17, 432, 0, INTERPOLATE_POINTS, (0.618584, -0.391925, 1.016455), (0.493584, -0.314671, 0.814200), 144 }
|
||||
led_strip { 17, 433, 0, INTERPOLATE_POINTS, (0.500000, -0.299017, 0.809017), (0.625000, -0.376271, 1.011271), 144 }
|
||||
led_strip { 17, 434, 0, INTERPOLATE_POINTS, (0.612168, -0.387580, 1.021638), (0.487168, -0.310325, 0.819384), 144 }
|
||||
led_strip { 18, 456, 0, INTERPOLATE_POINTS, (-0.506416, -0.303363, 0.803834), (-0.631416, -0.380617, 1.006088), 144 }
|
||||
led_strip { 18, 457, 0, INTERPOLATE_POINTS, (-0.618584, -0.391925, 1.016455), (-0.493584, -0.314671, 0.814200), 144 }
|
||||
led_strip { 18, 458, 0, INTERPOLATE_POINTS, (-0.505000, -0.312107, 0.800927), (-0.630000, -0.389361, 1.003181), 144 }
|
||||
led_strip { 18, 459, 0, INTERPOLATE_POINTS, (-0.617168, -0.400670, 1.013548), (-0.492168, -0.323415, 0.811293), 144 }
|
||||
led_strip { 19, 481, 0, INTERPOLATE_POINTS, (-0.303363, -0.803834, 0.506416), (-0.380617, -1.006088, 0.631416), 144 }
|
||||
led_strip { 19, 482, 0, INTERPOLATE_POINTS, (-0.391925, -1.016455, 0.618584), (-0.314671, -0.814200, 0.493584), 144 }
|
||||
led_strip { 19, 483, 0, INTERPOLATE_POINTS, (-0.312107, -0.800927, 0.505000), (-0.389361, -1.003181, 0.630000), 144 }
|
||||
led_strip { 19, 484, 0, INTERPOLATE_POINTS, (-0.400670, -1.013548, 0.617168), (-0.323415, -0.811293, 0.492168), 144 }
|
||||
led_strip { 20, 506, 0, INTERPOLATE_POINTS, (0.312982, -0.809779, 0.490851), (0.390236, -1.012033, 0.615851), 144 }
|
||||
led_strip { 20, 507, 0, INTERPOLATE_POINTS, (0.382306, -1.010509, 0.634149), (0.305052, -0.808255, 0.509149), 144 }
|
||||
led_strip { 20, 508, 0, INTERPOLATE_POINTS, (0.317107, -0.804017, 0.496910), (0.394361, -1.006271, 0.621910), 144 }
|
||||
led_strip { 20, 509, 0, INTERPOLATE_POINTS, (0.386431, -1.004748, 0.640207), (0.309177, -0.802493, 0.515207), 144 }
|
||||
led_strip { 21, 531, 0, INTERPOLATE_POINTS, (0.000000, 0.009619, -0.997267), (0.000000, 0.009619, -1.247267), 144 }
|
||||
led_strip { 21, 532, 0, INTERPOLATE_POINTS, (0.000000, -0.009619, -1.252733), (0.000000, -0.009619, -1.002733), 144 }
|
||||
led_strip { 21, 533, 0, INTERPOLATE_POINTS, (0.008090, 0.005000, -0.996910), (0.008090, 0.005000, -1.246910), 144 }
|
||||
led_strip { 21, 534, 0, INTERPOLATE_POINTS, (0.008090, -0.014239, -1.252375), (0.008090, -0.014239, -1.002375), 144 }
|
||||
led_strip { 22, 556, 0, INTERPOLATE_POINTS, (-0.506416, -0.303363, -0.803834), (-0.631416, -0.380617, -1.006088), 144 }
|
||||
led_strip { 22, 557, 0, INTERPOLATE_POINTS, (-0.618584, -0.391925, -1.016455), (-0.493584, -0.314671, -0.814200), 144 }
|
||||
led_strip { 22, 558, 0, INTERPOLATE_POINTS, (-0.500000, -0.299017, -0.809017), (-0.625000, -0.376271, -1.011271), 144 }
|
||||
led_strip { 22, 559, 0, INTERPOLATE_POINTS, (-0.612168, -0.387580, -1.021638), (-0.487168, -0.310325, -0.819384), 144 }
|
||||
led_strip { 23, 581, 0, INTERPOLATE_POINTS, (0.506416, -0.303363, -0.803834), (0.631416, -0.380617, -1.006088), 144 }
|
||||
led_strip { 23, 582, 0, INTERPOLATE_POINTS, (0.618584, -0.391925, -1.016455), (0.493584, -0.314671, -0.814200), 144 }
|
||||
led_strip { 23, 583, 0, INTERPOLATE_POINTS, (0.505000, -0.312107, -0.800927), (0.630000, -0.389361, -1.003181), 144 }
|
||||
led_strip { 23, 584, 0, INTERPOLATE_POINTS, (0.617168, -0.400670, -1.013548), (0.492168, -0.323415, -0.811293), 144 }
|
||||
led_strip { 24, 606, 0, INTERPOLATE_POINTS, (-0.312982, -0.809779, -0.490851), (-0.390236, -1.012033, -0.615851), 144 }
|
||||
led_strip { 24, 607, 0, INTERPOLATE_POINTS, (-0.382306, -1.010509, -0.634149), (-0.305052, -0.808255, -0.509149), 144 }
|
||||
led_strip { 24, 608, 0, INTERPOLATE_POINTS, (-0.317107, -0.804017, -0.496910), (-0.394361, -1.006271, -0.621910), 144 }
|
||||
led_strip { 24, 609, 0, INTERPOLATE_POINTS, (-0.386431, -1.004748, -0.640207), (-0.309177, -0.802493, -0.515207), 144 }
|
||||
led_strip { 25, 631, 0, INTERPOLATE_POINTS, (0.312982, -0.809779, -0.490851), (0.390236, -1.012033, -0.615851), 144 }
|
||||
led_strip { 25, 632, 0, INTERPOLATE_POINTS, (0.382306, -1.010509, -0.634149), (0.305052, -0.808255, -0.509149), 144 }
|
||||
led_strip { 25, 633, 0, INTERPOLATE_POINTS, (0.304017, -0.812107, -0.491910), (0.381271, -1.014361, -0.616910), 144 }
|
||||
led_strip { 25, 634, 0, INTERPOLATE_POINTS, (0.373341, -1.012838, -0.635207), (0.296086, -0.810584, -0.510207), 144 }
|
||||
led_strip { 26, 656, 0, INTERPOLATE_POINTS, (-0.490851, 0.312982, -0.809779), (-0.615851, 0.390236, -1.012033), 144 }
|
||||
led_strip { 26, 657, 0, INTERPOLATE_POINTS, (-0.634149, 0.382306, -1.010509), (-0.509149, 0.305052, -0.808255), 144 }
|
||||
led_strip { 26, 658, 0, INTERPOLATE_POINTS, (-0.491910, 0.304017, -0.812107), (-0.616910, 0.381271, -1.014361), 144 }
|
||||
led_strip { 26, 659, 0, INTERPOLATE_POINTS, (-0.635207, 0.373341, -1.012838), (-0.510207, 0.296086, -0.810584), 144 }
|
||||
led_strip { 27, 681, 0, INTERPOLATE_POINTS, (0.490851, 0.312982, -0.809779), (0.615851, 0.390236, -1.012033), 144 }
|
||||
led_strip { 27, 682, 0, INTERPOLATE_POINTS, (0.634149, 0.382306, -1.010509), (0.509149, 0.305052, -0.808255), 144 }
|
||||
led_strip { 27, 683, 0, INTERPOLATE_POINTS, (0.496910, 0.317107, -0.804017), (0.621910, 0.394361, -1.006271), 144 }
|
||||
led_strip { 27, 684, 0, INTERPOLATE_POINTS, (0.640207, 0.386431, -1.004748), (0.515207, 0.309177, -0.802493), 144 }
|
||||
led_strip { 28, 706, 0, INTERPOLATE_POINTS, (0.312982, 0.809779, -0.490851), (0.390236, 1.012033, -0.615851), 144 }
|
||||
led_strip { 28, 707, 0, INTERPOLATE_POINTS, (0.382306, 1.010509, -0.634149), (0.305052, 0.808255, -0.509149), 144 }
|
||||
led_strip { 28, 708, 0, INTERPOLATE_POINTS, (0.317107, 0.804017, -0.496910), (0.394361, 1.006271, -0.621910), 144 }
|
||||
led_strip { 28, 709, 0, INTERPOLATE_POINTS, (0.386431, 1.004748, -0.640207), (0.309177, 0.802493, -0.515207), 144 }
|
||||
led_strip { 29, 731, 0, INTERPOLATE_POINTS, (-0.312982, 0.809779, -0.490851), (-0.390236, 1.012033, -0.615851), 144 }
|
||||
led_strip { 29, 732, 0, INTERPOLATE_POINTS, (-0.382306, 1.010509, -0.634149), (-0.305052, 0.808255, -0.509149), 144 }
|
||||
led_strip { 29, 733, 0, INTERPOLATE_POINTS, (-0.304017, 0.812107, -0.491910), (-0.381271, 1.014361, -0.616910), 144 }
|
||||
led_strip { 29, 734, 0, INTERPOLATE_POINTS, (-0.373341, 1.012838, -0.635207), (-0.296086, 0.810584, -0.510207), 144 }
|
||||
led_strip { 30, 756, 0, INTERPOLATE_POINTS, (0.997267, 0.000000, -0.009619), (1.247267, 0.000000, -0.009619), 144 }
|
||||
led_strip { 30, 757, 0, INTERPOLATE_POINTS, (1.252733, 0.000000, 0.009619), (1.002733, 0.000000, 0.009619), 144 }
|
||||
led_strip { 30, 758, 0, INTERPOLATE_POINTS, (0.996910, 0.008090, -0.005000), (1.246910, 0.008090, -0.005000), 144 }
|
||||
led_strip { 30, 759, 0, INTERPOLATE_POINTS, (1.252375, 0.008090, 0.014239), (1.002375, 0.008090, 0.014239), 144 }
|
||||
led_strip { 31, 781, 0, INTERPOLATE_POINTS, (0.803834, 0.506416, 0.303363), (1.006088, 0.631416, 0.380617), 144 }
|
||||
led_strip { 31, 782, 0, INTERPOLATE_POINTS, (1.016455, 0.618584, 0.391925), (0.814200, 0.493584, 0.314671), 144 }
|
||||
led_strip { 31, 783, 0, INTERPOLATE_POINTS, (0.800927, 0.505000, 0.312107), (1.003181, 0.630000, 0.389361), 144 }
|
||||
led_strip { 31, 784, 0, INTERPOLATE_POINTS, (1.013548, 0.617168, 0.400670), (0.811293, 0.492168, 0.323415), 144 }
|
||||
led_strip { 32, 806, 0, INTERPOLATE_POINTS, (0.803834, -0.506416, 0.303363), (1.006088, -0.631416, 0.380617), 144 }
|
||||
led_strip { 32, 807, 0, INTERPOLATE_POINTS, (1.016455, -0.618584, 0.391925), (0.814200, -0.493584, 0.314671), 144 }
|
||||
led_strip { 32, 808, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.299017), (1.011271, -0.625000, 0.376271), 144 }
|
||||
led_strip { 32, 809, 0, INTERPOLATE_POINTS, (1.021638, -0.612168, 0.387580), (0.819384, -0.487168, 0.310325), 144 }
|
||||
led_strip { 33, 831, 0, INTERPOLATE_POINTS, (-0.997267, 0.000000, 0.009619), (-1.247267, 0.000000, 0.009619), 144 }
|
||||
led_strip { 33, 832, 0, INTERPOLATE_POINTS, (-1.252733, 0.000000, -0.009619), (-1.002733, 0.000000, -0.009619), 144 }
|
||||
led_strip { 33, 833, 0, INTERPOLATE_POINTS, (-0.996910, 0.008090, 0.005000), (-1.246910, 0.008090, 0.005000), 144 }
|
||||
led_strip { 33, 834, 0, INTERPOLATE_POINTS, (-1.252375, 0.008090, -0.014239), (-1.002375, 0.008090, -0.014239), 144 }
|
||||
led_strip { 34, 856, 0, INTERPOLATE_POINTS, (-0.809779, 0.490851, 0.312982), (-1.012033, 0.615851, 0.390236), 144 }
|
||||
led_strip { 34, 857, 0, INTERPOLATE_POINTS, (-1.010509, 0.634149, 0.382306), (-0.808255, 0.509149, 0.305052), 144 }
|
||||
led_strip { 34, 858, 0, INTERPOLATE_POINTS, (-0.804017, 0.496910, 0.317107), (-1.006271, 0.621910, 0.394361), 144 }
|
||||
led_strip { 34, 859, 0, INTERPOLATE_POINTS, (-1.004748, 0.640207, 0.386431), (-0.802493, 0.515207, 0.309177), 144 }
|
||||
led_strip { 35, 881, 0, INTERPOLATE_POINTS, (-0.809779, -0.490851, 0.312982), (-1.012033, -0.615851, 0.390236), 144 }
|
||||
led_strip { 35, 882, 0, INTERPOLATE_POINTS, (-1.010509, -0.634149, 0.382306), (-0.808255, -0.509149, 0.305052), 144 }
|
||||
led_strip { 35, 883, 0, INTERPOLATE_POINTS, (-0.812107, -0.491910, 0.304017), (-1.014361, -0.616910, 0.381271), 144 }
|
||||
led_strip { 35, 884, 0, INTERPOLATE_POINTS, (-1.012838, -0.635207, 0.373341), (-0.810584, -0.510207, 0.296086), 144 }
|
||||
led_strip { 36, 906, 0, INTERPOLATE_POINTS, (-0.803834, 0.506416, -0.303363), (-1.006088, 0.631416, -0.380617), 144 }
|
||||
led_strip { 36, 907, 0, INTERPOLATE_POINTS, (-1.016455, 0.618584, -0.391925), (-0.814200, 0.493584, -0.314671), 144 }
|
||||
led_strip { 36, 908, 0, INTERPOLATE_POINTS, (-0.800927, 0.505000, -0.312107), (-1.003181, 0.630000, -0.389361), 144 }
|
||||
led_strip { 36, 909, 0, INTERPOLATE_POINTS, (-1.013548, 0.617168, -0.400670), (-0.811293, 0.492168, -0.323415), 144 }
|
||||
led_strip { 37, 931, 0, INTERPOLATE_POINTS, (-0.803834, -0.506416, -0.303363), (-1.006088, -0.631416, -0.380617), 144 }
|
||||
led_strip { 37, 932, 0, INTERPOLATE_POINTS, (-1.016455, -0.618584, -0.391925), (-0.814200, -0.493584, -0.314671), 144 }
|
||||
led_strip { 37, 933, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.299017), (-1.011271, -0.625000, -0.376271), 144 }
|
||||
led_strip { 37, 934, 0, INTERPOLATE_POINTS, (-1.021638, -0.612168, -0.387580), (-0.819384, -0.487168, -0.310325), 144 }
|
||||
led_strip { 38, 956, 0, INTERPOLATE_POINTS, (0.803834, 0.506416, -0.303363), (1.006088, 0.631416, -0.380617), 144 }
|
||||
led_strip { 38, 957, 0, INTERPOLATE_POINTS, (1.016455, 0.618584, -0.391925), (0.814200, 0.493584, -0.314671), 144 }
|
||||
led_strip { 38, 958, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.299017), (1.011271, 0.625000, -0.376271), 144 }
|
||||
led_strip { 38, 959, 0, INTERPOLATE_POINTS, (1.021638, 0.612168, -0.387580), (0.819384, 0.487168, -0.310325), 144 }
|
||||
led_strip { 39, 981, 0, INTERPOLATE_POINTS, (0.803834, -0.506416, -0.303363), (1.006088, -0.631416, -0.380617), 144 }
|
||||
led_strip { 39, 982, 0, INTERPOLATE_POINTS, (1.016455, -0.618584, -0.391925), (0.814200, -0.493584, -0.314671), 144 }
|
||||
led_strip { 39, 983, 0, INTERPOLATE_POINTS, (0.800927, -0.505000, -0.312107), (1.003181, -0.630000, -0.389361), 144 }
|
||||
led_strip { 39, 984, 0, INTERPOLATE_POINTS, (1.013548, -0.617168, -0.400670), (0.811293, -0.492168, -0.323415), 144 }
|
||||
led_strip { 40, 1006, 0, INTERPOLATE_POINTS, (0.009619, 0.997267, 0.000000), (0.009619, 1.247267, 0.000000), 144 }
|
||||
led_strip { 40, 1007, 0, INTERPOLATE_POINTS, (-0.009619, 1.252733, 0.000000), (-0.009619, 1.002733, 0.000000), 144 }
|
||||
led_strip { 40, 1008, 0, INTERPOLATE_POINTS, (0.005000, 0.996910, -0.008090), (0.005000, 1.246910, -0.008090), 144 }
|
||||
led_strip { 40, 1009, 0, INTERPOLATE_POINTS, (-0.014239, 1.252375, -0.008090), (-0.014239, 1.002375, -0.008090), 144 }
|
||||
led_strip { 41, 1031, 0, INTERPOLATE_POINTS, (0.009619, -0.997267, 0.000000), (0.009619, -1.247267, 0.000000), 144 }
|
||||
led_strip { 41, 1032, 0, INTERPOLATE_POINTS, (-0.009619, -1.252733, 0.000000), (-0.009619, -1.002733, 0.000000), 144 }
|
||||
led_strip { 41, 1033, 0, INTERPOLATE_POINTS, (0.005000, -0.996910, 0.008090), (0.005000, -1.246910, 0.008090), 144 }
|
||||
led_strip { 41, 1034, 0, INTERPOLATE_POINTS, (-0.014239, -1.252375, 0.008090), (-0.014239, -1.002375, 0.008090), 144 }
|
||||
END_OF_ASSEMBLY_FILE
|
Binary file not shown.
|
@ -0,0 +1,452 @@
|
|||
control_box_count 42
|
||||
led_strip_count 240
|
||||
|
||||
control_box { 0, "192.168.1.200", (0.000000, 0.525731, 0.850651) }
|
||||
control_box { 1, "192.168.1.201", (0.000000, -0.525731, 0.850651) }
|
||||
control_box { 2, "192.168.1.202", (0.000000, -0.525731, -0.850651) }
|
||||
control_box { 3, "192.168.1.203", (0.000000, 0.525731, -0.850651) }
|
||||
control_box { 4, "192.168.1.204", (0.850651, 0.000000, 0.525731) }
|
||||
control_box { 5, "192.168.1.205", (-0.850651, 0.000000, 0.525731) }
|
||||
control_box { 6, "192.168.1.206", (-0.850651, 0.000000, -0.525731) }
|
||||
control_box { 7, "192.168.1.207", (0.850651, 0.000000, -0.525731) }
|
||||
control_box { 8, "192.168.1.208", (0.525731, 0.850651, 0.000000) }
|
||||
control_box { 9, "192.168.1.209", (-0.525731, 0.850651, 0.000000) }
|
||||
control_box { 10, "192.168.1.210", (-0.525731, -0.850651, 0.000000) }
|
||||
control_box { 11, "192.168.1.211", (0.525731, -0.850651, 0.000000) }
|
||||
control_box { 12, "192.168.1.212", (0.000000, 0.000000, 1.000000) }
|
||||
control_box { 13, "192.168.1.213", (0.500000, 0.309017, 0.809017) }
|
||||
control_box { 14, "192.168.1.214", (-0.500000, 0.309017, 0.809017) }
|
||||
control_box { 15, "192.168.1.215", (0.309017, 0.809017, 0.500000) }
|
||||
control_box { 16, "192.168.1.216", (-0.309017, 0.809017, 0.500000) }
|
||||
control_box { 17, "192.168.1.217", (0.500000, -0.309017, 0.809017) }
|
||||
control_box { 18, "192.168.1.218", (-0.500000, -0.309017, 0.809017) }
|
||||
control_box { 19, "192.168.1.219", (-0.309017, -0.809017, 0.500000) }
|
||||
control_box { 20, "192.168.1.220", (0.309017, -0.809017, 0.500000) }
|
||||
control_box { 21, "192.168.1.221", (0.000000, 0.000000, -1.000000) }
|
||||
control_box { 22, "192.168.1.222", (-0.500000, -0.309017, -0.809017) }
|
||||
control_box { 23, "192.168.1.223", (0.500000, -0.309017, -0.809017) }
|
||||
control_box { 24, "192.168.1.224", (-0.309017, -0.809017, -0.500000) }
|
||||
control_box { 25, "192.168.1.225", (0.309017, -0.809017, -0.500000) }
|
||||
control_box { 26, "192.168.1.226", (-0.500000, 0.309017, -0.809017) }
|
||||
control_box { 27, "192.168.1.227", (0.500000, 0.309017, -0.809017) }
|
||||
control_box { 28, "192.168.1.228", (0.309017, 0.809017, -0.500000) }
|
||||
control_box { 29, "192.168.1.229", (-0.309017, 0.809017, -0.500000) }
|
||||
control_box { 30, "192.168.1.230", (1.000000, 0.000000, 0.000000) }
|
||||
control_box { 31, "192.168.1.231", (0.809017, 0.500000, 0.309017) }
|
||||
control_box { 32, "192.168.1.232", (0.809017, -0.500000, 0.309017) }
|
||||
control_box { 33, "192.168.1.233", (-1.000000, 0.000000, 0.000000) }
|
||||
control_box { 34, "192.168.1.234", (-0.809017, 0.500000, 0.309017) }
|
||||
control_box { 35, "192.168.1.235", (-0.809017, -0.500000, 0.309017) }
|
||||
control_box { 36, "192.168.1.236", (-0.809017, 0.500000, -0.309017) }
|
||||
control_box { 37, "192.168.1.237", (-0.809017, -0.500000, -0.309017) }
|
||||
control_box { 38, "192.168.1.238", (0.809017, 0.500000, -0.309017) }
|
||||
control_box { 39, "192.168.1.239", (0.809017, -0.500000, -0.309017) }
|
||||
control_box { 40, "192.168.1.240", (0.000000, 1.000000, 0.000000) }
|
||||
control_box { 41, "192.168.1.241", (0.000000, -1.000000, 0.000000) }
|
||||
|
||||
led_strip { 0, 0, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 0, 1, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 0, 2, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 0, 3, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 0, 4, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, 0.850651), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 1, 25, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 1, 26, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 1, 27, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 1, 28, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 1, 29, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, 0.850651), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 2, 50, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 2, 51, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 2, 52, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 2, 53, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 2, 54, 0, INTERPOLATE_POINTS, (0.000000, -0.525731, -0.850651), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 3, 75, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 3, 76, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 3, 77, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 3, 78, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 3, 79, 0, INTERPOLATE_POINTS, (0.000000, 0.525731, -0.850651), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 4, 100, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 4, 101, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 4, 102, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 4, 103, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 4, 104, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, 0.525731), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 5, 125, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 5, 126, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 5, 127, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 5, 128, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 5, 129, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, 0.525731), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 6, 150, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 6, 151, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 6, 152, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 6, 153, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 6, 154, 0, INTERPOLATE_POINTS, (-0.850651, 0.000000, -0.525731), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 7, 175, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 7, 176, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 7, 177, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 7, 178, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 7, 179, 0, INTERPOLATE_POINTS, (0.850651, 0.000000, -0.525731), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 8, 200, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 8, 201, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 8, 202, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 8, 203, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 8, 204, 0, INTERPOLATE_POINTS, (0.525731, 0.850651, 0.000000), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 9, 225, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 9, 226, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 9, 227, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 9, 228, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 9, 229, 0, INTERPOLATE_POINTS, (-0.525731, 0.850651, 0.000000), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 10, 250, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 10, 251, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 10, 252, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 10, 253, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 10, 254, 0, INTERPOLATE_POINTS, (-0.525731, -0.850651, 0.000000), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 11, 275, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 11, 276, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 11, 277, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 11, 278, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 11, 279, 0, INTERPOLATE_POINTS, (0.525731, -0.850651, 0.000000), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 12, 300, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 12, 301, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 12, 302, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 12, 303, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 12, 304, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 12, 305, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, 1.000000), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 13, 325, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 13, 326, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 13, 327, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 13, 328, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 13, 329, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 13, 330, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, 0.809017), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 14, 350, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 14, 351, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 14, 352, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 14, 353, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 14, 354, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 14, 355, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, 0.809017), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 15, 375, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 15, 376, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 15, 377, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 15, 378, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 15, 379, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 15, 380, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, 0.500000), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 16, 400, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 16, 401, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 16, 402, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 16, 403, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (0.000000, 0.525731, 0.850651), 144 }
|
||||
led_strip { 16, 404, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 16, 405, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, 0.500000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 17, 425, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 17, 426, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 17, 427, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 17, 428, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 17, 429, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 17, 430, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, 0.809017), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 18, 450, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 18, 451, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 18, 452, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 18, 453, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 18, 454, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (0.000000, 0.000000, 1.000000), 144 }
|
||||
led_strip { 18, 455, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, 0.809017), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 19, 475, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 19, 476, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (-0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 19, 477, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 19, 478, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 19, 479, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 19, 480, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, 0.500000), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 20, 500, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 20, 501, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 20, 502, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 20, 503, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.000000, -0.525731, 0.850651), 144 }
|
||||
led_strip { 20, 504, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 20, 505, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, 0.500000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 21, 525, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 21, 526, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 21, 527, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 21, 528, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 21, 529, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 21, 530, 0, INTERPOLATE_POINTS, (0.000000, 0.000000, -1.000000), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 22, 550, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (-0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 22, 551, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 22, 552, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 22, 553, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 22, 554, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 22, 555, 0, INTERPOLATE_POINTS, (-0.500000, -0.309017, -0.809017), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 23, 575, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 23, 576, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 23, 577, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 23, 578, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 23, 579, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 23, 580, 0, INTERPOLATE_POINTS, (0.500000, -0.309017, -0.809017), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 24, 600, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 24, 601, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 24, 602, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 24, 603, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 24, 604, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 24, 605, 0, INTERPOLATE_POINTS, (-0.309017, -0.809017, -0.500000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 25, 625, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 25, 626, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.000000, -1.000000, 0.000000), 144 }
|
||||
led_strip { 25, 627, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 25, 628, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.000000, -0.525731, -0.850651), 144 }
|
||||
led_strip { 25, 629, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 25, 630, 0, INTERPOLATE_POINTS, (0.309017, -0.809017, -0.500000), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 26, 650, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 26, 651, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 26, 652, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 26, 653, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (-0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 26, 654, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 26, 655, 0, INTERPOLATE_POINTS, (-0.500000, 0.309017, -0.809017), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 27, 675, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 27, 676, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 27, 677, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 27, 678, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 27, 679, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 27, 680, 0, INTERPOLATE_POINTS, (0.500000, 0.309017, -0.809017), (0.000000, 0.000000, -1.000000), 144 }
|
||||
led_strip { 28, 700, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 28, 701, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 28, 702, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 28, 703, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 28, 704, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 28, 705, 0, INTERPOLATE_POINTS, (0.309017, 0.809017, -0.500000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 29, 725, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 29, 726, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (0.000000, 1.000000, 0.000000), 144 }
|
||||
led_strip { 29, 727, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 29, 728, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (0.000000, 0.525731, -0.850651), 144 }
|
||||
led_strip { 29, 729, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 29, 730, 0, INTERPOLATE_POINTS, (-0.309017, 0.809017, -0.500000), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 30, 750, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 30, 751, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 30, 752, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 30, 753, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 30, 754, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 30, 755, 0, INTERPOLATE_POINTS, (1.000000, 0.000000, 0.000000), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 31, 775, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 31, 776, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 31, 777, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 31, 778, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 31, 779, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 31, 780, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, 0.309017), (0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 32, 800, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 32, 801, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 32, 802, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 32, 803, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 32, 804, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.500000, -0.309017, 0.809017), 144 }
|
||||
led_strip { 32, 805, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.309017), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 33, 825, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 33, 826, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 33, 827, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.809017, 0.500000, -0.309017), 144 } led_strip { 33, 829, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 33, 830, 0, INTERPOLATE_POINTS, (-1.000000, 0.000000, 0.000000), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 34, 850, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 34, 851, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.500000, 0.309017, 0.809017), 144 }
|
||||
led_strip { 34, 852, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 34, 853, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 34, 854, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-0.809017, 0.500000, -0.309017), 144 }
|
||||
led_strip { 34, 855, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, 0.309017), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 35, 875, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-0.850651, 0.000000, 0.525731), 144 }
|
||||
led_strip { 35, 876, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 35, 877, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-0.809017, -0.500000, -0.309017), 144 }
|
||||
led_strip { 35, 878, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 35, 879, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, 0.309017), (-0.309017, -0.809017, 0.500000), 144 } led_strip { 36, 900, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 36, 901, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 36, 902, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 36, 903, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 36, 904, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 36, 905, 0, INTERPOLATE_POINTS, (-0.809017, 0.500000, -0.309017), (-0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 37, 925, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 37, 926, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 37, 927, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 37, 928, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 37, 929, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 37, 930, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.309017), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 38, 950, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 38, 951, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.809017, 0.500000, 0.309017), 144 }
|
||||
led_strip { 38, 952, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 38, 953, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 38, 954, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.500000, 0.309017, -0.809017), 144 }
|
||||
led_strip { 38, 955, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.309017), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 39, 975, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 39, 976, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 39, 977, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.500000, -0.309017, -0.809017), 144 }
|
||||
led_strip { 39, 978, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.850651, 0.000000, -0.525731), 144 }
|
||||
led_strip { 39, 979, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (1.000000, 0.000000, 0.000000), 144 }
|
||||
led_strip { 39, 980, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, -0.309017), (0.809017, -0.500000, 0.309017), 144 }
|
||||
led_strip { 40, 1000, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 40, 1001, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 40, 1002, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (-0.309017, 0.809017, -0.500000), 144 }
|
||||
led_strip { 40, 1003, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (-0.525731, 0.850651, 0.000000), 144 }
|
||||
led_strip { 40, 1004, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (-0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 40, 1005, 0, INTERPOLATE_POINTS, (0.000000, 1.000000, 0.000000), (0.309017, 0.809017, 0.500000), 144 }
|
||||
led_strip { 41, 1025, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 41, 1026, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 41, 1027, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (-0.309017, -0.809017, 0.500000), 144 }
|
||||
led_strip { 41, 1028, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (-0.525731, -0.850651, 0.000000), 144 }
|
||||
led_strip { 41, 1029, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (-0.309017, -0.809017, -0.500000), 144 }
|
||||
led_strip { 41, 1030, 0, INTERPOLATE_POINTS, (0.000000, -1.000000, 0.000000), (0.309017, -0.809017, -0.500000), 144 }
|
||||
|
||||
led_strip { 0, 5, 0, INTERPOLATE_POINTS, (-0.005654, 0.530914, 0.844235), (-0.005654, 0.662347, 1.056898), 144 }
|
||||
led_strip { 0, 6, 0, INTERPOLATE_POINTS, (0.005654, 0.651981, 1.069729), (0.005654, 0.520548, 0.857067), 144 }
|
||||
led_strip { 0, 7, 0, INTERPOLATE_POINTS, (-0.009149, 0.521766, 0.849889), (-0.009149, 0.653199, 1.062552), 144 }
|
||||
led_strip { 0, 8, 0, INTERPOLATE_POINTS, (0.002160, 0.642832, 1.075384), (0.002160, 0.511399, 0.862721), 144 }
|
||||
led_strip { 1, 30, 0, INTERPOLATE_POINTS, (0.005654, -0.530914, 0.844235), (0.005654, -0.662347, 1.056898), 144 }
|
||||
led_strip { 1, 31, 0, INTERPOLATE_POINTS, (-0.005654, -0.651981, 1.069729), (-0.005654, -0.520548, 0.857067), 144 }
|
||||
led_strip { 1, 32, 0, INTERPOLATE_POINTS, (0.009149, -0.521766, 0.849889), (0.009149, -0.653199, 1.062552), 144 }
|
||||
led_strip { 1, 33, 0, INTERPOLATE_POINTS, (-0.002160, -0.642832, 1.075384), (-0.002160, -0.511399, 0.862721), 144 }
|
||||
led_strip { 2, 55, 0, INTERPOLATE_POINTS, (-0.005654, -0.530914, -0.844235), (-0.005654, -0.662347, -1.056898), 144 }
|
||||
led_strip { 2, 56, 0, INTERPOLATE_POINTS, (0.005654, -0.651981, -1.069729), (0.005654, -0.520548, -0.857067), 144 }
|
||||
led_strip { 2, 57, 0, INTERPOLATE_POINTS, (-0.009149, -0.521766, -0.849889), (-0.009149, -0.653199, -1.062552), 144 }
|
||||
led_strip { 2, 58, 0, INTERPOLATE_POINTS, (0.002160, -0.642832, -1.075384), (0.002160, -0.511399, -0.862721), 144 }
|
||||
led_strip { 3, 80, 0, INTERPOLATE_POINTS, (0.005654, 0.530914, -0.844235), (0.005654, 0.662347, -1.056898), 144 }
|
||||
led_strip { 3, 81, 0, INTERPOLATE_POINTS, (-0.005654, 0.651981, -1.069729), (-0.005654, 0.520548, -0.857067), 144 }
|
||||
led_strip { 3, 82, 0, INTERPOLATE_POINTS, (0.009149, 0.521766, -0.849889), (0.009149, 0.653199, -1.062552), 144 }
|
||||
led_strip { 3, 83, 0, INTERPOLATE_POINTS, (-0.002160, 0.642832, -1.075384), (-0.002160, 0.511399, -0.862721), 144 }
|
||||
led_strip { 4, 105, 0, INTERPOLATE_POINTS, (0.849889, 0.009149, 0.521766), (1.062552, 0.009149, 0.653199), 144 }
|
||||
led_strip { 4, 106, 0, INTERPOLATE_POINTS, (1.064075, -0.009149, 0.661129), (0.851413, -0.009149, 0.529696), 144 }
|
||||
led_strip { 4, 107, 0, INTERPOLATE_POINTS, (0.844235, 0.005654, 0.530914), (1.056898, 0.005654, 0.662347), 144 }
|
||||
led_strip { 4, 108, 0, INTERPOLATE_POINTS, (1.058421, -0.012643, 0.670278), (0.845758, -0.012643, 0.538845), 144 }
|
||||
led_strip { 5, 130, 0, INTERPOLATE_POINTS, (-0.844235, 0.005654, 0.530914), (-1.056898, 0.005654, 0.662347), 144 }
|
||||
led_strip { 5, 131, 0, INTERPOLATE_POINTS, (-1.069729, -0.005654, 0.651981), (-0.857067, -0.005654, 0.520548), 144 }
|
||||
led_strip { 5, 132, 0, INTERPOLATE_POINTS, (-0.849889, 0.009149, 0.521766), (-1.062552, 0.009149, 0.653199), 144 }
|
||||
led_strip { 5, 133, 0, INTERPOLATE_POINTS, (-1.075384, -0.002160, 0.642832), (-0.862721, -0.002160, 0.511399), 144 }
|
||||
led_strip { 6, 155, 0, INTERPOLATE_POINTS, (-0.849889, 0.009149, -0.521766), (-1.062552, 0.009149, -0.653199), 144 }
|
||||
led_strip { 6, 156, 0, INTERPOLATE_POINTS, (-1.064075, -0.009149, -0.661129), (-0.851413, -0.009149, -0.529696), 144 }
|
||||
led_strip { 6, 157, 0, INTERPOLATE_POINTS, (-0.844235, 0.005654, -0.530914), (-1.056898, 0.005654, -0.662347), 144 }
|
||||
led_strip { 6, 158, 0, INTERPOLATE_POINTS, (-1.058421, -0.012643, -0.670278), (-0.845758, -0.012643, -0.538845), 144 }
|
||||
led_strip { 7, 180, 0, INTERPOLATE_POINTS, (0.853383, 0.000000, -0.516112), (1.066046, 0.000000, -0.647545), 144 }
|
||||
led_strip { 7, 181, 0, INTERPOLATE_POINTS, (1.060581, 0.000000, -0.666783), (0.847918, 0.000000, -0.535351), 144 }
|
||||
led_strip { 7, 182, 0, INTERPOLATE_POINTS, (0.849889, -0.009149, -0.521766), (1.062552, -0.009149, -0.653199), 144 }
|
||||
led_strip { 7, 183, 0, INTERPOLATE_POINTS, (1.057086, -0.009149, -0.672437), (0.844424, -0.009149, -0.541005), 144 }
|
||||
led_strip { 8, 205, 0, INTERPOLATE_POINTS, (0.530914, 0.844235, -0.005654), (0.662347, 1.056898, -0.005654), 144 }
|
||||
led_strip { 8, 206, 0, INTERPOLATE_POINTS, (0.651981, 1.069729, 0.005654), (0.520548, 0.857067, 0.005654), 144 }
|
||||
led_strip { 8, 207, 0, INTERPOLATE_POINTS, (0.521766, 0.849889, -0.009149), (0.653199, 1.062552, -0.009149), 144 }
|
||||
led_strip { 8, 208, 0, INTERPOLATE_POINTS, (0.642832, 1.075384, 0.002160), (0.511399, 0.862721, 0.002160), 144 }
|
||||
led_strip { 9, 230, 0, INTERPOLATE_POINTS, (-0.530914, 0.844235, -0.005654), (-0.662347, 1.056898, -0.005654), 144 }
|
||||
led_strip { 9, 231, 0, INTERPOLATE_POINTS, (-0.651981, 1.069729, 0.005654), (-0.520548, 0.857067, 0.005654), 144 }
|
||||
led_strip { 9, 232, 0, INTERPOLATE_POINTS, (-0.530914, 0.844235, 0.005654), (-0.662347, 1.056898, 0.005654), 144 }
|
||||
led_strip { 9, 233, 0, INTERPOLATE_POINTS, (-0.651981, 1.069729, 0.016962), (-0.520548, 0.857067, 0.016962), 144 }
|
||||
led_strip { 10, 255, 0, INTERPOLATE_POINTS, (-0.530914, -0.844235, 0.005654), (-0.662347, -1.056898, 0.005654), 144 }
|
||||
led_strip { 10, 256, 0, INTERPOLATE_POINTS, (-0.651981, -1.069729, -0.005654), (-0.520548, -0.857067, -0.005654), 144 }
|
||||
led_strip { 10, 257, 0, INTERPOLATE_POINTS, (-0.530914, -0.844235, -0.005654), (-0.662347, -1.056898, -0.005654), 144 }
|
||||
led_strip { 10, 258, 0, INTERPOLATE_POINTS, (-0.651981, -1.069729, -0.016962), (-0.520548, -0.857067, -0.016962), 144 }
|
||||
led_strip { 11, 280, 0, INTERPOLATE_POINTS, (0.530914, -0.844235, 0.005654), (0.662347, -1.056898, 0.005654), 144 }
|
||||
led_strip { 11, 281, 0, INTERPOLATE_POINTS, (0.651981, -1.069729, -0.005654), (0.520548, -0.857067, -0.005654), 144 }
|
||||
led_strip { 11, 282, 0, INTERPOLATE_POINTS, (0.521766, -0.849889, 0.009149), (0.653199, -1.062552, 0.009149), 144 }
|
||||
led_strip { 11, 283, 0, INTERPOLATE_POINTS, (0.642832, -1.075384, -0.002160), (0.511399, -0.862721, -0.002160), 144 }
|
||||
led_strip { 12, 306, 0, INTERPOLATE_POINTS, (0.000000, 0.009619, 0.997267), (0.000000, 0.009619, 1.247267), 144 }
|
||||
led_strip { 12, 307, 0, INTERPOLATE_POINTS, (0.000000, -0.009619, 1.252733), (0.000000, -0.009619, 1.002733), 144 }
|
||||
led_strip { 12, 308, 0, INTERPOLATE_POINTS, (-0.008090, 0.005000, 0.996910), (-0.008090, 0.005000, 1.246910), 144 }
|
||||
led_strip { 12, 309, 0, INTERPOLATE_POINTS, (-0.008090, -0.014239, 1.252375), (-0.008090, -0.014239, 1.002375), 144 }
|
||||
led_strip { 13, 331, 0, INTERPOLATE_POINTS, (0.506416, 0.303363, 0.803834), (0.631416, 0.380617, 1.006088), 144 }
|
||||
led_strip { 13, 332, 0, INTERPOLATE_POINTS, (0.618584, 0.391925, 1.016455), (0.493584, 0.314671, 0.814200), 144 }
|
||||
led_strip { 13, 333, 0, INTERPOLATE_POINTS, (0.505000, 0.312107, 0.800927), (0.630000, 0.389361, 1.003181), 144 }
|
||||
led_strip { 13, 334, 0, INTERPOLATE_POINTS, (0.617168, 0.400670, 1.013548), (0.492168, 0.323415, 0.811293), 144 }
|
||||
led_strip { 14, 356, 0, INTERPOLATE_POINTS, (-0.490851, 0.312982, 0.809779), (-0.615851, 0.390236, 1.012033), 144 }
|
||||
led_strip { 14, 357, 0, INTERPOLATE_POINTS, (-0.634149, 0.382306, 1.010509), (-0.509149, 0.305052, 0.808255), 144 }
|
||||
led_strip { 14, 358, 0, INTERPOLATE_POINTS, (-0.496910, 0.317107, 0.804017), (-0.621910, 0.394361, 1.006271), 144 }
|
||||
led_strip { 14, 359, 0, INTERPOLATE_POINTS, (-0.640207, 0.386431, 1.004748), (-0.515207, 0.309177, 0.802493), 144 }
|
||||
led_strip { 15, 381, 0, INTERPOLATE_POINTS, (0.312982, 0.809779, 0.490851), (0.390236, 1.012033, 0.615851), 144 }
|
||||
led_strip { 15, 382, 0, INTERPOLATE_POINTS, (0.382306, 1.010509, 0.634149), (0.305052, 0.808255, 0.509149), 144 }
|
||||
led_strip { 15, 383, 0, INTERPOLATE_POINTS, (0.304017, 0.812107, 0.491910), (0.381271, 1.014361, 0.616910), 144 }
|
||||
led_strip { 15, 384, 0, INTERPOLATE_POINTS, (0.373341, 1.012838, 0.635207), (0.296086, 0.810584, 0.510207), 144 }
|
||||
led_strip { 16, 406, 0, INTERPOLATE_POINTS, (-0.312982, 0.809779, 0.490851), (-0.390236, 1.012033, 0.615851), 144 }
|
||||
led_strip { 16, 407, 0, INTERPOLATE_POINTS, (-0.382306, 1.010509, 0.634149), (-0.305052, 0.808255, 0.509149), 144 }
|
||||
led_strip { 16, 408, 0, INTERPOLATE_POINTS, (-0.317107, 0.804017, 0.496910), (-0.394361, 1.006271, 0.621910), 144 }
|
||||
led_strip { 16, 409, 0, INTERPOLATE_POINTS, (-0.386431, 1.004748, 0.640207), (-0.309177, 0.802493, 0.515207), 144 }
|
||||
led_strip { 17, 431, 0, INTERPOLATE_POINTS, (0.506416, -0.303363, 0.803834), (0.631416, -0.380617, 1.006088), 144 }
|
||||
led_strip { 17, 432, 0, INTERPOLATE_POINTS, (0.618584, -0.391925, 1.016455), (0.493584, -0.314671, 0.814200), 144 }
|
||||
led_strip { 17, 433, 0, INTERPOLATE_POINTS, (0.500000, -0.299017, 0.809017), (0.625000, -0.376271, 1.011271), 144 }
|
||||
led_strip { 17, 434, 0, INTERPOLATE_POINTS, (0.612168, -0.387580, 1.021638), (0.487168, -0.310325, 0.819384), 144 }
|
||||
led_strip { 18, 456, 0, INTERPOLATE_POINTS, (-0.506416, -0.303363, 0.803834), (-0.631416, -0.380617, 1.006088), 144 }
|
||||
led_strip { 18, 457, 0, INTERPOLATE_POINTS, (-0.618584, -0.391925, 1.016455), (-0.493584, -0.314671, 0.814200), 144 }
|
||||
led_strip { 18, 458, 0, INTERPOLATE_POINTS, (-0.505000, -0.312107, 0.800927), (-0.630000, -0.389361, 1.003181), 144 }
|
||||
led_strip { 18, 459, 0, INTERPOLATE_POINTS, (-0.617168, -0.400670, 1.013548), (-0.492168, -0.323415, 0.811293), 144 }
|
||||
led_strip { 19, 481, 0, INTERPOLATE_POINTS, (-0.303363, -0.803834, 0.506416), (-0.380617, -1.006088, 0.631416), 144 }
|
||||
led_strip { 19, 482, 0, INTERPOLATE_POINTS, (-0.391925, -1.016455, 0.618584), (-0.314671, -0.814200, 0.493584), 144 }
|
||||
led_strip { 19, 483, 0, INTERPOLATE_POINTS, (-0.312107, -0.800927, 0.505000), (-0.389361, -1.003181, 0.630000), 144 }
|
||||
led_strip { 19, 484, 0, INTERPOLATE_POINTS, (-0.400670, -1.013548, 0.617168), (-0.323415, -0.811293, 0.492168), 144 }
|
||||
led_strip { 20, 506, 0, INTERPOLATE_POINTS, (0.312982, -0.809779, 0.490851), (0.390236, -1.012033, 0.615851), 144 }
|
||||
led_strip { 20, 507, 0, INTERPOLATE_POINTS, (0.382306, -1.010509, 0.634149), (0.305052, -0.808255, 0.509149), 144 }
|
||||
led_strip { 20, 508, 0, INTERPOLATE_POINTS, (0.317107, -0.804017, 0.496910), (0.394361, -1.006271, 0.621910), 144 }
|
||||
led_strip { 20, 509, 0, INTERPOLATE_POINTS, (0.386431, -1.004748, 0.640207), (0.309177, -0.802493, 0.515207), 144 }
|
||||
led_strip { 21, 531, 0, INTERPOLATE_POINTS, (0.000000, 0.009619, -0.997267), (0.000000, 0.009619, -1.247267), 144 }
|
||||
led_strip { 21, 532, 0, INTERPOLATE_POINTS, (0.000000, -0.009619, -1.252733), (0.000000, -0.009619, -1.002733), 144 }
|
||||
led_strip { 21, 533, 0, INTERPOLATE_POINTS, (0.008090, 0.005000, -0.996910), (0.008090, 0.005000, -1.246910), 144 }
|
||||
led_strip { 21, 534, 0, INTERPOLATE_POINTS, (0.008090, -0.014239, -1.252375), (0.008090, -0.014239, -1.002375), 144 }
|
||||
led_strip { 22, 556, 0, INTERPOLATE_POINTS, (-0.506416, -0.303363, -0.803834), (-0.631416, -0.380617, -1.006088), 144 }
|
||||
led_strip { 22, 557, 0, INTERPOLATE_POINTS, (-0.618584, -0.391925, -1.016455), (-0.493584, -0.314671, -0.814200), 144 }
|
||||
led_strip { 22, 558, 0, INTERPOLATE_POINTS, (-0.500000, -0.299017, -0.809017), (-0.625000, -0.376271, -1.011271), 144 }
|
||||
led_strip { 22, 559, 0, INTERPOLATE_POINTS, (-0.612168, -0.387580, -1.021638), (-0.487168, -0.310325, -0.819384), 144 }
|
||||
led_strip { 23, 581, 0, INTERPOLATE_POINTS, (0.506416, -0.303363, -0.803834), (0.631416, -0.380617, -1.006088), 144 }
|
||||
led_strip { 23, 582, 0, INTERPOLATE_POINTS, (0.618584, -0.391925, -1.016455), (0.493584, -0.314671, -0.814200), 144 }
|
||||
led_strip { 23, 583, 0, INTERPOLATE_POINTS, (0.505000, -0.312107, -0.800927), (0.630000, -0.389361, -1.003181), 144 }
|
||||
led_strip { 23, 584, 0, INTERPOLATE_POINTS, (0.617168, -0.400670, -1.013548), (0.492168, -0.323415, -0.811293), 144 }
|
||||
led_strip { 24, 606, 0, INTERPOLATE_POINTS, (-0.312982, -0.809779, -0.490851), (-0.390236, -1.012033, -0.615851), 144 }
|
||||
led_strip { 24, 607, 0, INTERPOLATE_POINTS, (-0.382306, -1.010509, -0.634149), (-0.305052, -0.808255, -0.509149), 144 }
|
||||
led_strip { 24, 608, 0, INTERPOLATE_POINTS, (-0.317107, -0.804017, -0.496910), (-0.394361, -1.006271, -0.621910), 144 }
|
||||
led_strip { 24, 609, 0, INTERPOLATE_POINTS, (-0.386431, -1.004748, -0.640207), (-0.309177, -0.802493, -0.515207), 144 }
|
||||
led_strip { 25, 631, 0, INTERPOLATE_POINTS, (0.312982, -0.809779, -0.490851), (0.390236, -1.012033, -0.615851), 144 }
|
||||
led_strip { 25, 632, 0, INTERPOLATE_POINTS, (0.382306, -1.010509, -0.634149), (0.305052, -0.808255, -0.509149), 144 }
|
||||
led_strip { 25, 633, 0, INTERPOLATE_POINTS, (0.304017, -0.812107, -0.491910), (0.381271, -1.014361, -0.616910), 144 }
|
||||
led_strip { 25, 634, 0, INTERPOLATE_POINTS, (0.373341, -1.012838, -0.635207), (0.296086, -0.810584, -0.510207), 144 }
|
||||
led_strip { 26, 656, 0, INTERPOLATE_POINTS, (-0.490851, 0.312982, -0.809779), (-0.615851, 0.390236, -1.012033), 144 }
|
||||
led_strip { 26, 657, 0, INTERPOLATE_POINTS, (-0.634149, 0.382306, -1.010509), (-0.509149, 0.305052, -0.808255), 144 }
|
||||
led_strip { 26, 658, 0, INTERPOLATE_POINTS, (-0.491910, 0.304017, -0.812107), (-0.616910, 0.381271, -1.014361), 144 }
|
||||
led_strip { 26, 659, 0, INTERPOLATE_POINTS, (-0.635207, 0.373341, -1.012838), (-0.510207, 0.296086, -0.810584), 144 }
|
||||
led_strip { 27, 681, 0, INTERPOLATE_POINTS, (0.490851, 0.312982, -0.809779), (0.615851, 0.390236, -1.012033), 144 }
|
||||
led_strip { 27, 682, 0, INTERPOLATE_POINTS, (0.634149, 0.382306, -1.010509), (0.509149, 0.305052, -0.808255), 144 }
|
||||
led_strip { 27, 683, 0, INTERPOLATE_POINTS, (0.496910, 0.317107, -0.804017), (0.621910, 0.394361, -1.006271), 144 }
|
||||
led_strip { 27, 684, 0, INTERPOLATE_POINTS, (0.640207, 0.386431, -1.004748), (0.515207, 0.309177, -0.802493), 144 }
|
||||
led_strip { 28, 706, 0, INTERPOLATE_POINTS, (0.312982, 0.809779, -0.490851), (0.390236, 1.012033, -0.615851), 144 }
|
||||
led_strip { 28, 707, 0, INTERPOLATE_POINTS, (0.382306, 1.010509, -0.634149), (0.305052, 0.808255, -0.509149), 144 }
|
||||
led_strip { 28, 708, 0, INTERPOLATE_POINTS, (0.317107, 0.804017, -0.496910), (0.394361, 1.006271, -0.621910), 144 }
|
||||
led_strip { 28, 709, 0, INTERPOLATE_POINTS, (0.386431, 1.004748, -0.640207), (0.309177, 0.802493, -0.515207), 144 }
|
||||
led_strip { 29, 731, 0, INTERPOLATE_POINTS, (-0.312982, 0.809779, -0.490851), (-0.390236, 1.012033, -0.615851), 144 }
|
||||
led_strip { 29, 732, 0, INTERPOLATE_POINTS, (-0.382306, 1.010509, -0.634149), (-0.305052, 0.808255, -0.509149), 144 }
|
||||
led_strip { 29, 733, 0, INTERPOLATE_POINTS, (-0.304017, 0.812107, -0.491910), (-0.381271, 1.014361, -0.616910), 144 }
|
||||
led_strip { 29, 734, 0, INTERPOLATE_POINTS, (-0.373341, 1.012838, -0.635207), (-0.296086, 0.810584, -0.510207), 144 }
|
||||
led_strip { 30, 756, 0, INTERPOLATE_POINTS, (0.997267, 0.000000, -0.009619), (1.247267, 0.000000, -0.009619), 144 }
|
||||
led_strip { 30, 757, 0, INTERPOLATE_POINTS, (1.252733, 0.000000, 0.009619), (1.002733, 0.000000, 0.009619), 144 }
|
||||
led_strip { 30, 758, 0, INTERPOLATE_POINTS, (0.996910, 0.008090, -0.005000), (1.246910, 0.008090, -0.005000), 144 }
|
||||
led_strip { 30, 759, 0, INTERPOLATE_POINTS, (1.252375, 0.008090, 0.014239), (1.002375, 0.008090, 0.014239), 144 }
|
||||
led_strip { 31, 781, 0, INTERPOLATE_POINTS, (0.803834, 0.506416, 0.303363), (1.006088, 0.631416, 0.380617), 144 }
|
||||
led_strip { 31, 782, 0, INTERPOLATE_POINTS, (1.016455, 0.618584, 0.391925), (0.814200, 0.493584, 0.314671), 144 }
|
||||
led_strip { 31, 783, 0, INTERPOLATE_POINTS, (0.800927, 0.505000, 0.312107), (1.003181, 0.630000, 0.389361), 144 }
|
||||
led_strip { 31, 784, 0, INTERPOLATE_POINTS, (1.013548, 0.617168, 0.400670), (0.811293, 0.492168, 0.323415), 144 }
|
||||
led_strip { 32, 806, 0, INTERPOLATE_POINTS, (0.803834, -0.506416, 0.303363), (1.006088, -0.631416, 0.380617), 144 }
|
||||
led_strip { 32, 807, 0, INTERPOLATE_POINTS, (1.016455, -0.618584, 0.391925), (0.814200, -0.493584, 0.314671), 144 }
|
||||
led_strip { 32, 808, 0, INTERPOLATE_POINTS, (0.809017, -0.500000, 0.299017), (1.011271, -0.625000, 0.376271), 144 }
|
||||
led_strip { 32, 809, 0, INTERPOLATE_POINTS, (1.021638, -0.612168, 0.387580), (0.819384, -0.487168, 0.310325), 144 }
|
||||
led_strip { 33, 831, 0, INTERPOLATE_POINTS, (-0.997267, 0.000000, 0.009619), (-1.247267, 0.000000, 0.009619), 144 }
|
||||
led_strip { 33, 832, 0, INTERPOLATE_POINTS, (-1.252733, 0.000000, -0.009619), (-1.002733, 0.000000, -0.009619), 144 }
|
||||
led_strip { 33, 833, 0, INTERPOLATE_POINTS, (-0.996910, 0.008090, 0.005000), (-1.246910, 0.008090, 0.005000), 144 }
|
||||
led_strip { 33, 834, 0, INTERPOLATE_POINTS, (-1.252375, 0.008090, -0.014239), (-1.002375, 0.008090, -0.014239), 144 }
|
||||
led_strip { 34, 856, 0, INTERPOLATE_POINTS, (-0.809779, 0.490851, 0.312982), (-1.012033, 0.615851, 0.390236), 144 }
|
||||
led_strip { 34, 857, 0, INTERPOLATE_POINTS, (-1.010509, 0.634149, 0.382306), (-0.808255, 0.509149, 0.305052), 144 }
|
||||
led_strip { 34, 858, 0, INTERPOLATE_POINTS, (-0.804017, 0.496910, 0.317107), (-1.006271, 0.621910, 0.394361), 144 }
|
||||
led_strip { 34, 859, 0, INTERPOLATE_POINTS, (-1.004748, 0.640207, 0.386431), (-0.802493, 0.515207, 0.309177), 144 }
|
||||
led_strip { 35, 881, 0, INTERPOLATE_POINTS, (-0.809779, -0.490851, 0.312982), (-1.012033, -0.615851, 0.390236), 144 }
|
||||
led_strip { 35, 882, 0, INTERPOLATE_POINTS, (-1.010509, -0.634149, 0.382306), (-0.808255, -0.509149, 0.305052), 144 }
|
||||
led_strip { 35, 883, 0, INTERPOLATE_POINTS, (-0.812107, -0.491910, 0.304017), (-1.014361, -0.616910, 0.381271), 144 }
|
||||
led_strip { 35, 884, 0, INTERPOLATE_POINTS, (-1.012838, -0.635207, 0.373341), (-0.810584, -0.510207, 0.296086), 144 }
|
||||
led_strip { 36, 906, 0, INTERPOLATE_POINTS, (-0.803834, 0.506416, -0.303363), (-1.006088, 0.631416, -0.380617), 144 }
|
||||
led_strip { 36, 907, 0, INTERPOLATE_POINTS, (-1.016455, 0.618584, -0.391925), (-0.814200, 0.493584, -0.314671), 144 }
|
||||
led_strip { 36, 908, 0, INTERPOLATE_POINTS, (-0.800927, 0.505000, -0.312107), (-1.003181, 0.630000, -0.389361), 144 }
|
||||
led_strip { 36, 909, 0, INTERPOLATE_POINTS, (-1.013548, 0.617168, -0.400670), (-0.811293, 0.492168, -0.323415), 144 }
|
||||
led_strip { 37, 931, 0, INTERPOLATE_POINTS, (-0.803834, -0.506416, -0.303363), (-1.006088, -0.631416, -0.380617), 144 }
|
||||
led_strip { 37, 932, 0, INTERPOLATE_POINTS, (-1.016455, -0.618584, -0.391925), (-0.814200, -0.493584, -0.314671), 144 }
|
||||
led_strip { 37, 933, 0, INTERPOLATE_POINTS, (-0.809017, -0.500000, -0.299017), (-1.011271, -0.625000, -0.376271), 144 }
|
||||
led_strip { 37, 934, 0, INTERPOLATE_POINTS, (-1.021638, -0.612168, -0.387580), (-0.819384, -0.487168, -0.310325), 144 }
|
||||
led_strip { 38, 956, 0, INTERPOLATE_POINTS, (0.803834, 0.506416, -0.303363), (1.006088, 0.631416, -0.380617), 144 }
|
||||
led_strip { 38, 957, 0, INTERPOLATE_POINTS, (1.016455, 0.618584, -0.391925), (0.814200, 0.493584, -0.314671), 144 }
|
||||
led_strip { 38, 958, 0, INTERPOLATE_POINTS, (0.809017, 0.500000, -0.299017), (1.011271, 0.625000, -0.376271), 144 }
|
||||
led_strip { 38, 959, 0, INTERPOLATE_POINTS, (1.021638, 0.612168, -0.387580), (0.819384, 0.487168, -0.310325), 144 }
|
||||
led_strip { 39, 981, 0, INTERPOLATE_POINTS, (0.803834, -0.506416, -0.303363), (1.006088, -0.631416, -0.380617), 144 }
|
||||
led_strip { 39, 982, 0, INTERPOLATE_POINTS, (1.016455, -0.618584, -0.391925), (0.814200, -0.493584, -0.314671), 144 }
|
||||
led_strip { 39, 983, 0, INTERPOLATE_POINTS, (0.800927, -0.505000, -0.312107), (1.003181, -0.630000, -0.389361), 144 }
|
||||
led_strip { 39, 984, 0, INTERPOLATE_POINTS, (1.013548, -0.617168, -0.400670), (0.811293, -0.492168, -0.323415), 144 }
|
||||
led_strip { 40, 1006, 0, INTERPOLATE_POINTS, (0.009619, 0.997267, 0.000000), (0.009619, 1.247267, 0.000000), 144 }
|
||||
led_strip { 40, 1007, 0, INTERPOLATE_POINTS, (-0.009619, 1.252733, 0.000000), (-0.009619, 1.002733, 0.000000), 144 }
|
||||
led_strip { 40, 1008, 0, INTERPOLATE_POINTS, (0.005000, 0.996910, -0.008090), (0.005000, 1.246910, -0.008090), 144 }
|
||||
led_strip { 40, 1009, 0, INTERPOLATE_POINTS, (-0.014239, 1.252375, -0.008090), (-0.014239, 1.002375, -0.008090), 144 }
|
||||
led_strip { 41, 1031, 0, INTERPOLATE_POINTS, (0.009619, -0.997267, 0.000000), (0.009619, -1.247267, 0.000000), 144 }
|
||||
led_strip { 41, 1032, 0, INTERPOLATE_POINTS, (-0.009619, -1.252733, 0.000000), (-0.009619, -1.002733, 0.000000), 144 }
|
||||
led_strip { 41, 1033, 0, INTERPOLATE_POINTS, (0.005000, -0.996910, 0.008090), (0.005000, -1.246910, 0.008090), 144 }
|
||||
led_strip { 41, 1034, 0, INTERPOLATE_POINTS, (-0.014239, -1.252375, 0.008090), (-0.014239, -1.002375, 0.008090), 144 }
|
||||
END_OF_ASSEMBLY_FILE
|
|
@ -0,0 +1,20 @@
|
|||
led_strip_count 16
|
||||
|
||||
led_strip { 0, 1, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (1.0, 0.75, 0.0), 90 }
|
||||
led_strip { 0, 2, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (0.66, 0.75, 0.33), 90 }
|
||||
led_strip { 0, 3, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (0.33, 0.75, 0.66), 90 }
|
||||
led_strip { 0, 4, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (0.0, 0.75, 1.0), 90 }
|
||||
led_strip { 0, 5, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (-0.33, 0.75, 0.66), 90 }
|
||||
led_strip { 0, 6, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (-0.66, 0.75, 0.33), 90 }
|
||||
led_strip { 0, 7, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (-1.0, 0.75, 0.0), 90 }
|
||||
led_strip { 0, 8, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (-0.66, 0.75, -0.33), 90 }
|
||||
led_strip { 0, 9, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (-0.33, 0.75, -0.66), 90 }
|
||||
led_strip { 0, 10, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (0.0, 0.75, -1.0), 90 }
|
||||
led_strip { 0, 11, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (0.33, 0.75, -0.66), 90 }
|
||||
led_strip { 0, 12, 0, INTERPOLATE_POINTS, (0.0, 0.75, 0.0), (0.66, 0.75, -0.33), 90 }
|
||||
|
||||
led_strip { 0, 41, 0, INTERPOLATE_POINTS, (0.05, -0.75, 0.0), (0.05, 0.0, 0.0), 170 }
|
||||
led_strip { 0, 42, 0, INTERPOLATE_POINTS, (0.05, 0.0, 0.0), (0.05, 0.75, 0.0), 130 }
|
||||
led_strip { 0, 43, 0, INTERPOLATE_POINTS, (-0.05, -0.75, 0.0), (-0.05, 0.0, 0.0), 170 }
|
||||
led_strip { 0, 44, 0, INTERPOLATE_POINTS, (-0.05, 0.0, 0.0), (-0.05, 0.75, 0.0), 130 }
|
||||
END_OF_ASSEMBLY_FILE
|
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
|
@ -0,0 +1,14 @@
|
|||
control_box_count 4
|
||||
led_strip_count 4
|
||||
|
||||
control_box { 0, "192.168.0.1", (1, 1, 1) }
|
||||
control_box { 1, "192.168.0.2", (-1, 1, 1) }
|
||||
control_box { 2, "192.168.0.3", (-1, 1, -1) }
|
||||
control_box { 3, "192.168.0.4", (1, 1, -1) }
|
||||
|
||||
led_strip { 0, 1, 0, INTERPOLATE_POINTS, (1.0, 1.0, 1.0), (-1.0, 1.0, 1.0), 144 }
|
||||
led_strip { 1, 2, 0, INTERPOLATE_POINTS, (-1.0, 1.0, 1.0), (-1.0, 1.0, -1.0), 144 }
|
||||
led_strip { 2, 3, 0, INTERPOLATE_POINTS, (-1.0, 1.0, -1.0), (1.0, 1.0, -1.0), 144 }
|
||||
led_strip { 3, 4, 0, INTERPOLATE_POINTS, (1.0, 1.0, -1.0), (1.0, 1.0, 1.0), 144 }
|
||||
|
||||
END_OF_ASSEMBLY_FILE
|
|
@ -0,0 +1,23 @@
|
|||
struct hello_struct_t
|
||||
{
|
||||
const int x;
|
||||
float* y;
|
||||
char hello;
|
||||
};
|
||||
|
||||
union Vector
|
||||
{
|
||||
struct {
|
||||
int X;
|
||||
int Y;
|
||||
int Z;
|
||||
};
|
||||
int E[3];
|
||||
};
|
||||
|
||||
struct test_def;
|
||||
|
||||
int main (int ArgCount, char* Args[])
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
build\build_app_msvc_win32_debug.bat
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
call remedybg.bat ./app_run_tree/win32_msvc/debug/session.rdbg
|
|
@ -0,0 +1,89 @@
|
|||
const fs = require("fs");
|
||||
|
||||
const IN_FILE_PATH_PRIMARY = "../run_tree/data/cities_final.json";
|
||||
const IN_FILE_PATH_SECONDARY = "../run_tree/data/cities_secondary_final.json";
|
||||
const OUT_FILE_PATH = "../src_v2/user_space/incenter_gen_cities.h"
|
||||
|
||||
function print_city_desc (city, prefix, dest, gets_own_universe)
|
||||
{
|
||||
const city_ascii = city.city_ascii
|
||||
.toLowerCase()
|
||||
.replaceAll(' ', '_')
|
||||
.replaceAll('-', '_')
|
||||
.replaceAll('\'', '')
|
||||
.replaceAll('`', '');
|
||||
|
||||
const city_id = `${prefix}_${city_ascii}`;
|
||||
const { lat, lng } = city;
|
||||
|
||||
dest.enum_out += ` ${city_id} = ${dest.enum_counter++},\n`;
|
||||
|
||||
const universe = gets_own_universe ? city_id : "incenter_secondary_city_universe";
|
||||
|
||||
dest.desc_out += ` [${city_id}] = {
|
||||
.id = ${city_id},
|
||||
.lat = ${lat},
|
||||
.lon = ${lng},
|
||||
.sacn_universe = ${universe},
|
||||
},\n`;
|
||||
|
||||
dest.strings_out += ` [${city_id}] = "${city_id}",\n`;
|
||||
}
|
||||
|
||||
function main ()
|
||||
{
|
||||
const primary_file = fs.readFileSync(IN_FILE_PATH_PRIMARY, {});
|
||||
const primary_json = JSON.parse(primary_file);
|
||||
|
||||
const secondary_file = fs.readFileSync(IN_FILE_PATH_SECONDARY, {});
|
||||
const secondary_json = JSON.parse(secondary_file);
|
||||
|
||||
let out = "// NOTE: This file is autogenerated by csv_to_cstruct.js\n";
|
||||
|
||||
let enum_counter = 0;
|
||||
let enum_out = "// NOTE: These are values for Incenter_City_Id\nenum {\n";
|
||||
enum_out += ` city_black_rock = ${enum_counter++},\n`;
|
||||
|
||||
let desc_out = "global Incenter_City_Desc city_descs[] = {\n";
|
||||
|
||||
let strings_out = "global char* city_strings[] = {\n";
|
||||
|
||||
let dest = {
|
||||
enum_counter,
|
||||
enum_out,
|
||||
desc_out,
|
||||
strings_out,
|
||||
};
|
||||
|
||||
primary_json.forEach((city) => {
|
||||
print_city_desc(city, "city", dest, true);
|
||||
});
|
||||
|
||||
// Add Black Rock City
|
||||
dest.desc_out += `\n // Black Rock City\n [city_black_rock] = {
|
||||
.id = city_black_rock,
|
||||
.lat = -90.0f,
|
||||
.lon = 0,
|
||||
.sacn_universe = city_black_rock,
|
||||
},\n`;
|
||||
|
||||
dest.strings_out += ` [city_black_rock] = "city_black_rock",\n`;
|
||||
dest.enum_out += " city_count,\n";
|
||||
dest.enum_out += " city_secondary_first = city_count + 1,\n";
|
||||
|
||||
secondary_json.forEach((city) => {
|
||||
print_city_desc(city, "city_secondary", dest, false);
|
||||
});
|
||||
|
||||
dest.enum_out += " city_secondary_count,\n";
|
||||
dest.enum_out += "};\n\n";
|
||||
dest.desc_out += "};\n\n";
|
||||
dest.strings_out += "};\n\n";
|
||||
|
||||
out += dest.enum_out;
|
||||
out += dest.desc_out;
|
||||
out += dest.strings_out;
|
||||
fs.writeFileSync(OUT_FILE_PATH, out, {});
|
||||
}
|
||||
|
||||
main();
|
|
@ -0,0 +1,4 @@
|
|||
@echo off
|
||||
pushd app_run_tree
|
||||
start win32_msvc\debug\win32_foldhaus.exe
|
||||
popd
|
|
@ -0,0 +1,11 @@
|
|||
@echo off
|
||||
|
||||
IF NOT "%PrebuildCalled%"=="1" GOTO error
|
||||
|
||||
IF EXIST %CTIMEPATH% ( call C:\apps\ctime\ctime.exe -end %StatsPath%\%StatsFile% %LastError% )
|
||||
IF EXIST %CTIMEPATH% ( call C:\apps\ctime\ctime.exe -stats %StatsPath%\%StatsFile% )
|
||||
set PrebuildCalled=0
|
||||
GOTO:eof
|
||||
|
||||
:error
|
||||
echo ERROR: _prebuild_win32.bat was not called before _postbuild_win32.bat.
|
|
@ -0,0 +1,31 @@
|
|||
@echo off
|
||||
|
||||
REM This file takes three arguments
|
||||
REM 1 = "app" or "meta"
|
||||
REM 2 = "debug" or "release"
|
||||
REM 3 = "msvc" or "clang"
|
||||
|
||||
set PrebuildCalled=1
|
||||
|
||||
set ProjectDevFolder=%~dp0
|
||||
set ProjectDevPath=%ProjectDevFolder:~0,-7%
|
||||
|
||||
set SourceCodePath=%ProjectDevPath%\src\%1
|
||||
|
||||
set MetaProgramPath=%ProjectDevPath%\meta_run_tree\win32_%3\%2
|
||||
|
||||
set ProjectRunTree=%ProjectDevPath%\%1_run_tree\win32_%3
|
||||
set BuildPath=%ProjectRunTree%\%2
|
||||
set StatsPath=%ProjectRunTree%\stats
|
||||
set StatsFile=%1_win32_%3_%2_build_time.ctm
|
||||
|
||||
IF NOT EXIST %BuildPath% mkdir %BuildPath%
|
||||
IF NOT EXIST %StatsPath% mkdir %StatsPath%
|
||||
|
||||
set CTimePath=C:\apps\ctime
|
||||
IF EXIST %CTIMEPATH% ( call C:\apps\ctime\ctime.exe -begin %StatsPath%\%StatsFile% )
|
||||
|
||||
echo.
|
||||
echo BUILDING TO %BuildPath%
|
||||
echo STATS IN %StatsPath%\%StatsFile%
|
||||
echo.
|
417
build/build.sh
417
build/build.sh
|
@ -1,412 +1,9 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# --------------------------------------------
|
||||
# Usage
|
||||
SCRIPT_REL_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
$SCRIPT_REL_DIR/build_.sh debug osx arm64
|
||||
# $SCRIPT_REL_DIR/build_.sh debug wasm intel
|
||||
|
||||
VALID_VALUES_COMPILER=("clang" "clang++" "msvc")
|
||||
VALID_VALUES_MODE=("debug" "release")
|
||||
VALID_VALUES_PLATFORM=("win32" "osx" "linux" "raspi" "wasm")
|
||||
VALID_VALUES_ARCH=("x64" "arm64")
|
||||
VALID_VALUES_PACKAGE=("true" "false")
|
||||
|
||||
printf_r () {
|
||||
printf "\e[31m$@\e[0m\n"
|
||||
}
|
||||
|
||||
printf_g () {
|
||||
printf "\e[32m%s\e[0m\n" "$@"
|
||||
}
|
||||
|
||||
print_usage () {
|
||||
printf "\n"
|
||||
printf "Build Command Syntax:\n"
|
||||
printf_g " $0 [compiler] [mode] [platform] [arch] [package]"
|
||||
printf "\n"
|
||||
printf "Compiler Options:\n"
|
||||
printf " \e[32m%s\e[m\n" "${VALID_VALUES_COMPILER[@]}"
|
||||
printf "\n"
|
||||
printf "Release Mode Options:\n"
|
||||
printf " \e[32m%s\e[m\n" "${VALID_VALUES_MODE[@]}"
|
||||
printf "\n"
|
||||
printf "Platform Options:\n"
|
||||
printf " \e[32m%s\e[m\n" "${VALID_VALUES_PLATFORM[@]}"
|
||||
printf "\n"
|
||||
printf "Arch Options: \n"
|
||||
printf " \e[32m%s\e[m\n" "${VALID_VALUES_ARCH[@]}"
|
||||
printf "\n"
|
||||
printf "Package Options:\n"
|
||||
printf_g " 'package' or no flag to omit packaging\n"
|
||||
printf "\n"
|
||||
printf "Examples:\n"
|
||||
printf " $0 clang debug osx arm64\n"
|
||||
printf " $0 msvc release win32 x64 package\n"
|
||||
}
|
||||
|
||||
OPTS=()
|
||||
for ((i=1; i<=$#; i+=1)); do
|
||||
OPTS+=(${!i})
|
||||
done
|
||||
|
||||
if [ "${OPTS[0]}" == "-h" ] || [ "${OPTS[0]}" == "--help" ]
|
||||
then
|
||||
print_usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --------------------------------------------
|
||||
# Utilities
|
||||
|
||||
pushdir () {
|
||||
command pushd "$@" > /dev/null
|
||||
}
|
||||
|
||||
popdir () {
|
||||
command popd "$@" > /dev/null
|
||||
}
|
||||
|
||||
# --------------------------------------------
|
||||
# Project Directory Identification
|
||||
|
||||
OLD_PATH=$(pwd)
|
||||
|
||||
BUILD_SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
pushdir $BUILD_SCRIPT_DIR
|
||||
pushdir ..
|
||||
PROJECT_PATH=$(pwd)
|
||||
popdir
|
||||
popdir
|
||||
|
||||
BLD_DIR="${PROJECT_PATH}/build"
|
||||
SRC_DIR="${PROJECT_PATH}/src"
|
||||
OUT_DIR="${PROJECT_PATH}/run_tree"
|
||||
|
||||
# --------------------------------------------
|
||||
# Input Flag Settings
|
||||
|
||||
INPUT_FLAG_UNSET="unset"
|
||||
|
||||
COMPILER=$INPUT_FLAG_UNSET
|
||||
MODE=$INPUT_FLAG_UNSET
|
||||
PLATFORM=$INPUT_FLAG_UNSET
|
||||
ARCH=$INPUT_FLAG_UNSET
|
||||
PACKAGE=$INPUT_FLAG_UNSET
|
||||
|
||||
# --------------------------------------------
|
||||
# Create a local build file if there isn't one
|
||||
# using local context to determine defaults
|
||||
|
||||
BLD_LOCAL_FILE="${BLD_DIR}/build_local.sh"
|
||||
|
||||
if [ ! -f $BLD_LOCAL_FILE ]
|
||||
then
|
||||
|
||||
printf "Creating a build/build_local.sh file for you."
|
||||
printf " Path: ${BLD_LOCAL_FILE}"
|
||||
printf "This file is excluded in the .gitignore. It is for you to set local compilation targets"
|
||||
|
||||
touch $BLD_LOCAL_FILE
|
||||
printf "#!/bin/bash\n" >> $BLD_LOCAL_FILE
|
||||
printf "\n" >> $BLD_LOCAL_FILE
|
||||
printf "COMPILER=\"clang\"\n" >> $BLD_LOCAL_FILE
|
||||
printf "MODE=\"debug\"\n" >> $BLD_LOCAL_FILE
|
||||
printf "PLATFORM=\"osx\"\n" >> $BLD_LOCAL_FILE
|
||||
printf "ARCH=\"arm64\"\n" >> $BLD_LOCAL_FILE
|
||||
printf "PACKAGE=\"false\"\n" >> $BLD_LOCAL_FILE
|
||||
printf "TEST_FILE=\"\"\n" >> $BLD_LOCAL_FILE
|
||||
fi
|
||||
|
||||
# --------------------------------------------
|
||||
# Call Local Build File
|
||||
|
||||
source ${BLD_LOCAL_FILE}
|
||||
|
||||
# --------------------------------------------
|
||||
# Use command line arguments to override local
|
||||
# build file
|
||||
|
||||
if [ "${#OPTS[@]}" -gt "0" ]; then
|
||||
OPTS_COUNT="${#OPTS[@]}"
|
||||
if [ $OPTS_COUNT -lt "4" ] || [ $OPTS_COUNT -gt "5" ]; then
|
||||
printf_r "Error: Incorrect number of arguments supplied"
|
||||
printf " You must either supply all or none of the build script arguments\n"
|
||||
print_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
COMPILER=${OPTS[0]}
|
||||
MODE=${OPTS[1]}
|
||||
PLATFORM=${OPTS[2]}
|
||||
ARCH=${OPTS[3]}
|
||||
|
||||
PACkaGE="false"
|
||||
if [ $OPTS_COUNT -eq "5" ]; then
|
||||
if [ "${OPTS[4]}" == "package" ]; then
|
||||
PACKAGE="true"
|
||||
else
|
||||
printf_r "Error: Invalid package command provided: ${PACKAGE}"
|
||||
printf " You must either supply the 'package' flag or omit it"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# --------------------------------------------
|
||||
# Verify valid values for all inputs
|
||||
|
||||
ALL_VALID_VALUES="true"
|
||||
|
||||
check_valid_flag () {
|
||||
local VALID_VALUES_NAME=$1[@]
|
||||
local VALID_VALUES=("${!VALID_VALUES_NAME}")
|
||||
local VALUE_GIVEN=$2
|
||||
local VALUE_ID=$3
|
||||
|
||||
if [[ ! " ${VALID_VALUES[*]} " =~ " ${VALUE_GIVEN} " ]]; then
|
||||
printf_r "Error: Invalid ${VALUE_ID} provided: ${VALUE_GIVEN}"
|
||||
printf " Must be one of: "
|
||||
printf_g "${VALID_VALUES[*]}\n"
|
||||
ALL_VALID_VALUES="false"
|
||||
fi
|
||||
}
|
||||
|
||||
check_valid_flag VALID_VALUES_COMPILER $COMPILER "compiler"
|
||||
check_valid_flag VALID_VALUES_MODE $MODE "mode"
|
||||
check_valid_flag VALID_VALUES_PLATFORM $PLATFORM "platform"
|
||||
check_valid_flag VALID_VALUES_ARCH $ARCH "arch"
|
||||
|
||||
if [[ ! " ${VALID_VALUES_PACKAGE[*]} " =~ " ${PACKAGE} " ]]; then
|
||||
printf_r "Error: Invalid package provided: ${PACKAGE}"
|
||||
printf " You must either supply the 'package' flag or omit it"
|
||||
ALL_VALID_VALUES="false"
|
||||
fi
|
||||
|
||||
if [ "${ALL_VALID_VALUES}" != "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${COMPILER}" == "clang" ] || [ "${COMPILER}" == "clang++" ]; then
|
||||
LINKER=${COMPILER}
|
||||
elif [ "${COMPILER}" == "msvc" ]; then
|
||||
LINKER="link"
|
||||
fi
|
||||
|
||||
printf "Compiler: "
|
||||
printf_g "${COMPILER}"
|
||||
printf "Mode: "
|
||||
printf_g "${MODE}"
|
||||
printf "Platform: "
|
||||
printf_g "${PLATFORM}"
|
||||
printf "Arch: "
|
||||
printf_g "${ARCH}"
|
||||
printf "Package: "
|
||||
printf_g "${PACKAGE}"
|
||||
|
||||
# --------------------------------------------
|
||||
# Hooks Identification
|
||||
|
||||
HOOK_PREBUILD="${BLD_DIR}/hook_prebuild.sh"
|
||||
HOOK_POSTBUILD="${BLD_DIR}/hook_postbuild.sh"
|
||||
HOOK_PRELINK="${BLD_DIR}/hook_prelink.sh"
|
||||
HOOK_POSTLINK="${BLD_DIR}/hook_postlink.sh"
|
||||
|
||||
printf "\nBuild Hooks:\n"
|
||||
if [ -f "${HOOK_PREBUILD}" ]; then
|
||||
printf " Pre Build: ${HOOK_PREBUILD##*/}\n"
|
||||
else
|
||||
HOOK_PREBUILD=""
|
||||
fi
|
||||
|
||||
if [ -f "${HOOK_POSTBUILD}" ]; then
|
||||
printf " Post Build: ${HOOK_POSTBUILD##*/}\n"
|
||||
else
|
||||
HOOK_POSTBUILD=""
|
||||
fi
|
||||
|
||||
if [ -f "${HOOK_PRELINK}" ]; then
|
||||
printf " Pre Link: ${HOOK_PRELINK##*/}\n"
|
||||
else
|
||||
HOOK_PRELINK=""
|
||||
fi
|
||||
|
||||
if [ -f "${HOOK_POSTLINK}" ]; then
|
||||
printf " Post Link: ${HOOK_POSTLINK##*/}\n"
|
||||
else
|
||||
HOOK_POSTLINK=""
|
||||
fi
|
||||
|
||||
# --------------------------------------------
|
||||
# File Parsing Helpers
|
||||
|
||||
trim() {
|
||||
local var="$*"
|
||||
|
||||
# remove leading whitespace characters
|
||||
var="${var#"${var%%[![:space:]]*}"}"
|
||||
|
||||
# remove trailing whitespace characters
|
||||
var="${var%"${var##*[![:space:]]}"}"
|
||||
|
||||
echo "${var}"
|
||||
}
|
||||
|
||||
load_file_into_lines_array() {
|
||||
FILE=$1
|
||||
local FILE_LINES_RAW=()
|
||||
IFS=$'\r\n'
|
||||
GLOBIGNORE='*'
|
||||
command eval 'FILE_LINES_RAW=($(cat $FILE))'
|
||||
|
||||
FILE_LINES=()
|
||||
for i in "${FILE_LINES_RAW[@]}"; do
|
||||
if [ "${i:0:1}" != "#" ]; then
|
||||
# strip any trailing comments off the end
|
||||
# this lets you do things like:
|
||||
# "compiler>msvc>-FC # full path error"
|
||||
# where you want to explain a flag
|
||||
local LINE=$i
|
||||
local LINE_NO_TRAILING_COMMENT="${LINE% #*}"
|
||||
FILE_LINES+=($LINE_NO_TRAILING_COMMENT)
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
parse_flags_from_selectors() {
|
||||
SELECTORS=()
|
||||
for ((i=1; i<=$#; i+=1)); do
|
||||
SELECTORS+=(${!i})
|
||||
done
|
||||
|
||||
FLAGS=()
|
||||
for i in "${FILE_LINES[@]}"; do
|
||||
LINE=$i
|
||||
FLAG="${LINE##*>}"
|
||||
|
||||
INCLUDE_FLAG="true"
|
||||
while [ "${LINE}" != "${FLAG}" ]; do
|
||||
NEXT_SELECTOR="${LINE%%>*}"
|
||||
LINE="${LINE#*>}"
|
||||
if [[ ! " ${SELECTORS[@]} " =~ " ${NEXT_SELECTOR} " ]]; then
|
||||
INCLUDE_FLAG="false"
|
||||
break
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if [ "${INCLUDE_FLAG}" == "true" ]; then
|
||||
FLAG=$(trim "${FLAG}")
|
||||
FLAG=$(eval "echo $FLAG")
|
||||
FLAGS+=($FLAG)
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
load_file_into_lines_array "${BLD_DIR}/build_flags.sh"
|
||||
|
||||
# --------------------------------------------
|
||||
# Assemble Flags
|
||||
|
||||
parse_flags_from_selectors "compiler" $COMPILER $MODE $PLATFORM $ARCH
|
||||
COMPILER_FLAGS=(${FLAGS[@]})
|
||||
|
||||
parse_flags_from_selectors "compiler" "input" $PLATFORM $ARCH
|
||||
COMPILER_INPUTS=(${FLAGS[@]})
|
||||
|
||||
parse_flags_from_selectors "linker" "flags" $MODE $PLATFORM $ARCH
|
||||
LINKER_FLAGS=(${FLAGS[@]})
|
||||
|
||||
parse_flags_from_selectors "linker" "libs" $LINKER $MODE $PLATFORM $ARCH
|
||||
LINKER_LIBRARIES=(${FLAGS[@]})
|
||||
|
||||
parse_flags_from_selectors "linker" "output" $LINKER $MODE $PLATFORM $ARCH
|
||||
LINKER_OUTPUT=(${FLAGS[@]})
|
||||
|
||||
# --------------------------------------------
|
||||
# Create the Run Tree path
|
||||
|
||||
OUT_PATH="${OUT_DIR}/${PLATFORM}/${ARCH}/${MODE}"
|
||||
|
||||
if [ ! -d $OUT_PATH ]; then
|
||||
mkdir -p $OUT_PATH
|
||||
fi
|
||||
|
||||
# --------------------------------------------
|
||||
# Compile The Program
|
||||
|
||||
printf "\nBeginning Compilation...\n"
|
||||
pushdir $OUT_PATH
|
||||
|
||||
find . -name "*" -delete > /dev/null
|
||||
|
||||
if [[ -f ${HOOK_PREBUILD} ]]; then
|
||||
source "${HOOK_PREBUILD}"
|
||||
fi
|
||||
|
||||
COMPILATION_SUCCESS="true"
|
||||
COMPILER_OUTPUT=()
|
||||
FAILED_COMPILES=()
|
||||
for i in "${COMPILER_INPUTS[@]}"; do
|
||||
INPUT="${i}"
|
||||
|
||||
INPUT_FILE="${INPUT##*/}"
|
||||
INPUT_EXTENSION="${INPUT_FILE##*.}"
|
||||
INPUT_NAME="${INPUT_FILE%.*}"
|
||||
OUTPUT_FILE="${INPUT_NAME}_${INPUT_EXTENSION}.o"
|
||||
|
||||
COMPILER_ARGS="-o ${OUTPUT_FILE} -c ${COMPILER_FLAGS[@]} -DPLATFORM_$PLATFORM=1 -DMODE_$MODE=1 -DARCH_$ARCH=1 $INPUT"
|
||||
|
||||
# echo $COMPILER $COMPILER_ARGS
|
||||
eval $COMPILER $COMPILER_ARGS
|
||||
if [ $? -eq 0 ]; then
|
||||
COMPILER_OUTPUT+=(${OUTPUT_FILE})
|
||||
else
|
||||
COMPILATION_SUCCESS="false"
|
||||
FAILED_COMPILES+=(${OUTPUT_FILE})
|
||||
fi
|
||||
|
||||
# TODO: if the output file was a .dll or .lib we don't want to include
|
||||
# those in the final compilation gather
|
||||
done
|
||||
|
||||
printf "\nCompiler Output\n"
|
||||
if [ ${#COMPILER_OUTPUT[@]} -gt 0 ]; then
|
||||
printf " %s \e[32m[SUCCESS]\e[0m\n" "${COMPILER_OUTPUT[@]}"
|
||||
fi
|
||||
if [ ${#FAILED_COMPILES[@]} -gt 0 ]; then
|
||||
printf " %s \e[31m[FAILED]\e[0m\n" "${FAILED_COMPILES[@]}"
|
||||
fi
|
||||
printf "\n"
|
||||
|
||||
if [[ -f ${HOOK_POSTBUILD} ]]; then
|
||||
source "${HOOK_POSTBUILD}"
|
||||
fi
|
||||
|
||||
if [ $COMPILATION_SUCCESS != "true" ]; then
|
||||
printf "Compilation Failed.\n Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -f ${HOOK_PRELINK} ]]; then
|
||||
source "${HOOK_PRELINK}"
|
||||
fi
|
||||
|
||||
LINKER_ARGS="-o ${LINKER_OUTPUT} ${COMPILER_OUTPUT[@]} ${LINKER_FLAGS[@]} ${LINKER_LIBRARIES[@]}"
|
||||
|
||||
printf "Linking...\n"
|
||||
# echo $LINKER $LINKER_ARGS
|
||||
eval $LINKER $LINKER_ARGS
|
||||
if [ $? -eq 0 ]; then
|
||||
printf " Link: "
|
||||
printf_g "[SUCCEEDED]"
|
||||
else
|
||||
printf "\n Link: "
|
||||
printf_r "[FAILED]"
|
||||
fi
|
||||
|
||||
if [[ -f ${HOOK_POSTLINK} ]]; then
|
||||
source "${HOOK_POSTLINK}"
|
||||
fi
|
||||
|
||||
popdir
|
||||
|
||||
printf "\n"
|
||||
exit 0
|
||||
# pushd "run_tree/raspi/arm64/debug"
|
||||
# clang -o lumenarium /home/pi/dev/Lumenarium/src_v2/platform/raspi/lumenarium_first_raspi.c -lm
|
||||
# popd
|
||||
|
|
|
@ -0,0 +1,378 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Ensure an error makes the script bail
|
||||
set -e
|
||||
|
||||
# --------------------------------------------
|
||||
# Usage
|
||||
|
||||
print_usage () {
|
||||
echo
|
||||
echo Build Command Syntax:
|
||||
echo " $0 [mode] [platform] [arch]"
|
||||
echo
|
||||
echo "Release Mode Options:"
|
||||
echo " debug"
|
||||
echo " prod"
|
||||
echo
|
||||
echo "Platform Options:"
|
||||
echo " win32"
|
||||
echo " osx"
|
||||
echo " wasm"
|
||||
echo " raspi"
|
||||
echo
|
||||
echo "Arch Options: (architecture)"
|
||||
echo " intel (valid with Platform Win32 and OSX) (default)"
|
||||
echo " arm64 (only valid for Platform OSX)"
|
||||
}
|
||||
|
||||
# --------------------------------------------
|
||||
# Arguments
|
||||
MODE=$1
|
||||
PLATFORM=$2
|
||||
ARCH=$3
|
||||
PACKAGE=$4
|
||||
|
||||
if [ "${MODE}" == "" ] | [ "${PLATFORM}" == "" ]
|
||||
then
|
||||
print_usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Default to Intel architecture if none provided
|
||||
if [ "${ARCH}" == "" ]
|
||||
then
|
||||
ARCH="intel"
|
||||
fi
|
||||
|
||||
if [ "${ARCH}" != "intel" ] && [ "${ARCH}" != "arm64" ]
|
||||
then
|
||||
echo "Uknown target architecture: ${ARCH}"
|
||||
print_usage
|
||||
exit 0
|
||||
|
||||
fi
|
||||
|
||||
# --------------------------------------------
|
||||
# Utilities
|
||||
|
||||
pushdir () {
|
||||
command pushd "$@" > /dev/null
|
||||
}
|
||||
|
||||
popdir () {
|
||||
command popd "$@" > /dev/null
|
||||
}
|
||||
|
||||
add_flag () {
|
||||
local -n ref=$1
|
||||
ref="$ref $2"
|
||||
}
|
||||
|
||||
# --------------------------------------------
|
||||
# Getting Project Path
|
||||
#
|
||||
# Project is stored in PROJECT_PATH
|
||||
|
||||
SCRIPT_REL_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
pushdir $SCRIPT_REL_DIR
|
||||
pushdir ..
|
||||
PROJECT_PATH=$(pwd)
|
||||
popdir
|
||||
popdir
|
||||
|
||||
# --------------------------------------------
|
||||
# Platform/Mode Specific Variables
|
||||
|
||||
# Compiler Selection
|
||||
|
||||
Compiler_win32="cl"
|
||||
Compiler_osx="clang"
|
||||
Compiler_raspi="clang"
|
||||
WasiSdk="/c/drive/apps/wasi-sdk"
|
||||
Compiler_wasm="$WasiSdk/bin/clang++"
|
||||
Compiler_linux="clang++"
|
||||
|
||||
# Platform Entry Points
|
||||
|
||||
PlatformEntry_win32="src_v2/platform/win32/lumenarium_first_win32.cpp"
|
||||
PlatformEntry_osx="src_v2/platform/osx/lumenarium_first_osx.c"
|
||||
PlatformEntry_wasm="src_v2/platform/wasm/lumenarium_first_wasm.cpp"
|
||||
PlatformEntry_linux="src_v2/platform/linux/lumenarium_first_linux.cpp"
|
||||
PlatformEntry_raspi="src_v2/platform/raspi/lumenarium_first_raspi.c"
|
||||
|
||||
# Intermediate Outputs
|
||||
|
||||
CompilerOutput_win32="lumenarium.o"
|
||||
CompilerOutput_osx="lumenarium"
|
||||
CompilerOutput_wasm="lumenarium.wasm"
|
||||
CompilerOutput_linux=""
|
||||
CompilerOutput_raspi="lumenarium"
|
||||
|
||||
# Executables
|
||||
|
||||
LinkerOutput_win32="lumenarium.exe"
|
||||
LinkerOutput_osx="lumenarium"
|
||||
LinkerOutput_wasm="lumenarium.wasm"
|
||||
LinkerOutput_linux=""
|
||||
LinkerOutput_raspi="lumenarium"
|
||||
|
||||
# Wasm Sys Root
|
||||
WasmSysRoot="${PROJECT_PATH}/src_v2/platform/wasm/sysroot/"
|
||||
|
||||
# Compiler Flags
|
||||
|
||||
CompilerFlags_win32="-nologo"
|
||||
CompilerFlags_win32+=" -FC" # display errors with full path
|
||||
CompilerFlags_win32+=" -WX" # treat warnings as errors
|
||||
CompilerFlags_win32+=" -W4" # output warning level
|
||||
CompilerFlags_win32+=" -Z7" # generate C compatible debug info
|
||||
# CompilerFlags_win32+="-Oi" # generate intrinsic functions
|
||||
# CompilerFlags_win32+="-MTd" # create a debug multithreaded exe w/ Libcmtd.lib
|
||||
# CompilerFlags_win32+="-fp:fast" # fast floating point model
|
||||
CompilerFlags_win32+=" -wd4505" #
|
||||
CompilerFlags_win32+=" -wd4100" #
|
||||
CompilerFlags_win32+=" -wd4189" #
|
||||
CompilerFlags_win32+=" -wd4702" #
|
||||
CompilerFlags_win32+=" -wd4996" # _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
CompilerFlags_osx=""
|
||||
|
||||
CompilerFlags_wasm=""
|
||||
CompilerFlags_wasm+=" -Wno-writable-strings" #
|
||||
CompilerFlags_wasm+=" --target=wasm32" #
|
||||
CompilerFlags_wasm+=" -nostdlib" #
|
||||
CompilerFlags_wasm+=" -Wl,--no-entry" #
|
||||
CompilerFlags_wasm+=" -Wl,--allow-undefined" #
|
||||
CompilerFlags_wasm+=" -Wl,--export-all" #
|
||||
|
||||
CompilerFlags_linux=" -pthread"
|
||||
|
||||
CompilerFlags_raspi=" -pthread" # "--target=arm-rpi-linux-gnueabihf" # "--target=arm-linux-gnueabihf" #target
|
||||
CompilerFlags_raspi+=" -lm" # link with local system math libraries
|
||||
|
||||
|
||||
CompilerFlags_DEBUG_win32=""
|
||||
CompilerFlags_DEBUG_win32+=" -Od" #
|
||||
CompilerFlags_DEBUG_win32+=" -Zi" #
|
||||
CompilerFlags_DEBUG_win32+=" -DDEBUG" #
|
||||
# add_flag CompilerFlags_DEBUG_win32 "-DPRINT_ASSERTS"
|
||||
|
||||
CompilerFlags_DEBUG="-O0"
|
||||
CompilerFlags_DEBUG+=" -g" #
|
||||
CompilerFlags_DEBUG+=" -DDEBUG" #
|
||||
if [ "${PLATFORM}" != "raspi" ]
|
||||
then
|
||||
CompilerFlags_DEBUG+=" -fsanitize=address" #address sanitizer
|
||||
fi
|
||||
|
||||
CompilerFlags_PROD=" -O3"
|
||||
|
||||
# Compiler flags that no matter what, we want to define
|
||||
# for the most part these pass the build parameters into the executable
|
||||
CompilerFlags_common=" -DPLATFORM_${PLATFORM}=1 -DMODE_${MODE}=1 -DARCH_${ARCH}=1"
|
||||
|
||||
# Linker Flags
|
||||
|
||||
LinkerFlags_win32=" -NOLOGO"
|
||||
LinkerFlags_win32+=" -incremental:no" #
|
||||
LinkerFlags_win32+=" -subsystem:windows" #
|
||||
# add_flag LinkerFlags_win32 "-entry:WinMain" #
|
||||
LinkerFlags_win32+=" -opt:ref" # eliminate functions that are never referenced
|
||||
|
||||
LinkerFlags_osx=""
|
||||
|
||||
LinkerFlags_wasm="--no-entry"
|
||||
LinkerFlags_wasm+=" --export-dynamic" #
|
||||
LinkerFlags_wasm+=" --unresolved-symbols=import-functions" #
|
||||
|
||||
LinkerFlags_linux=""
|
||||
LinkerFlags_raspi="-fuse-ld=lld"
|
||||
|
||||
LinkerFlags_DEBUG="-debug"
|
||||
LinkerFlags_PROD=""
|
||||
|
||||
# Linker Libs
|
||||
|
||||
LinkerLibs_win32="user32.lib kernel32.lib gdi32.lib opengl32.lib"
|
||||
# winmm.lib gdi32.lib dsound.lib Ws2_32.lib Comdlg32.lib Winspool.lib"
|
||||
|
||||
LinkerLibs_osx="-framework OpenGL -framework Cocoa -framework IOKit ${PROJECT_PATH}/src_v2/libs/glfw_osx/lib-universal/libglfw3.a"
|
||||
LinkerLibs_wasm=""
|
||||
LinkerLibs_linux=""
|
||||
LinkerLibs_raspi=""
|
||||
|
||||
# --------------------------------------------
|
||||
# Varible Selection
|
||||
|
||||
# Select Platform Variables
|
||||
|
||||
if [ "${PLATFORM}" == "win32" ]
|
||||
then
|
||||
Compiler=$Compiler_win32
|
||||
PlatformEntry=$PlatformEntry_win32
|
||||
CompilerFlags=$CompilerFlags_win32
|
||||
CompilerOutput=$CompilerOutput_win32
|
||||
LinkerOutput=$LinkerOutput_win32
|
||||
LinkerFlags=$LinkerFlags_win32
|
||||
LinkerLibs=$LinkerLibs_win32
|
||||
|
||||
elif [ "${PLATFORM}" == "osx" ]
|
||||
then
|
||||
Compiler=$Compiler_osx
|
||||
PlatformEntry=$PlatformEntry_osx
|
||||
CompilerFlags=$CompilerFlags_osx
|
||||
CompilerOutput=$CompilerOutput_osx
|
||||
LinkerOutput=$LinkerOutput_osx
|
||||
LinkerFlags=$LinkerFlags_osx
|
||||
LinkerLibs=$LinkerLibs_osx
|
||||
|
||||
if [ "${ARCH}" == "arm64" ]
|
||||
then
|
||||
CompilerFlags="${CompilerFlags} -arch arm64"
|
||||
elif [ "${ARCH}" == "intel" ]
|
||||
then
|
||||
CompilerFlags="${CompilerFlags} -arch x86_64"
|
||||
else
|
||||
echo "ERROR: Unrecognized Arch: ${ARCH}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
elif [ "${PLATFORM}" == "wasm" ]
|
||||
then
|
||||
Compiler=$Compiler_wasm
|
||||
PlatformEntry=$PlatformEntry_wasm
|
||||
CompilerFlags=$CompilerFlags_wasm
|
||||
CompilerOutput=$CompilerOutput_wasm
|
||||
LinkerOutput=$LinkerOutput_wasm
|
||||
LinkerFlags=$LinkerFlags_wasm
|
||||
LinkerLibs=$LinkerLibs_wasm
|
||||
|
||||
elif [ "${PLATFORM}" == "linux" ]
|
||||
then
|
||||
Compiler=$Compiler_linux
|
||||
PlatformEntry=$PlatformEntry_linux
|
||||
CompilerFlags=$CompilerFlags_linux
|
||||
CompilerOutput=$CompilerOutput_linux
|
||||
LinkerOutput=$LinkerOutput_linux
|
||||
LinkerFlags=$LinkerFlags_linux
|
||||
LinkerLibs=$LinkerLibs_linux
|
||||
|
||||
elif [ "${PLATFORM}" == "raspi" ]
|
||||
then
|
||||
Compiler=$Compiler_raspi
|
||||
PlatformEntry=$PlatformEntry_raspi
|
||||
CompilerFlags=$CompilerFlags_raspi
|
||||
CompilerOutput=$CompilerOutput_raspi
|
||||
LinkerOutput=$LinkerOutput_raspi
|
||||
LinkerFlags=$LinkerFlags_raspi
|
||||
LinkerLibs=$LinkerLibs_raspi
|
||||
else
|
||||
echo "Attempting to build for an unknown platform: ${PLATFORM}"
|
||||
print_usage
|
||||
exit 0
|
||||
|
||||
fi
|
||||
|
||||
# Select Release Mode Variables
|
||||
|
||||
if [ "${MODE}" == "debug" ]
|
||||
then
|
||||
if [ $PLATFORM == "win32" ]
|
||||
then
|
||||
CompilerFlags="${CompilerFlags} ${CompilerFlags_DEBUG_win32}"
|
||||
else
|
||||
CompilerFlags="${CompilerFlags} ${CompilerFlags_DEBUG}"
|
||||
fi
|
||||
|
||||
LinkerFlags="${LinkerFlags} ${LinkerFlags_DEBUG}"
|
||||
|
||||
elif [ "${MODE}" == "prod" ]
|
||||
then
|
||||
CompilerFlags="${CompilerFlags} ${CompilerFlags_PROD}"
|
||||
LinkerFlags="${LinkerFlags} ${LinkerFlags_PROD}"
|
||||
|
||||
else
|
||||
echo "Attempting to build for an unknown release mode: ${MODE}"
|
||||
print_usage
|
||||
exit 0
|
||||
|
||||
fi
|
||||
|
||||
# Common Flags
|
||||
CompilerFlags="${CompilerFlags} ${CompilerFlags_common}"
|
||||
|
||||
# --------------------------------------------
|
||||
# Build Path Construction
|
||||
#
|
||||
# This determines where the generated executable will
|
||||
# be located. In general, it can be found at
|
||||
# project_path/run_tree/platform/arch/release_mode/lumenarium.exe
|
||||
#
|
||||
# This section also ensures that the path requested actually exists
|
||||
|
||||
BuildDir="${PROJECT_PATH}/run_tree/${PLATFORM}/${ARCH}/${MODE}"
|
||||
EntryPath="${PROJECT_PATH}/${PlatformEntry}"
|
||||
|
||||
# Exception for wasm, which doesn't care about cpu architecture
|
||||
if [ $PLATFORM == "wasm" ]
|
||||
then
|
||||
BuildDir="${PROJECT_PATH}/run_tree/${PLATFORM}/${MODE}"
|
||||
|
||||
fi
|
||||
|
||||
# Make the build directory,
|
||||
# "-p" flag makes it make the entire tree, and not emit errors if it
|
||||
# exists.
|
||||
mkdir -p "${BuildDir}"
|
||||
|
||||
# --------------------------------------------
|
||||
# Compilation
|
||||
|
||||
echo "Building To: ${BuildDir}/${LinkerOutput}"
|
||||
echo
|
||||
pushdir $BuildDir
|
||||
|
||||
echo "Cleaning: ${CompilerOutput} and ${LinkerOutput}"
|
||||
rm -rf ${CompilerOutput} ${LinkerOutput}
|
||||
|
||||
echo "COMPILING..."
|
||||
if [ $PLATFORM == "win32" ]
|
||||
then
|
||||
$Compiler \
|
||||
$CompilerFlags \
|
||||
$EntryPath \
|
||||
-link \
|
||||
$LinkerFlags \
|
||||
$LinkerLibs \
|
||||
-OUT:${LinkerOutput}
|
||||
|
||||
elif [ $PLATFORM == "wasm" ]
|
||||
then
|
||||
$Compiler \
|
||||
$CompilerFlags \
|
||||
-o $LinkerOutput \
|
||||
$EntryPath
|
||||
cp \
|
||||
"${PROJECT_PATH}/src_v2/platform/wasm/lumenarium_wasm_imports.js" \
|
||||
./lumenarium_wasm_imports.js
|
||||
|
||||
else
|
||||
|
||||
# Preprocessing Steps
|
||||
ConvertCsvEntry="${PROJECT_PATH}/src_v2/tools/convert_csv.c"
|
||||
$Compiler \
|
||||
-o convert_csv \
|
||||
$CompilerFlags \
|
||||
$ConvertCsvEntry \
|
||||
$LinkerLibs
|
||||
|
||||
./convert_csv
|
||||
|
||||
echo "$Compiler -o $LinkerOutput $CompilerFlags $EntryPath $LinkerLibs"
|
||||
$Compiler -o $LinkerOutput $CompilerFlags $EntryPath $LinkerLibs
|
||||
|
||||
fi
|
||||
|
||||
echo "Finished..."
|
||||
popdir
|
|
@ -0,0 +1,7 @@
|
|||
pushd build
|
||||
clang++ ../src/gs_osx.mm \
|
||||
-g \
|
||||
-Wno-c11-extensions -Wno-unused-variable -Wno-unused-function \
|
||||
-framework Cocoa -framework OpenGL \
|
||||
-o osx_foldhaus.out
|
||||
popd
|
|
@ -0,0 +1,26 @@
|
|||
@echo off
|
||||
|
||||
SET MyPath=%~dp0
|
||||
SET MyPath=%MyPath:~0,-1%
|
||||
call %MyPath%\_prebuild_win32.bat app debug clang
|
||||
|
||||
set CommonCompilerFlags=-std=c++11 -Wno-writable-strings -Wno-unused-value -Wno-varargs -Wno-switch -Wno-microsoft-enum-forward-reference -DDEBUG=1
|
||||
|
||||
pushd %BuildPath%
|
||||
|
||||
del *.pdb > NUL 2> NUL
|
||||
|
||||
echo WAITING FOR PDB TO WRITE > lock.tmp
|
||||
|
||||
clang++ %CommonCompilerFlags% %SourceCodePath%\foldhaus_app.cpp -shared -o
|
||||
|
||||
set LastError=%ERRORLEVEL%
|
||||
|
||||
del lock.tmp
|
||||
|
||||
clang++ -c %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp
|
||||
link win32_foldhaus.o user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib
|
||||
|
||||
popd
|
||||
|
||||
call %MyPath%\_postbuild_win32.bat
|
|
@ -0,0 +1,46 @@
|
|||
@echo off
|
||||
|
||||
SET MyPath=%~dp0
|
||||
SET MyPath=%MyPath:~0,-1%
|
||||
|
||||
call %MyPath%\_prebuild_win32.bat app debug msvc
|
||||
call %MyPath%\setup_cl.bat
|
||||
|
||||
SET CommonCompilerFlags=-nologo -DDEBUG=1 -DPLATFORM_WINDOWS -FC -WX -W4 -Z7 -Oi -GR- -EHsc -EHa- -MTd -fp:fast -fp:except- -IC:\programs-dev\gs_libs\src
|
||||
|
||||
SET CommonCompilerFlags=-wd4127 -wd4702 -wd4101 -wd4505 -wd4100 -wd4189 -wd4244 -wd4201 -wd4996 -I%CommonLibs% -Od %CommonCompilerFlags%
|
||||
|
||||
SET CommonLinkerFlags= -opt:ref -incremental:no
|
||||
|
||||
SET DLLExports=/EXPORT:InitializeApplication /EXPORT:UpdateAndRender /EXPORT:CleanupApplication /EXPORT:ReloadStaticData
|
||||
|
||||
pushd %BuildPath%
|
||||
|
||||
del *.pdb > NUL 2> NUL
|
||||
|
||||
echo WAITING FOR PDB TO WRITE > lock.tmp
|
||||
|
||||
cl %CommonCompilerFlags% %SourceCodePath%\foldhaus_app.cpp /Fefoldhaus.dll /LD /link %CommoLinkerFlags% %DLLExports%
|
||||
SET LastError=%ERRORLEVEL%
|
||||
|
||||
del lock.tmp
|
||||
|
||||
cl %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib Winspool.lib
|
||||
|
||||
|
||||
REM COMPILE UTILITY EXES
|
||||
|
||||
cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial_monitor.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib Winspool.lib
|
||||
|
||||
cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp /Fegen_blumen_lumen.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib
|
||||
|
||||
REM COMPILE AND RUN TESTS
|
||||
cl %CommonCompilerFlags% %ProjectDevPath%\src\tests\sanity_tests.cpp /Fesanity_tests.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib
|
||||
|
||||
ECHO SANITY TESTS BEGIN
|
||||
sanity_tests.exe
|
||||
ECHO SANITY TESTS END
|
||||
|
||||
popd
|
||||
|
||||
call %MyPath%\_postbuild_win32.bat
|
|
@ -1,88 +0,0 @@
|
|||
################# COMPILER #################
|
||||
# Compiler: Global
|
||||
|
||||
compiler>input>win32> ${SRC_DIR}/platform/win32/lumenarium_first_win32.c
|
||||
compiler>input>osx> ${SRC_DIR}/platform/osx/lumenarium_first_osx.c
|
||||
compiler>input>raspi> ${SRC_DIR}/platform/raspi/lumenarium_first_raspi.c
|
||||
|
||||
msvc>-nologo
|
||||
msvc>-FC # full path errors
|
||||
msvc>-WX # treat warnings as errors
|
||||
msvc>-W4 # output warning level
|
||||
msvc>-Z7 # generate C compatible debug info
|
||||
# msvc>-Oi # generate intrinsic functions
|
||||
# msvc>-MTd # create a debug multithreaded exe w/ Libcmtd.lib
|
||||
#msvc>-fp:fast # fast floating point model
|
||||
msvc>-wd4505 #
|
||||
msvc>-wd4100 #
|
||||
msvc>-wd4189 #
|
||||
msvc>-wd4702 #
|
||||
msvc>-wd4996 # _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
compiler>wasm>-Wno-writable-strings #
|
||||
compiler>wasm>--target=wasm32 #
|
||||
compiler>wasm>-nostdlib #
|
||||
compiler>wasm>-Wl,--no-entry #
|
||||
compiler>wasm>-Wl,--allow-undefined #
|
||||
compiler>wasm>-Wl,--export-all #
|
||||
|
||||
compiler>clang>linux>-pthread
|
||||
|
||||
compiler>raspi>-pthread
|
||||
compiler>raspi>-lm # link with local system math libraries
|
||||
|
||||
compiler>clang>arm64>-arch arm64
|
||||
|
||||
# Compiler: Debug
|
||||
|
||||
compiler>debug>msvc>win32>-Od #
|
||||
compiler>debug>msvc>win32>-Zi #
|
||||
compiler>debug>msvc>win32>-DDEBUG=1 #
|
||||
# compiler>debug>msvc>win32>-DPRINT_ASSERTS=1
|
||||
|
||||
compiler>debug>clang>-O0
|
||||
compiler>debug>clang>-g
|
||||
compiler>debug>compiler>-DDEBUG=1
|
||||
|
||||
compiler>debug>clang>-fsanitize=address
|
||||
|
||||
# Compiler: Prod
|
||||
compiler>release>clang>-O3
|
||||
|
||||
################# LINKER #################
|
||||
|
||||
linker>output>osx>lumenarium
|
||||
linker>output>win32>lumenarium.exe
|
||||
|
||||
linker>win32>-NOLOGO
|
||||
linker>win32>-incremental:no
|
||||
linker>win32>-subsystem:windows
|
||||
linker>win32>-opt:ref # link time optimization - eliminate dead code
|
||||
|
||||
linker>wasm>--no-entry
|
||||
linker>wasm>--export-dynamic
|
||||
linker>wasm>--unresolved-symbols=import-functions
|
||||
|
||||
# TODO: I don't think the build system supports this right now
|
||||
linker>raspi>-fuse-ld=lld
|
||||
|
||||
# linker>flags>debug>-debug
|
||||
linker>flags>debug>-fsanitize=address
|
||||
|
||||
################# LIBRARIES #################
|
||||
|
||||
linker>libs>win32>user32.lib
|
||||
linker>libs>win32>kernel32.lib
|
||||
linker>libs>win32>gdi32.lib
|
||||
linker>libs>win32>opengl32.lib
|
||||
linker>libs>win32>winmm.lib
|
||||
linker>libs>win32>gdi32.lib
|
||||
linker>libs>win32>dsound.lib
|
||||
linker>libs>win32>Ws2_32.lib
|
||||
linker>libs>win32>Comdlg32.lib
|
||||
linker>libs>win32>Winspool.lib
|
||||
|
||||
linker>libs>osx>-framework OpenGL
|
||||
linker>libs>osx>-framework Cocoa
|
||||
linker>libs>osx>-framework IOKit
|
||||
linker>libs>osx>${SRC_DIR}/libs/glfw_osx/lib-universal/libglfw3.a
|
|
@ -0,0 +1,17 @@
|
|||
@echo off
|
||||
|
||||
SET MyPath=%~dp0
|
||||
SET MyPath=%MyPath:~0,-1%
|
||||
call %MyPath%\_prebuild_win32.bat meta debug msvc
|
||||
|
||||
set CommonCompilerFlags=-nologo -DDEBUG=1 -DPLATFORM_WINDOWS -FC -WX -W4 -Z7 -Oi -GR- -EHsc -EHa- -MTd -fp:fast -fp:except-
|
||||
set CommonCompilerFlags=-wd4127 -wd4702 -wd4101 -wd4505 -wd4100 -wd4189 -wd4244 -wd4201 -wd4996 -I%CommonLibs% -O2 %CommonCompilerFlags%
|
||||
set CommonLinkerFlags= -opt:ref
|
||||
|
||||
pushd %BuildPath%
|
||||
|
||||
cl %CommonCompilerFlags% %SourceCodePath%\foldhaus_meta.cpp /link %CommonLinkerFlags%
|
||||
|
||||
popd
|
||||
|
||||
call %MyPath%\_postbuild_win32.bat
|
|
@ -0,0 +1,40 @@
|
|||
@echo off
|
||||
|
||||
ECHO SETUP CL
|
||||
|
||||
SET "LIB="
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio 12.0
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio 11.0
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio 10.0
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio 13.0
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\Auxiliary\Build\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\Auxiliary\Build\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\Auxiliary\Build\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\Auxiliary\Build\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\Auxiliary\Build\vcvarsall.bat" x64))
|
||||
|
||||
SET VC_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional
|
||||
IF NOT DEFINED LIB (IF EXIST "%VC_PATH%" (call "%VC_PATH%\VC\Auxiliary\Build\vcvarsall.bat" x64))
|
||||
|
||||
ECHO SETUP CL COMPLETE
|
Binary file not shown.
Before Width: | Height: | Size: 313 KiB |
|
@ -16,7 +16,8 @@ blacklist_patterns = {
|
|||
load_paths_base = {
|
||||
{ ".", .relative = true, .recursive = false, },
|
||||
{ "build", .relative = true, .recursive = false, },
|
||||
{ "src", .relative = true, .recursive = true, },
|
||||
// { "src", .relative = true, .recursive = true, },
|
||||
{ "src_v2", .relative = true, .recursive = true, },
|
||||
{ "meta", .relative = true, .recursive = true, },
|
||||
{ "gs_libs", .relative = true, .recursive = true, },
|
||||
};
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="gl_canvas" width="640" height="480"></canvas>
|
||||
|
||||
<script type="text/javascript" src="lumenarium_wasm_imports.js"></script>
|
||||
<script type="text/javascript" src="loader.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
let module = null;
|
||||
let instance = null;
|
||||
|
||||
|
||||
async function load_webassembly_module ()
|
||||
{
|
||||
lumenarium_wasm_imports = webgl_add_imports("#gl_canvas", lumenarium_wasm_imports);
|
||||
|
||||
const path = "lumenarium.wasm";
|
||||
const promise = fetch(path);
|
||||
const module = await WebAssembly.compileStreaming(promise);
|
||||
|
||||
let memory = new WebAssembly.Memory({ initial: 2 });
|
||||
const env = {
|
||||
memory,
|
||||
...lumenarium_wasm_imports,
|
||||
};
|
||||
|
||||
let table = new WebAssembly.Table({ element: "anyfunc", initial: 32, });
|
||||
|
||||
instance = await WebAssembly.instantiate(module, { env })
|
||||
.then((res, err) => {
|
||||
return res;
|
||||
})
|
||||
.catch((a, b) => {
|
||||
console.log(a,b);
|
||||
});
|
||||
lumenarium_wasm_instance = instance;
|
||||
|
||||
// If function '__wasm_call_ctors' (global C++ constructors) exists, call it
|
||||
if (instance.exports.__wasm_call_ctors) instance.exports.__wasm_call_ctors();
|
||||
|
||||
// If function 'main' exists, call it with dummy arguments
|
||||
let result = 0;
|
||||
if (instance.exports.main) result = instance.exports.main();
|
||||
}
|
||||
|
||||
window.addEventListener("load", load_webassembly_module)
|
Binary file not shown.
|
@ -0,0 +1,167 @@
|
|||
var lumenarium_wasm_module = null;
|
||||
var lumenarium_wasm_instance = null;
|
||||
|
||||
var WASM_PAGE_SIZE = 65536;
|
||||
|
||||
function wasm_mem_get_u8_arr(inst, ptr, size)
|
||||
{
|
||||
let view = new Uint8Array(inst.exports.memory.buffer, ptr, size);
|
||||
return view;
|
||||
}
|
||||
|
||||
function wasm_read_string(inst, ptr, len)
|
||||
{
|
||||
let view = wasm_mem_get_u8_arr(inst, ptr, len);
|
||||
let string = '';
|
||||
for (let i = 0; i < len; i++)
|
||||
{
|
||||
string += String.fromCharCode(view[i]);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
function wasm_write_bytes(inst, src, ptr, len)
|
||||
{
|
||||
let view = wasm_mem_get_u8_arr(inst, ptr, len);
|
||||
for (let i = 0; i < len; i++) view[i] = src[i];
|
||||
}
|
||||
|
||||
function wasm_get_proc(inst, proc_ptr)
|
||||
{
|
||||
let result = inst.exports.__indirect_function_table.get(proc_ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
function fract (v) { return v % 1; }
|
||||
|
||||
var lumenarium_wasm_imports = {
|
||||
|
||||
memset: (dst, size, value) => {
|
||||
let view_dst = wasm_mem_get_u8_arr(lumenarium_wasm_instance, dst, size);
|
||||
for (let i = 0; i < size; i++)
|
||||
{
|
||||
view_dst[i] = value;
|
||||
}
|
||||
},
|
||||
|
||||
memcpy: (dst, src, size) => {
|
||||
let view_dst = wasm_mem_get_u8_arr(lumenarium_wasm_instance, dst, size);
|
||||
let view_src = wasm_mem_get_u8_arr(lumenarium_wasm_instance, src, size);
|
||||
for (let i = 0; i < size; i++)
|
||||
{
|
||||
view_dst[i] = view_src[i];
|
||||
}
|
||||
},
|
||||
|
||||
wasm_assert_always: () => {
|
||||
console.assert(false);
|
||||
},
|
||||
|
||||
wasm_get_memory_size: () => {
|
||||
return instance.exports.memory.buffer.byteLength;
|
||||
},
|
||||
|
||||
wasm_mem_grow: (new_size) => {
|
||||
let pages = new_size / WASM_PAGE_SIZE;
|
||||
let pages_rem = fract(pages);
|
||||
if (pages_rem > 0) pages = Math.floor(pages) + 1;
|
||||
let size_before = lumenarium_wasm_instance.exports.memory.buffer.byteLength;
|
||||
let old_page_count = lumenarium_wasm_instance.exports.memory.grow(pages);
|
||||
|
||||
console.log("mem_grow\n",
|
||||
"req size: ", new_size, "\n",
|
||||
"old size: ", (old_page_count * WASM_PAGE_SIZE), "\n",
|
||||
"old size: ", size_before, "\n",
|
||||
"grew by: ", (pages * WASM_PAGE_SIZE), "\n",
|
||||
"new size: ", lumenarium_wasm_instance.exports.memory.buffer.byteLength, "");
|
||||
},
|
||||
|
||||
wasm_performance_now: () => {
|
||||
return performance.now();
|
||||
},
|
||||
|
||||
wasm_sleep: (milliseconds) => {
|
||||
let start = Date.now();
|
||||
for (let at = Date.now(); (at - start) < milliseconds; at = Date.now()) {}
|
||||
},
|
||||
|
||||
wasm_fetch: async (file_path, file_path_len, dest, dest_size) => {
|
||||
let path = wasm_read_string(lumenarium_wasm_instance, file_path, file_path_len);
|
||||
fetch(path)
|
||||
.then(async (res) => {
|
||||
// TODO(PS): success checking
|
||||
let reader = res.body.getReader();
|
||||
let read_res = { done: false };
|
||||
|
||||
let view = wasm_mem_get_u8_arr(lumenarium_wasm_instance, dest, dest_size);
|
||||
let last_write = 0;
|
||||
while (!read_res.done)
|
||||
{
|
||||
read_res = await reader.read();
|
||||
if (read_res.done) break;
|
||||
|
||||
let len = read_res.value.length;
|
||||
let write_end = last_write + len;
|
||||
for (let i = last_write; i < write_end; i++)
|
||||
{
|
||||
view[i] = read_res.value[i - last_write];
|
||||
}
|
||||
last_write = write_end + 1;
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
},
|
||||
|
||||
wasm_request_animation_frame: (cb) => {
|
||||
let cb_proc = wasm_get_proc(lumenarium_wasm_instance, cb);
|
||||
window.requestAnimationFrame(cb_proc);
|
||||
},
|
||||
|
||||
print: (str_base, len) => {
|
||||
let string = wasm_read_string(lumenarium_wasm_instance, str_base, len);
|
||||
console.log(string);
|
||||
},
|
||||
};
|
||||
|
||||
let gl = null;
|
||||
|
||||
function glClearColor (r, g, b, a) { gl.clearColor(r,g,b,a); }
|
||||
function glEnable(v) { gl.enable(v); }
|
||||
function glDisable(v) { gl.disable(v); }
|
||||
function glBlendFunc(a,b) { gl.blendFunc(a,b); }
|
||||
function glViewport(xmin, ymin, xmax, ymax) { gl.viewport(xmin,ymin,xmax,ymax); }
|
||||
function glDepthFunc(v) { gl.depthFunc(v); }
|
||||
function glClear(mask) { gl.clear(mask); }
|
||||
|
||||
function webgl_add_imports (canvas_selector, imports) {
|
||||
const canvas = document.querySelector(canvas_selector);
|
||||
if (!canvas) return console.error("no canvas");
|
||||
|
||||
gl = canvas.getContext("webgl");
|
||||
if (gl === null) return console.error("no webgl ctx");
|
||||
|
||||
///////////////////////////////////////
|
||||
// Constants
|
||||
|
||||
imports.GL_TEXTURE_2D = gl.TEXTURE_2D;
|
||||
imports.GL_BLEND = gl.BLEND;
|
||||
imports.GL_SRC_ALPHA = gl.SRC_ALPHA;
|
||||
imports.GL_ONE_MINUS_SRC_ALPHA = gl.ONE_MINUS_SRC_ALPHA;
|
||||
imports.GL_DEPTH_TEST = gl.DEPTH_TEST;
|
||||
imports.GL_LESS = gl.LESS;
|
||||
imports.GL_COLOR_BUFFER_BIT = gl.COLOR_BUFFER_BIT;
|
||||
imports.GL_DEPTH_BUFFER_BIT = gl.DEPTH_BUFFER_BIT;
|
||||
|
||||
///////////////////////////////////////
|
||||
// Functions
|
||||
|
||||
imports.glClearColor = glClearColor;
|
||||
imports.glEnable = glEnable;
|
||||
imports.glDisable = glDisable;
|
||||
imports.glBlendFunc = glBlendFunc;
|
||||
imports.glViewport = glViewport;
|
||||
imports.glDepthFunc = glDepthFunc;
|
||||
imports.glClear = glClear;
|
||||
|
||||
return imports;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
OpenGL Version: 3.3.0 - Build 27.20.100.9778
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,159 @@
|
|||
//
|
||||
// File: foldhaus_default_nodes.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_DEFAULT_NODES_H
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// Values
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
NODE_STRUCT(float_value_data)
|
||||
{
|
||||
NODE_IN(r32, Value);
|
||||
NODE_OUT(r32, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(FloatValue, float_value_data)
|
||||
{
|
||||
Data->Result = Data->Value;
|
||||
}
|
||||
|
||||
NODE_STRUCT(vector_data)
|
||||
{
|
||||
NODE_IN(r32, X);
|
||||
NODE_IN(r32, Y);
|
||||
NODE_IN(r32, Z);
|
||||
NODE_IN(r32, W);
|
||||
NODE_OUT(v4, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(VectorValue, vector_data)
|
||||
{
|
||||
Data->Result = v4{Data->X, Data->Y, Data->Z, Data->W};
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// Arithmetic
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
NODE_STRUCT(multiply_data)
|
||||
{
|
||||
NODE_IN(r32, A);
|
||||
NODE_IN(r32, B);
|
||||
NODE_OUT(r32, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(MultiplyNodeProc, multiply_data)
|
||||
{
|
||||
Data->Result = Data->A * Data->B;
|
||||
}
|
||||
|
||||
NODE_STRUCT(add_data)
|
||||
{
|
||||
NODE_IN(v4, A);
|
||||
NODE_IN(v4, B);
|
||||
NODE_OUT(v4, Result);
|
||||
};
|
||||
|
||||
NODE_PROC(AddNodeProc, add_data)
|
||||
{
|
||||
Data->Result = Data->A + Data->B;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// Animators
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
GSMetaTag(node_struct);
|
||||
struct sin_wave_data
|
||||
{
|
||||
GSMetaTag(node_input);
|
||||
r32 Period;
|
||||
|
||||
GSMetaTag(node_input);
|
||||
r32 Min;
|
||||
|
||||
GSMetaTag(node_input);
|
||||
r32 Max;
|
||||
|
||||
GSMetaTag(node_input);
|
||||
r32 Result;
|
||||
|
||||
r32 Accumulator;
|
||||
};
|
||||
|
||||
NODE_PROC(SinWave, sin_wave_data)
|
||||
{
|
||||
Data->Accumulator += DeltaTime;
|
||||
if (Data->Period > 0)
|
||||
{
|
||||
while (Data->Accumulator > Data->Period)
|
||||
{
|
||||
Data->Accumulator -= Data->Period;
|
||||
}
|
||||
|
||||
r32 ActualMin = Min(Data->Min, Data->Max);
|
||||
r32 ActualMax = Max(Data->Min, Data->Max);
|
||||
r32 SinResult = SinR32((Data->Accumulator / Data->Period) * PiR32 * 2);
|
||||
Data->Result = RemapR32(SinResult, -1.f, 1.f, ActualMin, ActualMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data->Result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// Pattern Mixing
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
GSMetaTag(node_struct);
|
||||
struct multiply_patterns_data
|
||||
{
|
||||
GSMetaTag(node_input);
|
||||
color_buffer A;
|
||||
|
||||
GSMetaTag(node_input);
|
||||
color_buffer B;
|
||||
|
||||
GSMetaTag(node_output);
|
||||
color_buffer Result;
|
||||
};
|
||||
|
||||
NODE_PROC(MultiplyPatterns, multiply_patterns_data)
|
||||
{
|
||||
for (s32 LedIndex = 0; LedIndex < Data->Result.LEDCount; LedIndex++)
|
||||
{
|
||||
Assert(LedIndex >= 0 && LedIndex < Data->Result.LEDCount);
|
||||
|
||||
s32 AR = Data->A.Colors[LedIndex].R;
|
||||
s32 AG = Data->A.Colors[LedIndex].G;
|
||||
s32 AB = Data->A.Colors[LedIndex].B;
|
||||
|
||||
s32 BR = Data->B.Colors[LedIndex].R;
|
||||
s32 BG = Data->B.Colors[LedIndex].G;
|
||||
s32 BB = Data->B.Colors[LedIndex].B;
|
||||
|
||||
s32 RCombined = (AR * BR) / 255;
|
||||
s32 GCombined = (AG * BG) / 255;
|
||||
s32 BCombined = (AB * BB) / 255;
|
||||
|
||||
Data->Result.Colors[LedIndex].R = (u8)RCombined;
|
||||
Data->Result.Colors[LedIndex].G = (u8)GCombined;
|
||||
Data->Result.Colors[LedIndex].B = (u8)BCombined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_DEFAULT_NODES_H
|
||||
#endif // FOLDHAUS_DEFAULT_NODES_H
|
|
@ -0,0 +1,188 @@
|
|||
//
|
||||
// File: foldhaus_node.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_NODE_CPP
|
||||
|
||||
internal b32
|
||||
MemberIsInput(gsm_struct_member_type_info Member)
|
||||
{
|
||||
b32 Result = (0 <= gsm_GetMetaTagIndex(MetaTag_node_input, Member.Tags, Member.TagsCount));
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
MemberIsOutput(gsm_struct_member_type_info Member)
|
||||
{
|
||||
b32 Result = (0 <= gsm_GetMetaTagIndex(MetaTag_node_output, Member.Tags, Member.TagsCount));
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
ClearNodeWorkspaceStorage(pattern_node_workspace* Workspace)
|
||||
{
|
||||
ClearArena(&Workspace->Storage);
|
||||
Workspace->SparseToSortedNodeMap = 0;
|
||||
Workspace->SortedNodeHandles = 0;
|
||||
}
|
||||
|
||||
struct adjacency_list
|
||||
{
|
||||
// TODO(Peter): Can make these as buffers, not single digits later
|
||||
gs_list_handle NodeHandle;
|
||||
adjacency_list* Next;
|
||||
};
|
||||
|
||||
internal u32
|
||||
SortNodeNeighbors(u32 ContiguousNodeIndex, gs_list_handle NodeHandle, adjacency_list** NeighborsLists, b8* NodesVisited, gs_list_handle* SortedNodeHandles, u32 SortedNodesCount, s32* SparseToContiguousNodeMap)
|
||||
{
|
||||
NodesVisited[ContiguousNodeIndex] = true;
|
||||
|
||||
adjacency_list* Neighbor = NeighborsLists[ContiguousNodeIndex];
|
||||
while (Neighbor)
|
||||
{
|
||||
u32 ContiguousNeighborNodeIndex = SparseToContiguousNodeMap[Neighbor->NodeHandle.Index];
|
||||
if (!NodesVisited[ContiguousNeighborNodeIndex])
|
||||
{
|
||||
SortedNodesCount = SortNodeNeighbors(ContiguousNeighborNodeIndex, Neighbor->NodeHandle, NeighborsLists, NodesVisited, SortedNodeHandles, SortedNodesCount, SparseToContiguousNodeMap);
|
||||
}
|
||||
Neighbor = Neighbor->Next;
|
||||
}
|
||||
|
||||
SortedNodeHandles[SortedNodesCount++] = NodeHandle;
|
||||
return SortedNodesCount;
|
||||
}
|
||||
|
||||
internal s32*
|
||||
CreateSparseToContiguousMap (pattern_node_workspace Workspace, gs_memory_arena* Scratch)
|
||||
{
|
||||
s32* Result = PushArray(Scratch, s32, Workspace.Nodes.OnePastLastUsed);
|
||||
s32 ContiguousIndex = 0;
|
||||
for (u32 SparseNodeIndex = 0; SparseNodeIndex < Workspace.Nodes.OnePastLastUsed; SparseNodeIndex++)
|
||||
{
|
||||
gs_list_entry<pattern_node>* Entry = Workspace.Nodes.GetEntryAtIndex(SparseNodeIndex);
|
||||
if (!EntryIsFree(Entry))
|
||||
{
|
||||
Result[SparseNodeIndex] = ContiguousIndex++;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
UpdateSortedNodes(pattern_node_workspace* Workspace, gs_memory_arena* Scratch)
|
||||
{
|
||||
ClearNodeWorkspaceStorage(Workspace);
|
||||
|
||||
u32 NodeCount = Workspace->Nodes.Used;
|
||||
u32 SparseNodeCount = Workspace->Nodes.OnePastLastUsed;
|
||||
|
||||
s32* SparseToContiguousNodeMap = CreateSparseToContiguousMap(*Workspace, &Workspace->Storage);
|
||||
|
||||
// NOTE(Peter): We need to sort this later on so I'm just storing list lengths in this format
|
||||
// to begin with.
|
||||
// NeighborsListLengths[n].Radix = the number of neighbors for the node
|
||||
// NeighborsListLengths[n].ID = the sparse array index of the node
|
||||
gs_radix_entry* NeighborsListLengths = PushArray(Scratch, gs_radix_entry, NodeCount);
|
||||
adjacency_list** NeighborsLists = PushArray(Scratch, adjacency_list*, NodeCount);
|
||||
GSZeroArray(NeighborsLists, adjacency_list*, SparseNodeCount);
|
||||
|
||||
// Fill Radix
|
||||
for (u32 n = 0; n < SparseNodeCount; n++)
|
||||
{
|
||||
s32 ContiguousIndex = SparseToContiguousNodeMap[n];
|
||||
if (ContiguousIndex >= 0)
|
||||
{
|
||||
NeighborsListLengths[ContiguousIndex].Radix = 0;
|
||||
NeighborsListLengths[ContiguousIndex].ID = n;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct Adjaceny List
|
||||
for (u32 c = 0; c < Workspace->Connections.Used; c++)
|
||||
{
|
||||
pattern_node_connection Connection = *Workspace->Connections.GetElementAtIndex(c);
|
||||
|
||||
adjacency_list* ListAddition = PushStruct(Scratch, adjacency_list);
|
||||
ListAddition->NodeHandle = Connection.DownstreamNodeHandle;
|
||||
|
||||
s32 ContiguousNodeIndex = SparseToContiguousNodeMap[Connection.UpstreamNodeHandle.Index];
|
||||
ListAddition->Next = NeighborsLists[ContiguousNodeIndex];
|
||||
NeighborsLists[ContiguousNodeIndex] = ListAddition;
|
||||
|
||||
// Increment the number of neighbors - stored in Radix
|
||||
NeighborsListLengths[ContiguousNodeIndex].Radix++;
|
||||
}
|
||||
|
||||
// Sort by number of neighbors
|
||||
RadixSortInPlace(NeighborsListLengths, Workspace->Nodes.Used);
|
||||
|
||||
char* OutputCharArray = PushArray(Scratch, char, 1024);
|
||||
gs_string Outputgs_string = MakeString(OutputCharArray, 0, 1024);
|
||||
|
||||
PrintF(&Outputgs_string, "Neighbors Lists: \n");
|
||||
for (u32 d = 0; d < Workspace->Nodes.Used; d++)
|
||||
{
|
||||
PrintF(&Outputgs_string, " %d: Node [ %d ] : neighbors { ", d, NeighborsListLengths[d].ID);
|
||||
|
||||
adjacency_list* Neighbors = NeighborsLists[d];
|
||||
while (Neighbors)
|
||||
{
|
||||
PrintF(&Outputgs_string, "%d, ", Neighbors->NodeHandle.Index);
|
||||
Neighbors = Neighbors->Next;
|
||||
}
|
||||
PrintF(&Outputgs_string, " }\n");
|
||||
}
|
||||
NullTerminate(&Outputgs_string);
|
||||
|
||||
// This is a contiguous array.
|
||||
b8* NodesVisited = PushArray(Scratch, b8, NodeCount);
|
||||
GSZeroArray(NodesVisited, b8, NodeCount);
|
||||
|
||||
Workspace->SortedNodeHandles = PushArray(&Workspace->Storage, gs_list_handle, NodeCount);
|
||||
u32 SortedSparseNodeIndeciesUsed = 0;
|
||||
|
||||
for (u32 n = 0; n < Workspace->Nodes.Used; n++)
|
||||
{
|
||||
gs_radix_entry SortedNeighborsCount = NeighborsListLengths[n];
|
||||
u32 NeighborCount = SortedNeighborsCount.Radix;
|
||||
u32 NodeIndex = SortedNeighborsCount.ID;
|
||||
gs_list_handle NodeHandle = Workspace->Nodes.GetEntryAtIndex(NodeIndex)->Handle;
|
||||
u32 ContiguousNodeIndex = SparseToContiguousNodeMap[NodeIndex];
|
||||
|
||||
SortedSparseNodeIndeciesUsed = SortNodeNeighbors(ContiguousNodeIndex, NodeHandle, NeighborsLists, NodesVisited, Workspace->SortedNodeHandles, SortedSparseNodeIndeciesUsed, SparseToContiguousNodeMap);
|
||||
}
|
||||
|
||||
Workspace->SparseToSortedNodeMap = SparseToContiguousNodeMap;
|
||||
for (u32 SortedIndex = 0; SortedIndex < NodeCount; SortedIndex++)
|
||||
{
|
||||
gs_list_handle SortedHandle = Workspace->SortedNodeHandles[SortedIndex];
|
||||
Workspace->SparseToSortedNodeMap[SortedHandle.Index] = SortedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
PushNodeOnWorkspace(s32 NodeSpecificationIndex, pattern_node_workspace* Workspace, gs_memory_arena* Scratch)
|
||||
{
|
||||
pattern_node* NewNode = Workspace->Nodes.TakeElement();
|
||||
NewNode->SpecificationIndex = NodeSpecificationIndex;
|
||||
|
||||
UpdateSortedNodes(Workspace, Scratch);
|
||||
}
|
||||
|
||||
internal void
|
||||
PushNodeConnectionOnWorkspace(gs_list_handle UpstreamNodeHandle, u32 UpstreamPortIndex, gs_list_handle DownstreamNodeHandle, u32 DownstreamPortIndex, pattern_node_workspace* Workspace, gs_memory_arena* Scratch)
|
||||
{
|
||||
pattern_node_connection Connection = {};
|
||||
Connection.UpstreamNodeHandle = UpstreamNodeHandle;
|
||||
Connection.DownstreamNodeHandle = DownstreamNodeHandle;
|
||||
Connection.UpstreamPortIndex = UpstreamPortIndex;
|
||||
Connection.DownstreamPortIndex = DownstreamPortIndex;
|
||||
|
||||
Workspace->Connections.PushElementOnBucket(Connection);
|
||||
UpdateSortedNodes(Workspace, Scratch);
|
||||
}
|
||||
|
||||
#define FOLDHAUS_NODE_CPP
|
||||
#endif // FOLDHAUS_NODE_CPP
|
|
@ -0,0 +1,134 @@
|
|||
//
|
||||
// File: foldhaus_node.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_NODE_H
|
||||
|
||||
typedef enum node_type node_type;
|
||||
|
||||
#define IsInputMember 1 << 0
|
||||
#define IsOutputMember 1 << 1
|
||||
|
||||
#define DEFAULT_NODE_DIMENSION v2{125, 150}
|
||||
|
||||
struct color_buffer
|
||||
{
|
||||
v4* LedPositions;
|
||||
pixel* Colors;
|
||||
s32 LEDCount;
|
||||
};
|
||||
|
||||
// TODO(Peter): Use the Meta RTTI
|
||||
// :UseMetaInfo
|
||||
enum struct_member_type
|
||||
{
|
||||
MemberType_Invalid,
|
||||
MemberType_s32,
|
||||
MemberType_r32,
|
||||
MemberType_v4,
|
||||
MemberType_NODE_COLOR_BUFFER,
|
||||
MemberTypeCount,
|
||||
};
|
||||
|
||||
// TODO(Peter): Use the Meta RTTI
|
||||
// :UseMetaInfo
|
||||
struct node_struct_member
|
||||
{
|
||||
struct_member_type Type;
|
||||
char* Name;
|
||||
u64 Offset;
|
||||
b32 IsInput;
|
||||
};
|
||||
|
||||
// :UseMetaInfo
|
||||
struct node_specification
|
||||
{
|
||||
node_type Type;
|
||||
|
||||
char* Name;
|
||||
s32 NameLength;
|
||||
|
||||
node_struct_member* MemberList;
|
||||
u32 DataStructSize;
|
||||
u32 MemberListLength;
|
||||
|
||||
b32 IsPattern;
|
||||
};
|
||||
|
||||
struct node_specification_
|
||||
{
|
||||
node_type Type;
|
||||
gs_string Identifier;
|
||||
gsm_struct_type DataType;
|
||||
};
|
||||
|
||||
struct pattern_node
|
||||
{
|
||||
// TODO(Peter): Something to think about further down the line is the fact that
|
||||
// SpecificationIndex doesn't have to stay static throughout a single instance of
|
||||
// an application, let alone across separate runs. If you recompile (hot load or not)
|
||||
// with a new specification, the indecies all get thrown off. Should we hash the spec
|
||||
// names or something?
|
||||
|
||||
// TODO(Peter): A more immediate thing to handle is that u32 should really be node_type
|
||||
u32 SpecificationIndex;
|
||||
};
|
||||
|
||||
struct pattern_node_connection
|
||||
{
|
||||
gs_list_handle UpstreamNodeHandle;
|
||||
gs_list_handle DownstreamNodeHandle;
|
||||
|
||||
u32 UpstreamPortIndex;
|
||||
u32 DownstreamPortIndex;
|
||||
};
|
||||
|
||||
struct pattern_node_workspace
|
||||
{
|
||||
gs_list<pattern_node> Nodes;
|
||||
gs_bucket<pattern_node_connection> Connections;
|
||||
|
||||
// This is storage for all the structures which follow.
|
||||
// It is cleared when new nodes are added so that the
|
||||
// acceleration structures can be recalculated
|
||||
gs_memory_arena Storage;
|
||||
s32* SparseToSortedNodeMap;
|
||||
gs_list_handle* SortedNodeHandles;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// Pre Processor Macros
|
||||
///////////////////////////////////////////////
|
||||
|
||||
#define NODE_STRUCT(data_name) \
|
||||
struct data_name
|
||||
|
||||
#define NODE_PATTERN_STRUCT(data_name) \
|
||||
struct data_name
|
||||
|
||||
#define NODE_PROC(proc_name, input_type) \
|
||||
void proc_name(input_type* Data, r32 DeltaTime)
|
||||
|
||||
#define NODE_IN(type, name) type name
|
||||
#define NODE_OUT(type, name) type name
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// OUTPUT NODE
|
||||
///////////////////////////////////////////////
|
||||
|
||||
struct output_node_data
|
||||
{
|
||||
GSMetaTag(node_input);
|
||||
color_buffer Result;
|
||||
};
|
||||
|
||||
void OutputNode(output_node_data* Data, r32 DeltaTime)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#define FOLDHAUS_NODE_H
|
||||
#endif // FOLDHAUS_NODE_H
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// File: foldhaus_node_gui.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_NODE_GUI_H
|
||||
|
||||
struct gui_node
|
||||
{
|
||||
s32 Handle;
|
||||
node_type Type;
|
||||
v2 Min, Dim;
|
||||
};
|
||||
|
||||
#define GUI_NODES_MAX 256
|
||||
struct gui_node_list
|
||||
{
|
||||
s32 NodesUsed;
|
||||
gui_node Nodes[GUI_NODES_MAX];
|
||||
};
|
||||
|
||||
|
||||
#define FOLDHAUS_NODE_GUI_H
|
||||
#endif // FOLDHAUS_NODE_GUI_H
|
|
@ -0,0 +1,546 @@
|
|||
//
|
||||
// File: foldhaus_panel_node_graph.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_NODE_GRAPH_H
|
||||
|
||||
struct visual_node
|
||||
{
|
||||
node_specification_ Spec;
|
||||
v2 Position;
|
||||
};
|
||||
|
||||
struct visual_port
|
||||
{
|
||||
gs_list_handle SparseNodeHandle;
|
||||
u32 PortIndex;
|
||||
rect2 PortBounds;
|
||||
};
|
||||
|
||||
struct visual_connection
|
||||
{
|
||||
u32 UpstreamVisualPortIndex;
|
||||
u32 DownstreamVisualPortIndex;
|
||||
v2 UpstreamPosition;
|
||||
v2 DownstreamPosition;
|
||||
};
|
||||
|
||||
struct node_layout
|
||||
{
|
||||
// NOTE(Peter): This Map is a sparse array.
|
||||
// index i corresponds to index i in some list of nodes
|
||||
// the value at index i is the index of that node in a compressed list
|
||||
// if the value at i is -1, that means the entry is free
|
||||
s32* SparseToContiguousNodeMap;
|
||||
u32 SparseToContiguousNodeMapCount;
|
||||
|
||||
visual_node* VisualNodes;
|
||||
u32* VisualNodeLayers;
|
||||
u32 VisualNodesCount;
|
||||
|
||||
visual_port* VisualPorts;
|
||||
u32 VisualPortsCount;
|
||||
|
||||
visual_connection* VisualConnections;
|
||||
u32 VisualConnectionsCount;
|
||||
|
||||
u32 LayerCount;
|
||||
v2* LayerPositions;
|
||||
|
||||
b32 ConnectionIsInProgress;
|
||||
v2 InProgressConnectionStart;
|
||||
v2 InProgressConnectionEnd;
|
||||
};
|
||||
|
||||
struct node_graph_state
|
||||
{
|
||||
v2 ViewOffset;
|
||||
|
||||
gs_memory_arena LayoutMemory;
|
||||
node_layout Layout;
|
||||
|
||||
b32 LayoutIsDirty;
|
||||
};
|
||||
|
||||
//
|
||||
// Pan Node Graph
|
||||
//
|
||||
|
||||
OPERATION_STATE_DEF(pan_node_graph_operation_state)
|
||||
{
|
||||
v2 InitialViewOffset;
|
||||
|
||||
// TODO(Peter): I DON"T LIKE THIS!!!!
|
||||
// We should have a way to access the panel that created an operation mode or something
|
||||
v2* ViewOffset;
|
||||
};
|
||||
|
||||
OPERATION_RENDER_PROC(UpdatePanNodeGraph)
|
||||
{
|
||||
pan_node_graph_operation_state* OpState = (pan_node_graph_operation_state*)Operation.OpStateMemory;
|
||||
v2 MouseDelta = Mouse.Pos - Mouse.DownPos;
|
||||
*OpState->ViewOffset = MouseDelta + OpState->InitialViewOffset;
|
||||
}
|
||||
|
||||
input_command PanNodeGraphCommands[] = {
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndCurrentOperationMode },
|
||||
};
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(BeginPanNodeGraph)
|
||||
{
|
||||
operation_mode* PanNodeGraph = ActivateOperationModeWithCommands(&State->Modes, PanNodeGraphCommands, UpdatePanNodeGraph);
|
||||
pan_node_graph_operation_state* OpState = CreateOperationState(PanNodeGraph, &State->Modes, pan_node_graph_operation_state);
|
||||
|
||||
panel* NodeGraphPanel = State->HotPanel;
|
||||
node_graph_state* NodeGraphState = (node_graph_state*)NodeGraphPanel->PanelStateMemory;
|
||||
OpState->InitialViewOffset = NodeGraphState->ViewOffset;
|
||||
OpState->ViewOffset = &NodeGraphState->ViewOffset;
|
||||
}
|
||||
|
||||
//
|
||||
// Connect Nodes
|
||||
//
|
||||
|
||||
OPERATION_STATE_DEF(connect_nodes_operation_state)
|
||||
{
|
||||
visual_port VisualPort;
|
||||
u32 VisualPortIndex;
|
||||
b32 IsInput;
|
||||
};
|
||||
|
||||
OPERATION_RENDER_PROC(UpdateConnectNodeOperation)
|
||||
{
|
||||
panel_with_layout NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds);
|
||||
node_graph_state* GraphState = (node_graph_state*)NodeGraphPanel.Panel->PanelStateMemory;
|
||||
|
||||
GraphState->Layout.InProgressConnectionEnd = Mouse.Pos;
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(EndConnectNodesOperation)
|
||||
{
|
||||
connect_nodes_operation_state* OpState = GetCurrentOperationState(State->Modes, connect_nodes_operation_state);
|
||||
|
||||
panel_with_layout NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds);
|
||||
node_graph_state* GraphState = (node_graph_state*)NodeGraphPanel.Panel->PanelStateMemory;
|
||||
GraphState->Layout.ConnectionIsInProgress = false;
|
||||
|
||||
for (u32 p = 0; p < GraphState->Layout.VisualPortsCount; p++)
|
||||
{
|
||||
visual_port VisualPort = GraphState->Layout.VisualPorts[p];
|
||||
rect2 ViewAdjustedBounds = gs_RectOffsetByVector(VisualPort.PortBounds, GraphState->ViewOffset);
|
||||
if (gs_PointIsInRect(Mouse.Pos, ViewAdjustedBounds))
|
||||
{
|
||||
visual_port UpstreamPort = (OpState->IsInput & IsInputMember) ? VisualPort : OpState->VisualPort;
|
||||
visual_port DownstreamPort = (OpState->IsInput & IsInputMember) ? OpState->VisualPort : VisualPort;
|
||||
|
||||
PushNodeConnectionOnWorkspace(UpstreamPort.SparseNodeHandle, UpstreamPort.PortIndex,
|
||||
DownstreamPort.SparseNodeHandle, DownstreamPort.PortIndex,
|
||||
&State->NodeWorkspace, &State->Transient);
|
||||
|
||||
GraphState->LayoutIsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
EndCurrentOperationMode(State, Event, Mouse);
|
||||
}
|
||||
|
||||
input_command ConnectNodesOperationCommands[] = {
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndConnectNodesOperation },
|
||||
};
|
||||
|
||||
internal void
|
||||
BeginConnectNodesOperation(visual_port VisualPort, u32 VisualPortIndex, mouse_state Mouse, app_state* State)
|
||||
{
|
||||
operation_mode* ConnectNodesOperation = ActivateOperationModeWithCommands(&State->Modes, ConnectNodesOperationCommands, UpdateConnectNodeOperation);
|
||||
connect_nodes_operation_state* OpState = CreateOperationState(ConnectNodesOperation, &State->Modes, connect_nodes_operation_state);
|
||||
OpState->VisualPort = VisualPort;
|
||||
OpState->VisualPortIndex = VisualPortIndex;
|
||||
|
||||
panel_with_layout NodeGraphPanel = GetPanelContainingPoint(Mouse.DownPos, &State->PanelSystem, State->WindowBounds);
|
||||
node_graph_state* GraphState = (node_graph_state*)NodeGraphPanel.Panel->PanelStateMemory;
|
||||
|
||||
GraphState->Layout.ConnectionIsInProgress = true;
|
||||
GraphState->Layout.InProgressConnectionStart = gs_CalculateRectCenter(VisualPort.PortBounds);
|
||||
}
|
||||
|
||||
//
|
||||
// Node Graph Panel
|
||||
//
|
||||
|
||||
GSMetaTag(panel_commands);
|
||||
input_command NodeGraph_Commands[] = {{}};
|
||||
s32 NodeGraph_CommandsCount = 0;
|
||||
|
||||
GSMetaTag(panel_init);
|
||||
GSMetaTag(panel_type_node_graph);
|
||||
internal void
|
||||
NodeGraph_Init(panel* Panel, app_state* State)
|
||||
{
|
||||
// TODO(Peter): We aren't able to free this memory. We need a system for
|
||||
// taking fixed size chunks off the Memory stack and then reusing them. THis
|
||||
// should probably live outside the paneling system.
|
||||
// TODO: :FreePanelMemory
|
||||
Panel->PanelStateMemory = (u8*)PushStruct(&State->Permanent, node_graph_state);
|
||||
node_graph_state* GraphState = (node_graph_state*)Panel->PanelStateMemory;
|
||||
GraphState->LayoutIsDirty = true;
|
||||
}
|
||||
|
||||
GSMetaTag(panel_cleanup);
|
||||
GSMetaTag(panel_type_node_graph);
|
||||
internal void
|
||||
NodeGraph_Cleanup(panel* Panel, app_state* State)
|
||||
{
|
||||
node_graph_state* GraphState = (node_graph_state*)Panel->PanelStateMemory;
|
||||
FreeMemoryArena(&GraphState->LayoutMemory);
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawGrid (v2 Offset, v2 GridSquareDim, rect2 PanelBounds, render_command_buffer* RenderBuffer)
|
||||
{
|
||||
r32 LineValue = .16f;
|
||||
v4 LineColor = v4{LineValue, LineValue, LineValue, 1.f};
|
||||
|
||||
v2 GridSquareOffset = v2{
|
||||
GSModF(Offset.x, GridSquareDim.x),
|
||||
GSModF(Offset.y, GridSquareDim.y),
|
||||
};
|
||||
v2 GridOrigin = PanelBounds.Min + GridSquareOffset;
|
||||
|
||||
// Draw Vertical Lines
|
||||
r32 XOffset = 0;
|
||||
while (GridOrigin.x + XOffset < PanelBounds.Max.x)
|
||||
{
|
||||
v2 LineMin = v2{ GridOrigin.x + XOffset, PanelBounds.Min.y };
|
||||
v2 LineMax = v2{ LineMin.x + 1, PanelBounds.Max.y };
|
||||
PushRenderQuad2D(RenderBuffer, LineMin, LineMax, LineColor);
|
||||
|
||||
XOffset += GridSquareDim.x;
|
||||
}
|
||||
|
||||
// Draw Horizontal Lines
|
||||
r32 YOffset = 0;
|
||||
while (GridOrigin.y + YOffset < PanelBounds.Max.y)
|
||||
{
|
||||
v2 LineMin = v2{ PanelBounds.Min.x, GridOrigin.y + YOffset };
|
||||
v2 LineMax = v2{ PanelBounds.Max.x, LineMin.y + 1, };
|
||||
PushRenderQuad2D(RenderBuffer, LineMin, LineMax, LineColor);
|
||||
|
||||
YOffset += GridSquareDim.y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, r32 LineHeight, gs_string_alignment TextAlign, v2 TextOffset, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse)
|
||||
{
|
||||
rect2 PortBounds = rect2{v2{0, 0}, v2{6, 6}};
|
||||
|
||||
v2 LinePosition = Position;
|
||||
for (u32 i = 0; i < NodeDataTypeInfo.MembersCount; i++)
|
||||
{
|
||||
gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[i];
|
||||
if (MemberIsInput(Member))
|
||||
{
|
||||
// TODO(Peter): Can we make this rely on the same data that we use to
|
||||
// render the actual connection points?
|
||||
gs_string MemberName = MakeString(Member.Identifier, Member.IdentifierLength);
|
||||
DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, TextAlign);
|
||||
LinePosition.y -= LineHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle NodeHandle, r32 NodeWidth, r32 LineHeight, interface_config Interface, render_command_buffer* RenderBuffer, mouse_state Mouse, gs_memory_arena* Scratch)
|
||||
{
|
||||
gsm_struct_type_info NodeDataTypeInfo = StructTypes[NodeSpecification.DataType];
|
||||
|
||||
u32 InputMembers = 0;
|
||||
u32 OutputMembers = 0;
|
||||
for (u32 i = 0; i < NodeDataTypeInfo.MembersCount; i++)
|
||||
{
|
||||
gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[i];
|
||||
if (MemberIsInput(Member)) { InputMembers++; }
|
||||
if (MemberIsOutput(Member)) { OutputMembers++; }
|
||||
}
|
||||
u32 LineCount = 1 + Max(InputMembers, OutputMembers);
|
||||
|
||||
v2 NodeDim = v2{
|
||||
NodeWidth,
|
||||
(LineHeight * LineCount) + Interface.Margin.y,
|
||||
};
|
||||
rect2 NodeBounds = rect2{
|
||||
v2{ Position.x, Position.y - NodeDim.y },
|
||||
v2{ Position.x + NodeDim.x, Position.y },
|
||||
};
|
||||
|
||||
PushRenderQuad2D(RenderBuffer, NodeBounds.Min, NodeBounds.Max, v4{.16f, .16f, .16f, 1.f});
|
||||
|
||||
v2 LinePosition = v2{ NodeBounds.Min.x, NodeBounds.Max.y - LineHeight };
|
||||
v2 TextOffset = v2{Interface.Margin.x, 0};
|
||||
|
||||
PushRenderQuad2D(RenderBuffer, LinePosition, LinePosition + v2{NodeWidth, LineHeight}, v4{1.f, .24f, .39f, 1.f});
|
||||
|
||||
gs_string NodePrintName = MakeString(PushArray(Scratch, char, 256), 0, 256);
|
||||
PrintF(&NodePrintName, "%S [%d]", NodeSpecification.Identifier, NodeHandle.Index);
|
||||
DrawString(RenderBuffer, NodePrintName, Interface.Font, LinePosition + TextOffset, WhiteV4);
|
||||
LinePosition.y -= LineHeight;
|
||||
|
||||
v2 InputLinePosition = LinePosition;
|
||||
v2 OutputLinePosition = v2{LinePosition.x + NodeDim.x, LinePosition.y };
|
||||
v2 OutputTextOffset = v2{-TextOffset.x, TextOffset.y};
|
||||
for (u32 i = 0; i < NodeDataTypeInfo.MembersCount; i++)
|
||||
{
|
||||
gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[i];
|
||||
gs_string MemberName = MakeString(Member.Identifier, Member.IdentifierLength);
|
||||
|
||||
// TODO(Peter): Can we make this rely on the same data that we use to
|
||||
// render the actual connection points?
|
||||
if (MemberIsInput(Member))
|
||||
{
|
||||
DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, Align_Left);
|
||||
InputLinePosition.y -= LineHeight;
|
||||
}
|
||||
else if (MemberIsOutput(Member))
|
||||
{
|
||||
DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, Align_Right);
|
||||
OutputLinePosition.y -= LineHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal s32
|
||||
GetVisualPortIndexForNode(gs_list_handle SparseNodeHandle, u32 PortIndex, node_layout Layout)
|
||||
{
|
||||
s32 Result = -1;
|
||||
|
||||
for (u32 i = 0; i < Layout.VisualPortsCount; i++)
|
||||
{
|
||||
visual_port Port = Layout.VisualPorts[i];
|
||||
if (GSListHandlesAreEqual(Port.SparseNodeHandle, SparseNodeHandle) && Port.PortIndex == PortIndex)
|
||||
{
|
||||
Result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal node_layout
|
||||
ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, r32 LineHeight, gs_memory_arena* Storage, app_state* State)
|
||||
{
|
||||
node_layout Result = {};
|
||||
|
||||
for (u32 n = 0; n < Workspace.Nodes.Used; n++)
|
||||
{
|
||||
gs_list_handle NodeHandle = Workspace.SortedNodeHandles[n];
|
||||
pattern_node Node = *Workspace.Nodes.GetElementWithHandle(NodeHandle);
|
||||
|
||||
u32 SpecIndex = Node.SpecificationIndex;
|
||||
|
||||
node_specification_ Spec = NodeSpecifications[SpecIndex];
|
||||
gsm_struct_type_info NodeDataTypeInfo = StructTypes[Spec.DataType];
|
||||
Result.VisualPortsCount += NodeDataTypeInfo.MembersCount;;
|
||||
}
|
||||
|
||||
// Place nodes and connections
|
||||
Result.VisualNodesCount = Workspace.Nodes.Used;
|
||||
Result.VisualNodes = PushArray(Storage, visual_node, Result.VisualNodesCount);
|
||||
|
||||
u32 VisualPortsUsed = 0;
|
||||
Result.VisualPorts = PushArray(Storage, visual_port, Result.VisualPortsCount);
|
||||
|
||||
for (u32 n = 0; n < Workspace.Nodes.Used; n++)
|
||||
{
|
||||
gs_list_handle NodeHandle = Workspace.SortedNodeHandles[n];
|
||||
pattern_node Node = *Workspace.Nodes.GetElementWithHandle(NodeHandle);
|
||||
|
||||
u32 SpecIndex = Node.SpecificationIndex;
|
||||
|
||||
node_specification_ Spec = NodeSpecifications[SpecIndex];
|
||||
gsm_struct_type_info NodeDataTypeInfo = StructTypes[Spec.DataType];
|
||||
|
||||
visual_node* VisualNode = Result.VisualNodes + n;
|
||||
VisualNode->Spec = Spec;
|
||||
VisualNode->Position = v2{(1.5f * NodeWidth) * n, 0};
|
||||
|
||||
// NOTE(Peter): These start at 2 to account for the offset past the node title
|
||||
s32 InputsCount = 2;
|
||||
s32 OutputsCount = 2;
|
||||
for (u32 p = 0; p < NodeDataTypeInfo.MembersCount; p++)
|
||||
{
|
||||
gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[p];
|
||||
|
||||
rect2 PortBounds = {0};
|
||||
v2 PortDim = v2{8, 8};
|
||||
PortBounds.Min = VisualNode->Position + v2{0, PortDim.y / 2};
|
||||
if (MemberIsInput(Member))
|
||||
{
|
||||
PortBounds.Min.y -= LineHeight * InputsCount++;
|
||||
PortBounds.Min.x -= PortDim.x;
|
||||
}
|
||||
else if (MemberIsOutput(Member))
|
||||
{
|
||||
PortBounds.Min.y -= LineHeight * OutputsCount++;
|
||||
PortBounds.Min.x += NodeWidth;
|
||||
}
|
||||
PortBounds.Max = PortBounds.Min + v2{8, 8};
|
||||
|
||||
visual_port* VisualPort = Result.VisualPorts + VisualPortsUsed++;
|
||||
VisualPort->SparseNodeHandle = NodeHandle;
|
||||
VisualPort->PortIndex = p;
|
||||
VisualPort->PortBounds = PortBounds;
|
||||
}
|
||||
}
|
||||
|
||||
Result.VisualConnectionsCount = 0;
|
||||
|
||||
Result.VisualConnectionsCount = Workspace.Connections.Used;
|
||||
Result.VisualConnections = PushArray(Storage, visual_connection, Result.VisualConnectionsCount);
|
||||
for (u32 c = 0; c < Workspace.Connections.Used; c++)
|
||||
{
|
||||
pattern_node_connection* Connection = Workspace.Connections.GetElementAtIndex(c);
|
||||
|
||||
visual_connection* VisualConnection = Result.VisualConnections + c;
|
||||
VisualConnection->UpstreamVisualPortIndex = GetVisualPortIndexForNode(Connection->UpstreamNodeHandle, Connection->UpstreamPortIndex, Result);
|
||||
VisualConnection->DownstreamVisualPortIndex = GetVisualPortIndexForNode(Connection->DownstreamNodeHandle, Connection->DownstreamPortIndex, Result);
|
||||
|
||||
visual_port UpstreamPort = Result.VisualPorts[VisualConnection->UpstreamVisualPortIndex];
|
||||
visual_port DownstreamPort = Result.VisualPorts[VisualConnection->DownstreamVisualPortIndex];
|
||||
|
||||
VisualConnection->UpstreamPosition = gs_CalculateRectCenter(UpstreamPort.PortBounds);
|
||||
VisualConnection->DownstreamPosition = gs_CalculateRectCenter(DownstreamPort.PortBounds);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
GSMetaTag(panel_render);
|
||||
GSMetaTag(panel_type_node_graph);
|
||||
internal void
|
||||
NodeGraph_Render(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
node_graph_state* GraphState = (node_graph_state*)Panel.PanelStateMemory;
|
||||
b32 MouseHandled = false;
|
||||
|
||||
rect2 NodeSelectionWindowBounds = rect2{
|
||||
PanelBounds.Min,
|
||||
v2{PanelBounds.Min.x + 300, PanelBounds.Max.y},
|
||||
};
|
||||
rect2 GraphBounds = rect2{
|
||||
v2{NodeSelectionWindowBounds.Max.x, PanelBounds.Min.y},
|
||||
PanelBounds.Max,
|
||||
};
|
||||
|
||||
r32 NodeWidth = 150;
|
||||
r32 LayerDistance = 100;
|
||||
r32 LineHeight = ui_GetTextLineHeight(State->Interface);
|
||||
|
||||
if (GraphState->LayoutIsDirty)
|
||||
{
|
||||
// NOTE(Peter): Resset the LayoutMemory arena so we can use it again.
|
||||
// If LayoutIsDirty, then we need to recalculate all the members of GraphState->Layout
|
||||
// so we might as well just clear the whole thing (we aren't freeing, just reusing)
|
||||
ClearArena(&GraphState->LayoutMemory);
|
||||
GraphState->Layout = {};
|
||||
|
||||
GraphState->Layout = ArrangeNodes(State->NodeWorkspace, NodeWidth, LayerDistance, LineHeight, &GraphState->LayoutMemory, State);
|
||||
GraphState->LayoutIsDirty = false;
|
||||
}
|
||||
|
||||
DrawGrid(GraphState->ViewOffset, v2{100, 100}, GraphBounds, RenderBuffer);
|
||||
|
||||
for (u32 i = 0; i < GraphState->Layout.VisualConnectionsCount; i++)
|
||||
{
|
||||
visual_connection Connection = GraphState->Layout.VisualConnections[i];
|
||||
|
||||
v2 Start = GraphState->ViewOffset + Connection.UpstreamPosition;
|
||||
v2 End = GraphState->ViewOffset + Connection.DownstreamPosition;
|
||||
PushRenderLine2D(RenderBuffer, Start, End, 1.5f, WhiteV4);
|
||||
|
||||
v2 TempDim = v2{6, 6};
|
||||
PushRenderQuad2D(RenderBuffer, Start - TempDim, Start + TempDim, PinkV4);
|
||||
PushRenderQuad2D(RenderBuffer, End - TempDim, End + TempDim, YellowV4);
|
||||
}
|
||||
|
||||
if (GraphState->Layout.ConnectionIsInProgress)
|
||||
{
|
||||
PushRenderLine2D(RenderBuffer,
|
||||
GraphState->Layout.InProgressConnectionStart,
|
||||
GraphState->Layout.InProgressConnectionEnd,
|
||||
1.5f, WhiteV4);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < GraphState->Layout.VisualNodesCount; i++)
|
||||
{
|
||||
visual_node VisualNode = GraphState->Layout.VisualNodes[i];
|
||||
gs_list_handle NodeHandle = State->NodeWorkspace.SortedNodeHandles[i];
|
||||
DrawNode(VisualNode.Position + GraphState->ViewOffset, VisualNode.Spec, NodeHandle, NodeWidth, LineHeight, State->Interface.Style, RenderBuffer, Context.Mouse, &State->Transient);
|
||||
}
|
||||
|
||||
for (u32 p = 0; p < GraphState->Layout.VisualPortsCount; p++)
|
||||
{
|
||||
visual_port VisualPort = GraphState->Layout.VisualPorts[p];
|
||||
VisualPort.PortBounds.Min += GraphState->ViewOffset;
|
||||
VisualPort.PortBounds.Max += GraphState->ViewOffset;
|
||||
|
||||
v4 PortColor = WhiteV4;
|
||||
if (PointIsInRange(Context.Mouse.Pos, VisualPort.PortBounds.Min, VisualPort.PortBounds.Max))
|
||||
{
|
||||
PortColor = PinkV4;
|
||||
if (MouseButtonTransitionedDown(Context.Mouse.LeftButtonState))
|
||||
{
|
||||
BeginConnectNodesOperation(VisualPort, p, Context.Mouse, State);
|
||||
MouseHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
PushRenderQuad2D(RenderBuffer, VisualPort.PortBounds.Min, VisualPort.PortBounds.Max, PortColor);
|
||||
}
|
||||
|
||||
// Node Selection Panel
|
||||
v4 LineBGColors[] = {
|
||||
{ .16f, .16f, .16f, 1.f },
|
||||
{ .18f, .18f, .18f, 1.f },
|
||||
};
|
||||
|
||||
interface_list List = {};
|
||||
List.LineBGColors = LineBGColors;
|
||||
List.LineBGColorsCount = sizeof(LineBGColors) / sizeof(LineBGColors[0]);
|
||||
List.LineBGHoverColor = v4{ .22f, .22f, .22f, 1.f };
|
||||
List.TextColor = WhiteV4;
|
||||
List.ListBounds = NodeSelectionWindowBounds;
|
||||
List.ListElementDimensions = v2{
|
||||
Rect2Width(NodeSelectionWindowBounds),
|
||||
ui_GetTextLineHeight(State->Interface)
|
||||
};
|
||||
List.ElementLabelIndent = v2{10, 4};
|
||||
|
||||
gs_string Titlegs_string = MakeStringLiteral("Available Nodes");
|
||||
DrawListElement(Titlegs_string, &List, Context.Mouse, RenderBuffer, State->Interface.Style);
|
||||
|
||||
for (u32 i = 0; i < NodeType_Count; i++)
|
||||
{
|
||||
node_specification_ Spec = NodeSpecifications[i];
|
||||
rect2 ElementBounds = DrawListElement(Spec.Identifier, &List, Context.Mouse, RenderBuffer, State->Interface.Style);
|
||||
|
||||
if (MouseButtonTransitionedDown(Context.Mouse.LeftButtonState)
|
||||
&& gs_PointIsInRect(Context.Mouse.DownPos, ElementBounds))
|
||||
{
|
||||
PushNodeOnWorkspace(i, &State->NodeWorkspace, &State->Transient);
|
||||
GraphState->LayoutIsDirty = true;
|
||||
MouseHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MouseHandled && MouseButtonTransitionedDown(Context.Mouse.LeftButtonState))
|
||||
{
|
||||
BeginPanNodeGraph(State, {}, Context.Mouse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_PANEL_NODE_GRAPH_H
|
||||
#endif // FOLDHAUS_PANEL_NODE_GRAPH_H
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// File: foldhaus_search_lister.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_SEARCH_LISTER_CPP
|
||||
|
||||
internal b32
|
||||
NamePassesFilter (gs_string Target, gs_string Filter)
|
||||
{
|
||||
return (Filter.Length == 0 || StringContainsStringCaseInsensitive(Target, Filter));
|
||||
}
|
||||
|
||||
internal void
|
||||
FilterSearchLister (search_lister* SearchLister)
|
||||
{
|
||||
Assert(SearchLister->FilteredIndexLUT != 0);
|
||||
Assert(SearchLister->FilteredListMax == SearchLister->SourceListCount);
|
||||
|
||||
SearchLister->FilteredListCount = 0;
|
||||
|
||||
for (s32 i = 0; i < SearchLister->SourceListCount; i++)
|
||||
{
|
||||
gs_string* Namegs_string = SearchLister->SourceList + i;
|
||||
if (NamePassesFilter(*Namegs_string, SearchLister->Filter))
|
||||
{
|
||||
SearchLister->FilteredIndexLUT[SearchLister->FilteredListCount++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
SearchLister->HotItem = Clamp(0, SearchLister->HotItem, SearchLister->FilteredListCount - 1);
|
||||
|
||||
if (SearchLister->FilteredListCount == 0)
|
||||
{
|
||||
SearchLister->HotItem = -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal s32
|
||||
GetNextFilteredItem (search_lister SearchLister)
|
||||
{
|
||||
s32 Result = Min(SearchLister.HotItem + 1, SearchLister.FilteredListCount - 1);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
GetPrevFilteredItem (search_lister SearchLister)
|
||||
{
|
||||
s32 Result = Max(SearchLister.HotItem - 1, 0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_SEARCH_LISTER_CPP
|
||||
#endif // FOLDHAUS_SEARCH_LISTER_CPP
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// File: foldhaus_search_lister.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_SEARCH_LISTER_H
|
||||
|
||||
struct search_lister
|
||||
{
|
||||
// TODO(Peter): Giving up trying to just use the source list for now. At the moment
|
||||
// we are copying the gs_strings you want to filter from and storing them here. Come back
|
||||
// once its working and make the memory efficient version (ie store the existing memory
|
||||
// location, the element stride and the offset to the char*)
|
||||
s32 SourceListCount;
|
||||
gs_string* SourceList;
|
||||
|
||||
// NOTE(Peter): stores the source indecies of each filtered item
|
||||
// For example:
|
||||
// Index 0 in this array contains 3. This means the first item that passes the filter
|
||||
// is index 3 in ListMemory
|
||||
s32 FilteredListMax;
|
||||
s32 FilteredListCount;
|
||||
s32* FilteredIndexLUT;
|
||||
s32 HotItem;
|
||||
|
||||
gs_string Filter;
|
||||
};
|
||||
|
||||
|
||||
#define FOLDHAUS_SEARCH_LISTER_H
|
||||
#endif // FOLDHAUS_SEARCH_LISTER_H
|
|
@ -0,0 +1,249 @@
|
|||
//
|
||||
// File: foldhaus_text_entry.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_TEXT_ENTRY_CPP
|
||||
|
||||
internal void
|
||||
ResetTextInput (text_entry* Input)
|
||||
{
|
||||
Input->CursorPosition = 0;
|
||||
Input->Buffer.Length = 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
PipeSearchStringToDestination (text_entry* Input)
|
||||
{
|
||||
switch (Input->Destination.Type)
|
||||
{
|
||||
case TextTranslateTo_gs_string:
|
||||
{
|
||||
PrintF(Input->Destination.StringDest, "%S", Input->Buffer);
|
||||
}break;
|
||||
|
||||
case TextTranslateTo_R32:
|
||||
{
|
||||
*Input->Destination.FloatDest = (r32)ParseFloat(Input->Buffer.ConstString);
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
RemoveCharacterAtCursor (text_entry* TextEntry)
|
||||
{
|
||||
if (TextEntry->CursorPosition > 0)
|
||||
{
|
||||
for (u32 i = TextEntry->CursorPosition - 1; i < TextEntry->Buffer.Length; i++)
|
||||
{
|
||||
Assert(i + 1 < TextEntry->Buffer.Size);
|
||||
TextEntry->Buffer.Str[i] = TextEntry->Buffer.Str[i + 1];
|
||||
}
|
||||
TextEntry->CursorPosition--;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
SetTextInputDestinationToString (text_entry* TextInput, gs_string* DestinationString)
|
||||
{
|
||||
ResetTextInput(TextInput);
|
||||
TextInput->Destination.Type = TextTranslateTo_gs_string;
|
||||
TextInput->Destination.StringDest = DestinationString;
|
||||
PrintF(&TextInput->Buffer, "%S", *DestinationString);
|
||||
}
|
||||
|
||||
internal void
|
||||
SetTextInputDestinationToFloat (text_entry* TextInput, r32* DestinationFloat)
|
||||
{
|
||||
ResetTextInput(TextInput);
|
||||
TextInput->Destination.Type = TextTranslateTo_R32;
|
||||
TextInput->Destination.FloatDest = DestinationFloat;
|
||||
PrintF(&TextInput->Buffer, "%f", *DestinationFloat);
|
||||
|
||||
if (*DestinationFloat == 0.0f)
|
||||
{
|
||||
TextInput->CursorPosition = 1;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
MoveCursorRight (text_entry* TextEntry)
|
||||
{
|
||||
TextEntry->CursorPosition = Min(TextEntry->Buffer.Length, TextEntry->CursorPosition + 1);
|
||||
}
|
||||
|
||||
internal void
|
||||
MoveCursorLeft (text_entry* TextEntry)
|
||||
{
|
||||
TextEntry->CursorPosition = Max(0, TextEntry->CursorPosition - 1);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(TextEntryInsertChar)
|
||||
{
|
||||
|
||||
char Char = CharacterFromKeyCode(Event.Key);
|
||||
if (Event.Key >= KeyCode_A && Event.Key <= KeyCode_Z && (Event.Modifiers & Modifier_Shift) == 0)
|
||||
{
|
||||
Char += ('a' - 'A');
|
||||
}
|
||||
|
||||
// Shift string forward
|
||||
Assert(State->ActiveTextEntry.Buffer.Length < State->ActiveTextEntry.Buffer.Size);
|
||||
for (u32 i = State->ActiveTextEntry.Buffer.Length;
|
||||
i > (u32)State->ActiveTextEntry.CursorPosition;
|
||||
i--)
|
||||
{
|
||||
State->ActiveTextEntry.Buffer.Str[i] = State->ActiveTextEntry.Buffer.Str[i - 1];
|
||||
}
|
||||
// Insert new Character
|
||||
State->ActiveTextEntry.Buffer.Str[State->ActiveTextEntry.CursorPosition] = Char;
|
||||
State->ActiveTextEntry.CursorPosition++;
|
||||
PipeSearchStringToDestination(&State->ActiveTextEntry);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(RemoveCharacterFromEntrygs_string)
|
||||
{
|
||||
RemoveCharacterAtCursor(&State->ActiveTextEntry);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(TextEntryMoveCursorRight)
|
||||
{
|
||||
MoveCursorRight(&State->ActiveTextEntry);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(TextEntryMoveCursorLeft)
|
||||
{
|
||||
MoveCursorLeft(&State->ActiveTextEntry);
|
||||
}
|
||||
|
||||
internal void
|
||||
InitializeTextInputCommands (input_command_registry* Commands, gs_memory_arena* PermanentStorage)
|
||||
{
|
||||
if (Commands->Size > 0)
|
||||
{
|
||||
RegisterKeyPressCommand(Commands, KeyCode_Backspace, Command_Began | Command_Held, KeyCode_Invalid, RemoveCharacterFromEntrygs_string);
|
||||
RegisterKeyPressCommand(Commands, KeyCode_LeftArrow, Command_Began | Command_Held, KeyCode_Invalid, TextEntryMoveCursorLeft);
|
||||
RegisterKeyPressCommand(Commands, KeyCode_RightArrow, Command_Began | Command_Held, KeyCode_Invalid, TextEntryMoveCursorRight);
|
||||
|
||||
for (s32 i = KeyCode_a; i < KeyCode_UpArrow; i++)
|
||||
{
|
||||
RegisterKeyPressCommand(Commands, (key_code)i, Command_Began | Command_Held, KeyCode_Invalid, TextEntryInsertChar);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY \
|
||||
{ KeyCode_Backspace, KeyCode_Invalid, Command_Began | Command_Held, RemoveCharacterFromEntrygs_string }, \
|
||||
{ KeyCode_LeftArrow, KeyCode_Invalid, Command_Began | Command_Held, TextEntryMoveCursorLeft }, \
|
||||
{ KeyCode_RightArrow, KeyCode_Invalid, Command_Began | Command_Held, TextEntryMoveCursorRight }, \
|
||||
{ KeyCode_a, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_b, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_c, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_d, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_e, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_f, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_g, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_h, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_i, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_j, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_k, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_l, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_m, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_n, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_o, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_p, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_q, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_r, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_s, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_t, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_u, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_v, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_w, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_x, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_y, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_z, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_A, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_B, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_C, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_D, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_E, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_F, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_G, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_H, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_I, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_J, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_K, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_L, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_M, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_N, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_O, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_P, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Q, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_R, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_S, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_T, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_U, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_V, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_W, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_X, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Y, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Z, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_0, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_1, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_2, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_3, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_4, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_5, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_6, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_7, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_8, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_9, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num0, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num1, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num2, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num3, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num4, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num5, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num6, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num7, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num8, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Num9, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Bang, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_At, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Pound, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Dollar, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Percent, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Carrot, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Ampersand, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Star, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_LeftParen, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_RightParen, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Minus, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Plus, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Equals, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Underscore, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_LeftBrace, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_RightBrace, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_LeftBracket, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_RightBracket, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Colon, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_SemiColon, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_SingleQuote, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_DoubleQuote, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_ForwardSlash, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Backslash, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Pipe, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Comma, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Period, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_QuestionMark, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_LessThan, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_GreaterThan, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_Tilde, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }, \
|
||||
{ KeyCode_BackQuote, KeyCode_Invalid, Command_Began | Command_Held, TextEntryInsertChar }
|
||||
|
||||
|
||||
#define FOLDHAUS_TEXT_ENTRY_CPP
|
||||
#endif // FOLDHAUS_TEXT_ENTRY_CPP
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// File: foldhaus_text_entry.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_TEXT_ENTRY_H
|
||||
|
||||
enum text_translation_type
|
||||
{
|
||||
TextTranslateTo_gs_string,
|
||||
TextTranslateTo_R32,
|
||||
TextTranslateTo_S32,
|
||||
TextTranslateTo_U32,
|
||||
};
|
||||
|
||||
struct text_entry_destination
|
||||
{
|
||||
text_translation_type Type;
|
||||
union {
|
||||
gs_string* StringDest;
|
||||
r32* FloatDest;
|
||||
s32* SignedIntDest;
|
||||
u32* UnsignedIntDest;
|
||||
};
|
||||
};
|
||||
|
||||
struct text_entry
|
||||
{
|
||||
gs_string Buffer;
|
||||
s32 CursorPosition;
|
||||
|
||||
text_entry_destination Destination;
|
||||
};
|
||||
|
||||
#define FOLDHAUS_TEXT_ENTRY_H
|
||||
#endif // FOLDHAUS_TEXT_ENTRY_H
|
|
@ -0,0 +1,377 @@
|
|||
//
|
||||
// File: foldhaus_util_radialumia_file_converter.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_UTIL_RADIALUMIA_FILE_CONVERTER_CPP
|
||||
|
||||
#define DEBUG
|
||||
#define DEBUG_TRACK_SCOPE(name)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <gs_string.h>
|
||||
|
||||
#include "gs/gs_language.h"
|
||||
#include "gs/gs_string.h"
|
||||
#include "../meta/gs_meta_lexer.h"
|
||||
#include "gs/gs_vector.h"
|
||||
|
||||
#define gs_string_BUFFER_SIZE 512
|
||||
struct gs_string_buffer
|
||||
{
|
||||
char* Memory;
|
||||
s32 Size;
|
||||
gs_string_buffer* Next;
|
||||
};
|
||||
|
||||
struct gs_string_writer
|
||||
{
|
||||
char* Cursor;
|
||||
s32 UsedIngs_string;
|
||||
gs_string_buffer* Buffer;
|
||||
};
|
||||
|
||||
internal gs_string_buffer*
|
||||
Growgs_stringBuffer (gs_string_buffer* Buffer)
|
||||
{
|
||||
gs_string_buffer* Result;
|
||||
if (Buffer->Next)
|
||||
{
|
||||
Result = Growgs_stringBuffer(Buffer->Next);
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = (gs_string_buffer*)malloc(sizeof(gs_string_buffer));
|
||||
Result->Memory = (char*)malloc(sizeof(char) * gs_string_BUFFER_SIZE);
|
||||
memset(Result->Memory, 0, gs_string_BUFFER_SIZE);
|
||||
Result->Size = gs_string_BUFFER_SIZE;
|
||||
Result->Next = 0;
|
||||
|
||||
Buffer->Next = Result;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
Writegs_string(gs_string_writer* Writer, char* gs_string, s32 Length)
|
||||
{
|
||||
char* Src = gs_string;
|
||||
char* Dst = Writer->Cursor;
|
||||
s32 LengthWritten = 0;
|
||||
|
||||
while (*Src && Writer->UsedIngs_string < Writer->Buffer->Size &&LengthWritten < Length)
|
||||
{
|
||||
LengthWritten++;
|
||||
*Dst++ = *Src++;
|
||||
Writer->UsedIngs_string++;
|
||||
}
|
||||
|
||||
Writer->Cursor = Dst;
|
||||
|
||||
if (*Src && Writer->UsedIngs_string == Writer->Buffer->Size)
|
||||
{
|
||||
*(Dst - 1) = 0; // Null terminate the buffer
|
||||
Writer->Buffer = Growgs_stringBuffer(Writer->Buffer);
|
||||
Writer->Cursor = Writer->Buffer->Memory;
|
||||
Writer->UsedIngs_string = 0;
|
||||
Writegs_string(Writer, (Src - 1), (Length - LengthWritten) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
struct control_box_pairs
|
||||
{
|
||||
s32 Start;
|
||||
s32 End;
|
||||
};
|
||||
|
||||
struct extra_strips
|
||||
{
|
||||
s32 BoxID;
|
||||
v3 Start;
|
||||
v3 End;
|
||||
};
|
||||
|
||||
struct control_box
|
||||
{
|
||||
s32 ID;
|
||||
s32 Neighbors[6];
|
||||
r32 X;
|
||||
r32 Y;
|
||||
r32 Z;
|
||||
char* Address;
|
||||
};
|
||||
|
||||
int main(int ArgCount, char* Args[])
|
||||
{
|
||||
FILE* OldFilePtr = fopen("F:/data/radia_old.fold", "r");
|
||||
if (!OldFilePtr)
|
||||
{
|
||||
InvalidCodePath;
|
||||
}
|
||||
|
||||
fseek(OldFilePtr, 0, SEEK_END);
|
||||
s32 OldFileSize = ftell(OldFilePtr);
|
||||
fseek(OldFilePtr, 0, SEEK_SET);
|
||||
|
||||
char* OldFile = (char*)malloc(sizeof(char) * OldFileSize);
|
||||
fread(OldFile, 1, OldFileSize, OldFilePtr);
|
||||
|
||||
fclose(OldFilePtr);
|
||||
|
||||
s32 ControlBoxPairsUsed = 0;
|
||||
control_box_pairs* ControlBoxPairs = (control_box_pairs*)malloc(sizeof(control_box_pairs) * 512);
|
||||
s32 ControlBoxesUsed = 0;
|
||||
control_box* ControlBoxes = (control_box*)malloc(sizeof(control_box) * 64);
|
||||
s32 ExtraStripsUsed = 0;
|
||||
extra_strips* ExtraStrips = (extra_strips*)malloc(sizeof(extra_strips) * (42 * 4));
|
||||
|
||||
control_box_pairs* NextControlBoxPair = &ControlBoxPairs[0];
|
||||
control_box* NextControlBox = &ControlBoxes[0];
|
||||
extra_strips* NextStrip = &ExtraStrips[0];
|
||||
|
||||
tokenizer Tokenizer = {};
|
||||
Tokenizer.At = OldFile;
|
||||
while(*Tokenizer.At)
|
||||
{
|
||||
// Parse a Control Box
|
||||
memset(NextControlBox->Neighbors, -1, 6);
|
||||
s32 NeighborsAdded = 0;
|
||||
|
||||
control_box_pairs* StartPair = NextControlBoxPair;
|
||||
s32 PairsCount = 0;
|
||||
|
||||
if (gs_stringsEqual(Tokenizer.At, "EOF"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
EatToCharacterInclusive(&Tokenizer, '{');
|
||||
EatWhitespace(&Tokenizer);
|
||||
Assert(gs_stringsEqual(Tokenizer.At, "neighbors: ["));
|
||||
Tokenizer.At += gs_stringLength("neighbors: [");
|
||||
|
||||
// Parse Neighbors
|
||||
while(*Tokenizer.At && *Tokenizer.At != ']')
|
||||
{
|
||||
s32 NeighborIndex = ParseSignedInt(Tokenizer.At);
|
||||
NextControlBox->Neighbors[NeighborsAdded++] = NeighborIndex;
|
||||
NextControlBoxPair->End = NeighborIndex;
|
||||
NextControlBoxPair++;
|
||||
PairsCount++;
|
||||
ControlBoxPairsUsed++;
|
||||
|
||||
EatNumber(&Tokenizer);
|
||||
if (*Tokenizer.At == ']')
|
||||
{
|
||||
Tokenizer.At += 2; // Eat past "];"
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
EatToCharacterInclusive(&Tokenizer, ',');
|
||||
EatWhitespace(&Tokenizer);
|
||||
}
|
||||
}
|
||||
|
||||
EatWhitespace(&Tokenizer);
|
||||
|
||||
//Parse IP
|
||||
Assert(gs_stringsEqual(Tokenizer.At, "ip: "));
|
||||
Tokenizer.At += gs_stringLength("ip: ");
|
||||
NextControlBox->Address = (char*)malloc(sizeof(char) * 13);
|
||||
memcpy(NextControlBox->Address, Tokenizer.At, 13);
|
||||
Tokenizer.At += 13;
|
||||
Tokenizer.At++; // Eat past ";"
|
||||
|
||||
// Parse X
|
||||
EatWhitespace(&Tokenizer);
|
||||
Assert(gs_stringsEqual(Tokenizer.At, "x: "));
|
||||
Tokenizer.At += gs_stringLength("x: ");
|
||||
NextControlBox->X = ParseFloat(Tokenizer.At);
|
||||
EatToCharacterInclusive(&Tokenizer, ';');
|
||||
// Parse Y
|
||||
EatWhitespace(&Tokenizer);
|
||||
Assert(gs_stringsEqual(Tokenizer.At, "y: "));
|
||||
Tokenizer.At += gs_stringLength("y: ");
|
||||
NextControlBox->Y = ParseFloat(Tokenizer.At);
|
||||
EatToCharacterInclusive(&Tokenizer, ';');
|
||||
// Parse Z
|
||||
EatWhitespace(&Tokenizer);
|
||||
Assert(gs_stringsEqual(Tokenizer.At, "z: "));
|
||||
Tokenizer.At += gs_stringLength("z: ");
|
||||
NextControlBox->Z = ParseFloat(Tokenizer.At);
|
||||
EatToCharacterInclusive(&Tokenizer, ';');
|
||||
|
||||
// Parse ID
|
||||
EatWhitespace(&Tokenizer);
|
||||
Assert(gs_stringsEqual(Tokenizer.At, "id: "));
|
||||
Tokenizer.At += gs_stringLength("id: ");
|
||||
NextControlBox->ID = ParseSignedInt(Tokenizer.At);
|
||||
EatToCharacterInclusive(&Tokenizer, ';');
|
||||
|
||||
control_box_pairs* PairCursor = StartPair;
|
||||
for(s32 i = 0; i < PairsCount; i++)
|
||||
{
|
||||
PairCursor->Start = NextControlBox->ID;
|
||||
PairCursor++;
|
||||
}
|
||||
|
||||
NextControlBox++;
|
||||
ControlBoxesUsed++;
|
||||
|
||||
EatToCharacterInclusive(&Tokenizer, ';');
|
||||
EatWhitespace(&Tokenizer);
|
||||
}
|
||||
|
||||
// Add Spikes
|
||||
|
||||
|
||||
#define SPIKE_LEDS 346
|
||||
for (s32 sp = 0; sp < ControlBoxesUsed; sp++)
|
||||
{
|
||||
control_box* Box = &ControlBoxes[sp];
|
||||
|
||||
control_box* NeighborA = &ControlBoxes[Box->Neighbors[0]];
|
||||
control_box* NeighborB = &ControlBoxes[Box->Neighbors[1]];
|
||||
|
||||
v3 SpikeCenter = v3{Box->X, Box->Y, Box->Z};
|
||||
v3 StripPitch = Normalize(SpikeCenter) * ((2.f/8.f) / SPIKE_LEDS);
|
||||
v3 ToNA = Normalize(v3{NeighborA->X, NeighborA->Y, NeighborA->Z} - SpikeCenter);
|
||||
v3 ToNB = Normalize(v3{NeighborB->X, NeighborB->Y, NeighborB->Z} - SpikeCenter);
|
||||
|
||||
v3 StripAOutStart = SpikeCenter + (ToNA * .01f);
|
||||
v3 StripAOutEnd = StripAOutStart + (StripPitch * SPIKE_LEDS);
|
||||
|
||||
v3 StripBOutStart = SpikeCenter + (ToNB * .01f);
|
||||
v3 StripBOutEnd = StripBOutStart + (StripPitch * SPIKE_LEDS);
|
||||
|
||||
v3 StripAInStart = StripAOutEnd - (ToNA * .02f);
|
||||
v3 StripAInEnd = StripAOutStart - (ToNA * .02f);
|
||||
|
||||
v3 StripBInStart = StripBOutEnd - (ToNA * .02f);
|
||||
v3 StripBInEnd = StripBOutStart - (ToNA * .02f);
|
||||
|
||||
NextStrip->BoxID = Box->ID;
|
||||
NextStrip->Start = StripAOutStart;
|
||||
NextStrip->End = StripAOutEnd;
|
||||
NextStrip++;
|
||||
ExtraStripsUsed++;
|
||||
|
||||
NextStrip->BoxID = Box->ID;
|
||||
NextStrip->Start = StripAInStart;
|
||||
NextStrip->End = StripAInEnd;
|
||||
NextStrip++;
|
||||
ExtraStripsUsed++;
|
||||
|
||||
NextStrip->BoxID = Box->ID;
|
||||
NextStrip->Start = StripBOutStart;
|
||||
NextStrip->End = StripBOutEnd;
|
||||
NextStrip++;
|
||||
ExtraStripsUsed++;
|
||||
|
||||
NextStrip->BoxID = Box->ID;
|
||||
NextStrip->Start = StripBInStart;
|
||||
NextStrip->End = StripBInEnd;
|
||||
NextStrip++;
|
||||
ExtraStripsUsed++;
|
||||
}
|
||||
|
||||
|
||||
gs_string_buffer OutputFileBuffer = {};
|
||||
OutputFileBuffer.Memory = (char*)malloc(sizeof(char) * gs_string_BUFFER_SIZE);
|
||||
OutputFileBuffer.Size = gs_string_BUFFER_SIZE;
|
||||
OutputFileBuffer.Next = 0;
|
||||
|
||||
gs_string_writer RefWriter = {};
|
||||
RefWriter.Cursor = OutputFileBuffer.Memory;
|
||||
RefWriter.UsedIngs_string = 0;
|
||||
RefWriter.Buffer = &OutputFileBuffer;
|
||||
gs_string_writer* Writer = &RefWriter;
|
||||
|
||||
char gs_stringBuffer[512];
|
||||
s32 Len = 0;
|
||||
|
||||
Len = sprintf_s(gs_stringBuffer, 512, "control_box_count %d\n", ControlBoxesUsed);
|
||||
Writegs_string(Writer, gs_stringBuffer, Len);
|
||||
Len = sprintf_s(gs_stringBuffer, 512, "led_strip_count %d\n\n", ControlBoxPairsUsed);
|
||||
Writegs_string(Writer, gs_stringBuffer, Len);
|
||||
|
||||
for (s32 c = 0; c < ControlBoxesUsed; c++)
|
||||
{
|
||||
control_box* Box = ControlBoxes + c;
|
||||
Len = sprintf_s(gs_stringBuffer, 512,
|
||||
"control_box { %d, \"%s\", (%f, %f, %f) }\n",
|
||||
Box->ID, Box->Address,
|
||||
Box->X, Box->Y, Box->Z);
|
||||
Writegs_string(Writer, gs_stringBuffer, Len);
|
||||
}
|
||||
|
||||
Writegs_string(Writer, "\n", 1);
|
||||
|
||||
#define UNIVERSES_PER_BOX 25
|
||||
s32 UniversesPerBox[64];
|
||||
for (s32 u = 0; u < 64; u++)
|
||||
{
|
||||
UniversesPerBox[u] = UNIVERSES_PER_BOX * u;
|
||||
}
|
||||
|
||||
char LEDStripFormatgs_string[] = "led_strip { %d, %d, %d, INTERPOLATE_POINTS, (%f, %f, %f), (%f, %f, %f), 144 } \n";
|
||||
for (s32 s = 0; s < ControlBoxPairsUsed; s++)
|
||||
{
|
||||
control_box_pairs* Pair = ControlBoxPairs + s;
|
||||
|
||||
s32 Universe = UniversesPerBox[Pair->Start];
|
||||
UniversesPerBox[Pair->Start]++;
|
||||
|
||||
r32 StartX = ControlBoxes[Pair->Start].X;
|
||||
r32 StartY = ControlBoxes[Pair->Start].Y;
|
||||
r32 StartZ = ControlBoxes[Pair->Start].Z;
|
||||
|
||||
r32 EndX = ControlBoxes[Pair->End].X;
|
||||
r32 EndY = ControlBoxes[Pair->End].Y;
|
||||
r32 EndZ = ControlBoxes[Pair->End].Z;
|
||||
|
||||
Len = sprintf_s(gs_stringBuffer, 512,
|
||||
LEDStripFormatgs_string,
|
||||
Pair->Start, Universe, 0,
|
||||
StartX, StartY, StartZ,
|
||||
EndX, EndY, EndZ);
|
||||
Writegs_string(Writer, gs_stringBuffer, Len);
|
||||
}
|
||||
|
||||
Writegs_string(Writer, "\n", 1);
|
||||
|
||||
for (s32 sp = 0; sp < ExtraStripsUsed; sp++)
|
||||
{
|
||||
extra_strips* Strip = ExtraStrips + sp;
|
||||
|
||||
s32 Universe = UniversesPerBox[Strip->BoxID];
|
||||
UniversesPerBox[Strip->BoxID]++;
|
||||
|
||||
Len = sprintf_s(gs_stringBuffer, 512,
|
||||
LEDStripFormatgs_string,
|
||||
Strip->BoxID, Universe, 0,
|
||||
Strip->Start.x, Strip->Start.y, Strip->Start.z,
|
||||
Strip->End.x, Strip->End.y, Strip->End.z);
|
||||
Writegs_string(Writer, gs_stringBuffer, Len);
|
||||
}
|
||||
|
||||
Writegs_string(Writer, "END_OF_ASSEMBLY_FILE", gs_stringLength("END_OF_ASSEMBLY_FILE"));
|
||||
|
||||
*Writer->Cursor = 0;
|
||||
|
||||
FILE* OutputFile = fopen("F:/data/radialumia.fold", "w");
|
||||
gs_string_buffer* BufferCursor = &OutputFileBuffer;
|
||||
while(BufferCursor)
|
||||
{
|
||||
fprintf(OutputFile, BufferCursor->Memory);
|
||||
BufferCursor = BufferCursor->Next;
|
||||
}
|
||||
fclose(OutputFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FOLDHAUS_UTIL_RADIALUMIA_FILE_CONVERTER_CPP
|
||||
#endif // FOLDHAUS_UTIL_RADIALUMIA_FILE_CONVERTER_CPP
|
|
@ -0,0 +1,513 @@
|
|||
//
|
||||
// File: foldhaus_node_interface.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLHAUS_NODE_INTERFACE_CPP
|
||||
|
||||
////////////////////////////////////////
|
||||
//
|
||||
// Node Lister
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
struct node_lister_operation_state
|
||||
{
|
||||
search_lister SearchLister;
|
||||
v2 ListPosition;
|
||||
};
|
||||
|
||||
internal void
|
||||
RenderNodeLister(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse)
|
||||
{
|
||||
node_lister_operation_state* OpState = (node_lister_operation_state*)Operation.OpStateMemory;
|
||||
|
||||
v2 TopLeft = OpState->ListPosition;
|
||||
v2 Dimension = v2{300, 30};
|
||||
|
||||
// Filter the lister
|
||||
OpState->SearchLister.Filter = State->ActiveTextEntry.Buffer;
|
||||
FilterSearchLister(&OpState->SearchLister);
|
||||
|
||||
// Display Search Lister
|
||||
search_lister_result NodeListerResult = EvaluateSearchLister (&State->Interface_, TopLeft, Dimension,
|
||||
MakeStringLiteral("Nodes List"),
|
||||
OpState->SearchLister.SourceList,
|
||||
OpState->SearchLister.FilteredIndexLUT,
|
||||
OpState->SearchLister.FilteredListCount,
|
||||
OpState->SearchLister.HotItem,
|
||||
&State->ActiveTextEntry.Buffer,
|
||||
State->ActiveTextEntry.CursorPosition);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(NodeListerNextItem)
|
||||
{
|
||||
node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state);
|
||||
OpState->SearchLister.HotItem = GetNextFilteredItem(OpState->SearchLister);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(NodeListerPrevItem)
|
||||
{
|
||||
node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state);
|
||||
OpState->SearchLister.HotItem = GetPrevFilteredItem(OpState->SearchLister);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(CloseNodeLister)
|
||||
{
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(SelectAndCloseNodeLister)
|
||||
{
|
||||
node_lister_operation_state* OpState = GetCurrentOperationState(State->Modes, node_lister_operation_state);
|
||||
s32 FilteredNodeIndex = OpState->SearchLister.HotItem;
|
||||
if (FilteredNodeIndex >= 0)
|
||||
{
|
||||
s32 NodeIndex = OpState->SearchLister.FilteredIndexLUT[FilteredNodeIndex];
|
||||
PushNodeOnListFromSpecification(State->NodeList, (node_type)NodeIndex,
|
||||
Mouse.Pos, State->Permanent);
|
||||
}
|
||||
CloseNodeLister(State, Event, Mouse);
|
||||
}
|
||||
|
||||
input_command UniverseViewCommads [] = {
|
||||
{ KeyCode_DownArrow, KeyCode_Invalid, Command_Began, NodeListerNextItem },
|
||||
{ KeyCode_UpArrow, KeyCode_Invalid, Command_Began, NodeListerPrevItem },
|
||||
{ KeyCode_Enter, KeyCode_Invalid, Command_Began, SelectAndCloseNodeLister },
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, CloseNodeLister },
|
||||
{ KeyCode_Esc, KeyCode_Invalid, Command_Began, CloseNodeLister },
|
||||
DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY,
|
||||
};
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeLister)
|
||||
{
|
||||
operation_mode* AddNodeOperation = ActivateOperationModeWithCommands(&State->Modes, UniverseViewCommads);
|
||||
|
||||
AddNodeOperation->Render = RenderNodeLister;
|
||||
|
||||
node_lister_operation_state* OpState = CreateOperationState(AddNodeOperation,
|
||||
&State->Modes,
|
||||
node_lister_operation_state);
|
||||
{
|
||||
OpState->SearchLister.SourceListCount = NodeSpecificationsCount;
|
||||
OpState->SearchLister.SourceList = PushArray(&State->Modes.Arena, gs_string, OpState->SearchLister.SourceListCount);
|
||||
{
|
||||
for (s32 i = 0; i < OpState->SearchLister.SourceListCount; i++)
|
||||
{
|
||||
OpState->SearchLister.SourceList[i] = MakeString(
|
||||
NodeSpecifications[i].Name,
|
||||
NodeSpecifications[i].NameLength);
|
||||
}
|
||||
}
|
||||
OpState->SearchLister.Filter = MakeString(PushArray(&State->Modes.Arena, char, 64), 0, 64);
|
||||
|
||||
OpState->SearchLister.FilteredListMax = OpState->SearchLister.SourceListCount;
|
||||
OpState->SearchLister.FilteredListCount = 0;
|
||||
OpState->SearchLister.FilteredIndexLUT = PushArray(&State->Modes.Arena, s32, OpState->SearchLister.SourceListCount);
|
||||
}
|
||||
|
||||
OpState->ListPosition = Mouse.Pos;
|
||||
SetTextInputDestinationTogs_string(&State->ActiveTextEntry, &OpState->SearchLister.Filter);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
//
|
||||
// Node Color Picker
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
struct color_picker_operation_state
|
||||
{
|
||||
v4* ValueAddr;
|
||||
};
|
||||
|
||||
internal void
|
||||
CloseColorPicker(app_state* State)
|
||||
{
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(CloseColorPickerCommand)
|
||||
{
|
||||
CloseColorPicker(State);
|
||||
}
|
||||
|
||||
internal void
|
||||
RenderColorPicker(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse)
|
||||
{
|
||||
color_picker_operation_state* OpState = (color_picker_operation_state*)Operation.OpStateMemory;
|
||||
|
||||
|
||||
b32 ShouldClose = EvaluateColorPicker(RenderBuffer, OpState->ValueAddr,
|
||||
v2{200, 200}, State->Interface, Mouse);
|
||||
|
||||
if (ShouldClose)
|
||||
{
|
||||
CloseColorPicker(State);
|
||||
}
|
||||
}
|
||||
|
||||
input_command ColorPickerCommands [] = {
|
||||
{ KeyCode_Esc, KeyCode_Invalid, Command_Began, CloseColorPickerCommand },
|
||||
};
|
||||
|
||||
internal void
|
||||
OpenColorPicker(app_state* State, node_connection* Connection)
|
||||
{
|
||||
operation_mode* ColorPickerMode = ActivateOperationModeWithCommands(&State->Modes, ColorPickerCommands);
|
||||
ColorPickerMode->Render = RenderColorPicker;
|
||||
|
||||
color_picker_operation_state* OpState = CreateOperationState(ColorPickerMode,
|
||||
&State->Modes,
|
||||
color_picker_operation_state);
|
||||
OpState->ValueAddr = Connection->V4ValuePtr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
//
|
||||
// Node Field Text Edit
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(EndNodeFieldTextEdit)
|
||||
{
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
input_command NodeFieldTextEditCommands [] = {
|
||||
{ KeyCode_Enter, KeyCode_Invalid, Command_Began, EndNodeFieldTextEdit },
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, EndNodeFieldTextEdit },
|
||||
DEFAULT_TEXT_ENTRY_INPUT_COMMANDS_ARRAY_ENTRY,
|
||||
};
|
||||
|
||||
internal void
|
||||
BeginNodeFieldTextEdit(app_state* State, node_connection* Connection)
|
||||
{
|
||||
operation_mode* NodeFieldTextEditMode = ActivateOperationModeWithCommands(&State->Modes,
|
||||
NodeFieldTextEditCommands);
|
||||
|
||||
SetTextInputDestinationToFloat(&State->ActiveTextEntry, Connection->R32ValuePtr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
//
|
||||
// Node Port Mouse Drag
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
struct drag_node_port_operation_state
|
||||
{
|
||||
node_interaction Interaction;
|
||||
};
|
||||
|
||||
internal void
|
||||
RenderDraggingNodePort(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse)
|
||||
{
|
||||
drag_node_port_operation_state* OpState = (drag_node_port_operation_state*)Operation.OpStateMemory;
|
||||
UpdateDraggingNodePort(Mouse.Pos, OpState->Interaction, State->NodeList,
|
||||
State->NodeRenderSettings, RenderBuffer);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(EndDraggingNodePort)
|
||||
{
|
||||
drag_node_port_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_node_port_operation_state);
|
||||
|
||||
TryConnectNodes(OpState->Interaction, Mouse.Pos, State->NodeList, State->NodeRenderSettings);
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
input_command DragNodePortInputCommands[] = {
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDraggingNodePort },
|
||||
};
|
||||
|
||||
internal void
|
||||
BeginDraggingNodePort(app_state* State, node_interaction Interaction)
|
||||
{
|
||||
operation_mode* DragNodePortMode = ActivateOperationModeWithCommands(
|
||||
&State->Modes,
|
||||
DragNodePortInputCommands);
|
||||
DragNodePortMode->Render = RenderDraggingNodePort;
|
||||
|
||||
drag_node_port_operation_state* OpState = CreateOperationState(DragNodePortMode,
|
||||
&State->Modes,
|
||||
drag_node_port_operation_state);
|
||||
OpState->Interaction = Interaction;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
//
|
||||
// Node Field Mouse Drag
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
internal void
|
||||
RenderDragNodeField(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse)
|
||||
{
|
||||
// TODO(Peter):
|
||||
//UpdateDraggingNodeValue(Mouse.Pos, Mouse.OldPos, OpState->Interaction, State->NodeList, State->NodeRenderSettings, State);
|
||||
}
|
||||
|
||||
internal void
|
||||
BeginInteractWithNodeField(app_state* State, node_interaction Interaction)
|
||||
{
|
||||
// TODO(Peter):
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
//
|
||||
// Node Mouse Drag
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
struct drag_node_operation_state
|
||||
{
|
||||
node_interaction Interaction;
|
||||
};
|
||||
|
||||
internal void
|
||||
RenderDraggingNode(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse)
|
||||
{
|
||||
drag_node_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_node_operation_state);
|
||||
UpdateDraggingNode(Mouse.Pos, OpState->Interaction, State->NodeList,
|
||||
State->NodeRenderSettings);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(EndDraggingNode)
|
||||
{
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
input_command DragNodeInputCommands[] = {
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDraggingNode },
|
||||
};
|
||||
|
||||
internal void
|
||||
BeginDraggingNode(app_state* State, node_interaction Interaction)
|
||||
{
|
||||
operation_mode* DragNodeMode = ActivateOperationModeWithCommands(
|
||||
&State->Modes,
|
||||
DragNodeInputCommands);
|
||||
DragNodeMode->Render = RenderDraggingNode;
|
||||
|
||||
drag_node_operation_state* OpState = CreateOperationState(DragNodeMode,
|
||||
&State->Modes,
|
||||
drag_node_operation_state);
|
||||
OpState->Interaction = Interaction;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
//
|
||||
// Node View
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
struct node_view_operation_state
|
||||
{
|
||||
s32 SelectedNodeHandle;
|
||||
};
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseDragInteraction)
|
||||
{
|
||||
node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state);
|
||||
|
||||
node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.DownPos, State->NodeRenderSettings);
|
||||
if (Node)
|
||||
{
|
||||
node_interaction NewInteraction = GetNodeInteractionType(Node,
|
||||
Mouse.Pos,
|
||||
State->NodeRenderSettings);
|
||||
if (IsDraggingNodePort(NewInteraction))
|
||||
{
|
||||
BeginDraggingNodePort(State, NewInteraction);
|
||||
}
|
||||
else if(IsDraggingNodeValue(NewInteraction))
|
||||
{
|
||||
// TODO(Peter): This probably wants to live in a mouse held action
|
||||
// the first frame we realize we're held over a field, just transition to
|
||||
// drag node field
|
||||
//BeginInteractWithNodeField(State, NewInteraction, State->NodeRenderSettings);
|
||||
}
|
||||
else // IsDraggingNode
|
||||
{
|
||||
OpState->SelectedNodeHandle = Node->Handle;
|
||||
BeginDraggingNode(State, NewInteraction);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OpState->SelectedNodeHandle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(NodeViewBeginMouseSelectInteraction)
|
||||
{
|
||||
node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state);
|
||||
|
||||
node_header* Node = GetNodeUnderPoint(State->NodeList, Mouse.Pos, State->NodeRenderSettings);
|
||||
if (Node)
|
||||
{
|
||||
node_interaction NewInteraction = GetNodeInteractionType(Node,
|
||||
Mouse.Pos,
|
||||
State->NodeRenderSettings);
|
||||
if(IsDraggingNodeValue(NewInteraction))
|
||||
{
|
||||
node_connection* Connection = Node->Connections + NewInteraction.InputValue;
|
||||
struct_member_type InputType = Connection->Type;
|
||||
|
||||
if (InputType == MemberType_r32)
|
||||
{
|
||||
BeginNodeFieldTextEdit(State, Connection);
|
||||
}
|
||||
else if (InputType == MemberType_v4)
|
||||
{
|
||||
OpenColorPicker(State, Connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
RenderNodeView(panel Panel, rect2 PanelBounds, render_command_buffer* RenderBufer, app_state* State, context Context, mouse_state Mouse)
|
||||
{
|
||||
node_view_operation_state* OpState = (node_view_operation_state*)Operation.OpStateMemory;
|
||||
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
MakeStringBuffer(NodeHeaderBuffer, 128);
|
||||
|
||||
node_header* SelectedNode = GetNodeWithHandle(State->NodeList, OpState->SelectedNodeHandle);
|
||||
|
||||
node_list_iterator NodeIter = GetNodeListIterator(*State->NodeList);
|
||||
while (NodeIteratorIsValid(NodeIter))
|
||||
{
|
||||
node_header* Node = NodeIter.At;
|
||||
|
||||
rect2 NodeBounds = CalculateNodeBounds(Node, State->NodeRenderSettings);
|
||||
b32 DrawFields = PointIsInRect(Mouse.Pos, NodeBounds);
|
||||
|
||||
if (Node == SelectedNode)
|
||||
{
|
||||
PushRenderQuad2D(RenderBuffer, NodeBounds.Min - v2{2, 2}, NodeBounds.Max + v2{2, 2}, WhiteV4);
|
||||
}
|
||||
|
||||
PushRenderQuad2D(RenderBuffer, NodeBounds.Min, NodeBounds.Max, v4{.5f, .5f, .5f, 1.f});
|
||||
|
||||
// TODO(Peter): This is just for debug purposes. We can remove and go back to just having
|
||||
// Node->Name in Drawgs_string
|
||||
gs_string NodeName = GetNodeName(*Node);
|
||||
PrintF(&NodeHeaderBuffer, "%.*s: %d", NodeName.Length, NodeName.Memory, Node->Handle);
|
||||
DrawString(RenderBuffer, NodeHeaderBuffer, State->NodeRenderSettings.Font,
|
||||
v2{NodeBounds.Min.x + 5, NodeBounds.Max.y - (State->NodeRenderSettings.Font->PixelHeight + NODE_HEADER_HEIGHT + 5)},
|
||||
WhiteV4);
|
||||
|
||||
for (s32 Connection = 0; Connection < Node->ConnectionsCount; Connection++)
|
||||
{
|
||||
v4 PortColor = State->NodeRenderSettings.PortColors[Node->Connections[Connection].Type];
|
||||
|
||||
// Inputs
|
||||
if (ConnectionIsInput(Node, Connection))
|
||||
{
|
||||
rect2 PortBounds = CalculateNodeInputPortBounds(Node, Connection, State->NodeRenderSettings);
|
||||
DrawPort(RenderBuffer, PortBounds, PortColor);
|
||||
|
||||
//
|
||||
// TODO(Peter): I don't like excluding OutputNode, feels too much like a special case
|
||||
// but I don't want to get in to the meta programming right now.
|
||||
// We should just generate a spec and struct member types for NodeType_OutputNode
|
||||
//
|
||||
// :ExcludingOutputNodeSpecialCase
|
||||
//
|
||||
if (Node->Type != NodeType_OutputNode && DrawFields)
|
||||
{
|
||||
node_specification Spec = NodeSpecifications[Node->Type];
|
||||
node_struct_member Member = Spec.MemberList[Connection];
|
||||
DrawString(RenderBuffer, MakeString(Member.Name),
|
||||
State->NodeRenderSettings.Font,
|
||||
v2{PortBounds.Min.x - 8, PortBounds.Min.y}, WhiteV4, Align_Right);
|
||||
}
|
||||
|
||||
rect2 ValueBounds = CalculateNodeInputValueBounds(Node, Connection, State->NodeRenderSettings);
|
||||
DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font);
|
||||
|
||||
// NOTE(Peter): its way easier to draw the connection on the input port b/c its a 1:1 relationship,
|
||||
// whereas output ports might have many connections, they really only know about the most recent one
|
||||
// Not sure if this is a problem. We mostly do everything backwards here, starting at the
|
||||
// most downstream node and working back up to find dependencies.
|
||||
if (ConnectionHasUpstreamConnection(Node, Connection))
|
||||
{
|
||||
rect2 ConnectedPortBounds = GetBoundsOfPortConnectedToInput(Node, Connection, State->NodeList, State->NodeRenderSettings);
|
||||
v2 InputCenter = CalculateRectCenter(PortBounds);
|
||||
v2 OutputCenter = CalculateRectCenter(ConnectedPortBounds);
|
||||
PushRenderLine2D(RenderBuffer, OutputCenter, InputCenter, 1, WhiteV4);
|
||||
}
|
||||
}
|
||||
|
||||
// Outputs
|
||||
if (ConnectionIsOutput(Node, Connection))
|
||||
{
|
||||
rect2 PortBounds = CalculateNodeOutputPortBounds(Node, Connection, State->NodeRenderSettings);
|
||||
DrawPort(RenderBuffer, PortBounds, PortColor);
|
||||
|
||||
if (DrawFields)
|
||||
{
|
||||
node_specification Spec = NodeSpecifications[Node->Type];
|
||||
node_struct_member Member = Spec.MemberList[Connection];
|
||||
DrawString(RenderBuffer, MakeString(Member.Name),
|
||||
State->NodeRenderSettings.Font,
|
||||
v2{PortBounds.Max.x + 8, PortBounds.Min.y}, WhiteV4);
|
||||
}
|
||||
|
||||
rect2 ValueBounds = CalculateNodeOutputValueBounds(Node, Connection, State->NodeRenderSettings);
|
||||
DrawValueDisplay(RenderBuffer, ValueBounds, Node->Connections[Connection], State->NodeRenderSettings.Font);
|
||||
}
|
||||
|
||||
for (s32 Button = 0; Button < 3; Button++)
|
||||
{
|
||||
rect2 ButtonRect = CalculateNodeDragHandleBounds(NodeBounds, Button, State->NodeRenderSettings);
|
||||
PushRenderQuad2D(RenderBuffer, ButtonRect.Min, ButtonRect.Max, DragButtonColors[Button]);
|
||||
}
|
||||
}
|
||||
|
||||
Next(&NodeIter);
|
||||
}
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(NodeViewDeleteNode)
|
||||
{
|
||||
node_view_operation_state* OpState = GetCurrentOperationState(State->Modes, node_view_operation_state);
|
||||
if (OpState->SelectedNodeHandle > 0)
|
||||
{
|
||||
node_header* SelectedNode = GetNodeWithHandle(State->NodeList, OpState->SelectedNodeHandle);
|
||||
FreeNodeOnList(State->NodeList, SelectedNode);
|
||||
}
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(CloseNodeView)
|
||||
{
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
input_command NodeViewCommands [] = {
|
||||
{ KeyCode_Tab, KeyCode_Invalid, Command_Began, CloseNodeView},
|
||||
{ KeyCode_A, KeyCode_Invalid, Command_Began, OpenNodeLister},
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, NodeViewBeginMouseDragInteraction},
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, NodeViewBeginMouseSelectInteraction},
|
||||
{ KeyCode_X, KeyCode_Invalid, Command_Began, NodeViewDeleteNode},
|
||||
};
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(OpenNodeView)
|
||||
{
|
||||
operation_mode* NodeViewMode = ActivateOperationModeWithCommands(&State->Modes, NodeViewCommands);
|
||||
NodeViewMode->Render = RenderNodeView;
|
||||
|
||||
node_view_operation_state* OpState = CreateOperationState(NodeViewMode,
|
||||
&State->Modes,
|
||||
node_view_operation_state);
|
||||
|
||||
OpState->SelectedNodeHandle = 0;
|
||||
}
|
||||
|
||||
|
||||
#define FOLHAUS_NODE_INTERFACE_CPP
|
||||
#endif // FOLHAUS_NODE_INTERFACE_CPP
|
|
@ -0,0 +1,206 @@
|
|||
//
|
||||
// File: foldhaus_command_dispatch.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_COMMAND_DISPATCH_H
|
||||
|
||||
#define FOLDHAUS_INPUT_COMMAND_PROC(name) void name(app_state* State, input_entry Event, mouse_state Mouse, context Context, panel* Panel)
|
||||
typedef FOLDHAUS_INPUT_COMMAND_PROC(input_command_proc);
|
||||
|
||||
// NOTE(Peter): Helper function so I don't have to remember the parameters to this define
|
||||
#define ExecFoldhausCommand(cmd) cmd(State, Event, Mouse)
|
||||
|
||||
enum input_command_flags
|
||||
{
|
||||
Command_Began = 1 << 0,
|
||||
Command_Held = 1 << 1,
|
||||
Command_Ended = 1 << 2,
|
||||
};
|
||||
|
||||
#define Command_Any Command_Began | Command_Held | Command_Ended
|
||||
|
||||
// TODO(Peter): At the moment these are all key press commands. Need a way to differentiate between
|
||||
// press and hold. Probably add a second array to input_command_Registry
|
||||
struct input_command
|
||||
{
|
||||
key_code Key;
|
||||
key_code Mdfr;
|
||||
b32 Flags;
|
||||
input_command_proc* Proc;
|
||||
};
|
||||
|
||||
struct input_command_registry
|
||||
{
|
||||
input_command* Commands;
|
||||
s32 Size;
|
||||
s32 Used;
|
||||
|
||||
input_command_proc* MouseWheelCommand;
|
||||
};
|
||||
|
||||
struct command_queue_entry
|
||||
{
|
||||
input_command Command;
|
||||
input_entry Event;
|
||||
};
|
||||
|
||||
struct input_command_queue
|
||||
{
|
||||
s32 Size;
|
||||
s32 Used;
|
||||
command_queue_entry* Commands;
|
||||
};
|
||||
|
||||
internal void
|
||||
InitializeInputCommandRegistry (input_command_registry* CommandRegistry,
|
||||
s32 Size,
|
||||
gs_memory_arena* Storage)
|
||||
{
|
||||
CommandRegistry->Commands = PushArray(Storage, input_command, Size);
|
||||
CommandRegistry->Size = Size;
|
||||
CommandRegistry->Used = 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
RegisterMouseWheelCommand (input_command_registry* CommandRegistry,
|
||||
input_command_proc* Proc)
|
||||
{
|
||||
CommandRegistry->MouseWheelCommand = Proc;
|
||||
}
|
||||
|
||||
internal s32
|
||||
GetCommandIndexInQueue(input_command_queue* Queue, input_command Command, input_entry Event)
|
||||
{
|
||||
s32 Result = -1;
|
||||
for (s32 CommandIndex = 0; CommandIndex < Queue->Used; CommandIndex++)
|
||||
{
|
||||
command_queue_entry* Entry = Queue->Commands + CommandIndex;
|
||||
if(Entry->Event.Key == Event.Key)
|
||||
{
|
||||
Result = CommandIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal input_command_queue
|
||||
CommandQueue_Create(gs_memory_arena* Storage, u64 CommandMaxCount)
|
||||
{
|
||||
input_command_queue Result = {};
|
||||
Result.Size = CommandMaxCount;
|
||||
Result.Used = 0;
|
||||
Result.Commands = PushArray(Storage, command_queue_entry, CommandMaxCount);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
ClearCommandQueue(input_command_queue* Queue)
|
||||
{
|
||||
Queue->Used = 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
PushCommandOnQueue(input_command_queue* Queue, input_command Command, input_entry Event)
|
||||
{
|
||||
Assert(Queue->Used < Queue->Size);
|
||||
command_queue_entry Entry = {};
|
||||
Entry.Command = Command;
|
||||
Entry.Event = Event;
|
||||
Queue->Commands[Queue->Used++] = Entry;
|
||||
}
|
||||
|
||||
internal void
|
||||
RemoveCommandFromQueue(input_command_queue* Queue, s32 Index)
|
||||
{
|
||||
s32 CommandIndex = Index;
|
||||
if (CommandIndex < Queue->Used)
|
||||
{
|
||||
Queue->Used -= 1;
|
||||
|
||||
for (; CommandIndex < Queue->Used; CommandIndex++)
|
||||
{
|
||||
Queue->Commands[CommandIndex] = Queue->Commands[CommandIndex + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
RemoveCommandFromQueue(input_command_queue* Queue, input_command Command, input_entry Event)
|
||||
{
|
||||
s32 CommandIndex = GetCommandIndexInQueue(Queue, Command, Event);
|
||||
|
||||
// NOTE(Peter): If we made it through the queue without finding an event, there wasn't one
|
||||
// to remove. This happens when we've changed command registries as a result of an input command,
|
||||
// and the command exists in the new registry.
|
||||
// For example:
|
||||
// clicking a mouse button triggers a command to switch registries
|
||||
// the new registry tracks mouse drag (persist until release)
|
||||
// when the mouse is released, the event fires, but there is no mouse down event to remove
|
||||
// For this reason, I'm allowing the case where we try and remove a command where non exists
|
||||
// I don't think this is a great solution but Im not super familiar with the codebase right now
|
||||
// so leaving it as is. revisit if it becomes a problem.
|
||||
RemoveCommandFromQueue(Queue, CommandIndex);
|
||||
}
|
||||
|
||||
internal input_command*
|
||||
FindExistingCommand (input_command_registry CommandRegistry, key_code Key, key_code Mdfr, b32 Flags)
|
||||
{
|
||||
input_command* Result = 0;
|
||||
|
||||
for (s32 Cmd = 0; Cmd < CommandRegistry.Used; Cmd++)
|
||||
{
|
||||
input_command* Command = CommandRegistry.Commands + Cmd;
|
||||
if (Command->Key == Key && Command->Mdfr == Mdfr)
|
||||
{
|
||||
b32 FlagsOverlap = Flags & Command->Flags;
|
||||
if (FlagsOverlap)
|
||||
{
|
||||
Result = Command;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
FindAndPushExistingCommand(input_command_registry CommandRegistry, input_entry Event, b32 Flags, input_command_queue* CommandQueue)
|
||||
{
|
||||
b32 CommandFound = false;
|
||||
input_command* Command = FindExistingCommand(CommandRegistry, Event.Key, (key_code)0, Flags);
|
||||
if (Command)
|
||||
{
|
||||
PushCommandOnQueue(CommandQueue, *Command, Event);
|
||||
CommandFound = true;
|
||||
}
|
||||
return CommandFound;
|
||||
}
|
||||
|
||||
internal void
|
||||
RegisterKeyPressCommand (input_command_registry* CommandRegistry,
|
||||
key_code Key,
|
||||
b32 Flags,
|
||||
key_code Mdfr,
|
||||
input_command_proc* Proc)
|
||||
{
|
||||
input_command* Command = FindExistingCommand(*CommandRegistry, Key, Mdfr, Flags);
|
||||
|
||||
if (!Command)
|
||||
{
|
||||
Assert(CommandRegistry->Size > CommandRegistry->Used);
|
||||
Assert(Mdfr == KeyCode_Invalid || Mdfr == KeyCode_LeftShift || Mdfr == KeyCode_RightShift ||
|
||||
Mdfr == KeyCode_LeftCtrl || Mdfr == KeyCode_RightCtrl || Mdfr == KeyCode_Alt);
|
||||
Command = CommandRegistry->Commands + CommandRegistry->Used++;
|
||||
}
|
||||
|
||||
Command->Key = Key;
|
||||
Command->Flags = Flags;
|
||||
Command->Mdfr = Mdfr;
|
||||
Command->Proc = Proc;
|
||||
}
|
||||
|
||||
#define FOLDHAUS_COMMAND_DISPATCH_H
|
||||
#endif // FOLDHAUS_COMMAND_DISPATCH_H
|
|
@ -0,0 +1,156 @@
|
|||
//
|
||||
// File: foldhaus_editor.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-10-24
|
||||
//
|
||||
#ifndef FOLDHAUS_EDITOR_CPP
|
||||
|
||||
internal void
|
||||
Editor_HandleInput (app_state* State, rect2 WindowBounds, input_queue InputQueue, mouse_state Mouse, context Context)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
b32 MouseInputHandled = HandleMousePanelInteraction(&State->PanelSystem, State->WindowBounds, Mouse, State);
|
||||
|
||||
gs_string TextInputString = PushString(State->Transient, 32);
|
||||
|
||||
panel* ActivePanel = PanelSystem_GetPanelContainingPoint(&State->PanelSystem, Mouse.Pos);
|
||||
if (ActivePanel)
|
||||
{
|
||||
panel_definition ActiveDef = State->PanelSystem.PanelDefs[ActivePanel->TypeIndex];
|
||||
|
||||
input_command_registry ActiveCommands = {};
|
||||
if (State->Modes.ActiveModesCount > 0)
|
||||
{
|
||||
ActiveCommands = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1].Commands;
|
||||
}
|
||||
else if (ActiveDef.InputCommands)
|
||||
{
|
||||
ActiveCommands.Commands = ActiveDef.InputCommands;
|
||||
ActiveCommands.Size = sizeof(*ActiveDef.InputCommands) / sizeof(ActiveDef.InputCommands[0]);
|
||||
ActiveCommands.Used = ActiveCommands.Size;
|
||||
}
|
||||
|
||||
// Fill up the command queue
|
||||
for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++)
|
||||
{
|
||||
input_entry Event = InputQueue.Entries[EventIdx];
|
||||
|
||||
bool IsMouseEvent = (Event.Key == KeyCode_MouseLeftButton ||
|
||||
Event.Key == KeyCode_MouseMiddleButton ||
|
||||
Event.Key == KeyCode_MouseRightButton);
|
||||
if (IsMouseEvent && MouseInputHandled)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE(Peter): These are in the order Down, Up, Held because we want to privalege
|
||||
// Down and Up over Held. In other words, we don't want to call a Held command on the
|
||||
// frame when the button was released, even if the command is registered to both events
|
||||
if (KeyTransitionedDown(Event))
|
||||
{
|
||||
if (!FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue))
|
||||
{
|
||||
char KeyASCII = KeyCodeToChar(Event.Key);
|
||||
if (KeyASCII)
|
||||
{
|
||||
OutChar(&TextInputString, KeyASCII);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (KeyTransitionedUp(Event))
|
||||
{
|
||||
FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue);
|
||||
}
|
||||
else if (KeyHeldDown(Event))
|
||||
{
|
||||
if (!FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue))
|
||||
{
|
||||
char KeyASCII = KeyCodeToChar(Event.Key);
|
||||
if (KeyASCII)
|
||||
{
|
||||
OutChar(&TextInputString, KeyASCII);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Execute all commands in CommandQueue
|
||||
for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--)
|
||||
{
|
||||
command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx];
|
||||
if (Entry->Command.Proc)
|
||||
{
|
||||
Entry->Command.Proc(State, Entry->Event, Mouse, Context, ActivePanel);
|
||||
}
|
||||
else
|
||||
{
|
||||
EndCurrentOperationMode(State);
|
||||
}
|
||||
}
|
||||
|
||||
State->Interface.TempInputString = TextInputString.ConstString;
|
||||
|
||||
ClearCommandQueue(&State->CommandQueue);
|
||||
}
|
||||
|
||||
internal void
|
||||
Editor_Update(app_state* State, context* Context, input_queue InputQueue)
|
||||
{
|
||||
Context->Mouse.CursorType = CursorType_Arrow;
|
||||
State->WindowBounds = Context->WindowBounds;
|
||||
State->Interface.Mouse = Context->Mouse;
|
||||
|
||||
State->Interface.HotWidgetFramesSinceUpdate += 1;
|
||||
if (State->Interface.HotWidgetFramesSinceUpdate > 1)
|
||||
{
|
||||
State->Interface.HotWidget = {};
|
||||
}
|
||||
|
||||
Assert(State->Interface.PerFrameMemory &&
|
||||
(u64)State->Interface.PerFrameMemory != 0x5);
|
||||
|
||||
PanelSystem_UpdateLayout(&State->PanelSystem, State->WindowBounds);
|
||||
Editor_HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse, *Context);
|
||||
}
|
||||
|
||||
internal void
|
||||
Editor_Render(app_state* State, context* Context, render_command_buffer* RenderBuffer)
|
||||
{
|
||||
State->Interface.WindowBounds = Context->WindowBounds;
|
||||
PushRenderOrthographic(RenderBuffer, State->WindowBounds);
|
||||
PushRenderClearScreen(RenderBuffer);
|
||||
|
||||
|
||||
ui_InterfaceReset(&State->Interface);
|
||||
State->Interface.RenderBuffer = RenderBuffer;
|
||||
ui_PushLayout(&State->Interface, Context->WindowBounds, LayoutDirection_TopDown, MakeString("Editor Layout"));
|
||||
{
|
||||
DrawAllPanels(State->PanelSystem, RenderBuffer, &Context->Mouse, State, *Context);
|
||||
|
||||
for (s32 m = 0; m < State->Modes.ActiveModesCount; m++)
|
||||
{
|
||||
operation_mode OperationMode = State->Modes.ActiveModes[m];
|
||||
if (OperationMode.Render != 0)
|
||||
{
|
||||
OperationMode.Render(State, RenderBuffer, OperationMode, Context->Mouse, *Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_PopLayout(&State->Interface, MakeString("Editor Layout"));
|
||||
|
||||
|
||||
// Draw the Interface
|
||||
if (State->Interface.DrawOrderRoot != 0)
|
||||
{
|
||||
ui_widget* Widget = State->Interface.DrawOrderRoot;
|
||||
Editor_DrawWidgetList(State, Context, RenderBuffer, Widget, Context->WindowBounds);
|
||||
}
|
||||
|
||||
Context->GeneralWorkQueue->CompleteQueueWork(Context->GeneralWorkQueue, Context->ThreadContext);
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_EDITOR_CPP
|
||||
#endif // FOLDHAUS_EDITOR_CPP
|
|
@ -0,0 +1,170 @@
|
|||
//
|
||||
// File: foldhaus_editor_draw.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2021-01-16
|
||||
//
|
||||
#ifndef FOLDHAUS_EDITOR_DRAW_H
|
||||
|
||||
internal void
|
||||
Editor_DrawWidgetString(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ClippingBox, v4 Color, s32 CursorPosition)
|
||||
{
|
||||
gs_string Temp = PushString(State->Transient, 256);
|
||||
PrintF(&Temp, "%d", Widget.Id.Id);
|
||||
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer,
|
||||
Widget.String.Length + 1,
|
||||
State->Interface.Style.Font->BitmapMemory,
|
||||
State->Interface.Style.Font->BitmapTextureHandle,
|
||||
State->Interface.Style.Font->BitmapWidth,
|
||||
State->Interface.Style.Font->BitmapHeight,
|
||||
State->Interface.Style.Font->BitmapBytesPerPixel,
|
||||
State->Interface.Style.Font->BitmapStride);
|
||||
|
||||
v2 RegisterPosition = Widget.Bounds.Min + State->Interface.Style.Margin;
|
||||
|
||||
switch (Widget.Alignment)
|
||||
{
|
||||
case Align_Left:
|
||||
{
|
||||
RegisterPosition = DrawStringLeftAligned(RenderBuffer,
|
||||
&BatchConstructor, StringExpand(Widget.String), RegisterPosition, State->Interface.Style.Font, ClippingBox, Color, CursorPosition, GreenV4);
|
||||
}break;
|
||||
|
||||
case Align_Right:
|
||||
{
|
||||
RegisterPosition = DrawStringRightAligned(&BatchConstructor, StringExpand(Widget.String), RegisterPosition, State->Interface.Style.Font, ClippingBox, Color);
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
}
|
||||
|
||||
enum widget_fill_dir
|
||||
{
|
||||
WidgetFill_Horizontal = 0,
|
||||
WidgetFill_Vertical = 1,
|
||||
};
|
||||
|
||||
internal rect2
|
||||
Editor_GetWidgetFillBounds(ui_widget Widget)
|
||||
{
|
||||
Assert(ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill) || ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawVerticalFill));
|
||||
|
||||
rect2 Result = {};
|
||||
|
||||
widget_fill_dir Dir = WidgetFill_Horizontal;
|
||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill)) { Dir = WidgetFill_Vertical; }
|
||||
widget_fill_dir OtherDir = (widget_fill_dir)(WidgetFill_Vertical - Dir);
|
||||
|
||||
Result.Min.E[Dir] = Widget.Bounds.Min.E[Dir];
|
||||
Result.Max.E[Dir] = Widget.Bounds.Max.E[Dir];
|
||||
r32 FillToPoint = LerpR32(Widget.FillPercent, Widget.Bounds.Min.E[OtherDir], Widget.Bounds.Max.E[OtherDir]);
|
||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawFillReversed))
|
||||
{
|
||||
Result.Min.E[OtherDir] = FillToPoint;
|
||||
Result.Max.E[OtherDir] = Widget.Bounds.Max.E[OtherDir];
|
||||
}
|
||||
else if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawFillAsHandle))
|
||||
{
|
||||
Result.Min.E[OtherDir] = FillToPoint - 5;
|
||||
Result.Max.E[OtherDir] = FillToPoint + 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.Min.E[OtherDir] = Widget.Bounds.Min.E[OtherDir];
|
||||
Result.Max.E[OtherDir] = FillToPoint;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void Editor_DrawWidgetList(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 ParentClipBounds);
|
||||
|
||||
internal void
|
||||
Editor_DrawWidget(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget Widget, rect2 WidgetParentUnion)
|
||||
{
|
||||
bool IsActiveWidget = ui_WidgetIdsEqual(Widget.Id, State->Interface.ActiveWidget);
|
||||
;
|
||||
if (!Widget.Parent || (Rect2Area(WidgetParentUnion) > 0))
|
||||
{
|
||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawBackground))
|
||||
{
|
||||
v4 Color = State->Interface.Style.ButtonColor_Inactive;
|
||||
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.HotWidget))
|
||||
{
|
||||
Color = State->Interface.Style.ButtonColor_Active;
|
||||
}
|
||||
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.ActiveWidget))
|
||||
{
|
||||
Color = State->Interface.Style.ButtonColor_Selected;
|
||||
}
|
||||
PushRenderQuad2DClipped(RenderBuffer, Widget.Bounds, WidgetParentUnion, Color);
|
||||
}
|
||||
|
||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
|
||||
{
|
||||
v4 Color = State->Interface.Style.TextColor;
|
||||
s32 CursorPosition = -1;
|
||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_Typable) && IsActiveWidget)
|
||||
{
|
||||
CursorPosition = State->Interface.CursorPosition;
|
||||
}
|
||||
|
||||
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, WidgetParentUnion, Color, CursorPosition);
|
||||
}
|
||||
|
||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawHorizontalFill) ||
|
||||
ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawVerticalFill))
|
||||
{
|
||||
v4 Color = State->Interface.Style.ButtonColor_Selected;
|
||||
if (ui_WidgetIdsEqual(Widget.Id, State->Interface.HotWidget) ||
|
||||
ui_WidgetIdsEqual(Widget.Id, State->Interface.ActiveWidget))
|
||||
{
|
||||
Color = WhiteV4;
|
||||
}
|
||||
|
||||
rect2 FillBounds = Editor_GetWidgetFillBounds(Widget);
|
||||
rect2 ClippedFillBounds = Rect2Union(FillBounds, WidgetParentUnion);
|
||||
PushRenderQuad2D(RenderBuffer, ClippedFillBounds, Color);
|
||||
|
||||
if (ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawString) && Widget.String.Length > 0)
|
||||
{
|
||||
v4 TextColor = BlackV4;
|
||||
Editor_DrawWidgetString(State, Context, RenderBuffer, Widget, ClippedFillBounds, TextColor, -1);
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawOutline = ui_WidgetIsFlagSet(Widget, UIWidgetFlag_DrawOutline);
|
||||
DrawOutline |= ui_WidgetIsFlagSet(Widget, UIWidgetFlag_Typable) && IsActiveWidget;
|
||||
|
||||
if (DrawOutline)
|
||||
{
|
||||
// TODO(pjs): replace these with values from the style
|
||||
r32 Thickness = 1.0f;
|
||||
v4 Color = WhiteV4;
|
||||
PushRenderBoundingBox2D(RenderBuffer, WidgetParentUnion.Min, WidgetParentUnion.Max, Thickness, Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal void Editor_DrawWidgetList(app_state* State, context* Context, render_command_buffer* RenderBuffer, ui_widget* Widget, rect2 ParentClipBounds)
|
||||
{
|
||||
ui_widget* WidgetAt = Widget;
|
||||
while (WidgetAt)
|
||||
{
|
||||
rect2 WidgetParentUnion = WidgetAt->Bounds;
|
||||
WidgetParentUnion = Rect2Union(WidgetAt->Bounds, ParentClipBounds);
|
||||
|
||||
Editor_DrawWidget(State, Context, RenderBuffer, *WidgetAt, WidgetParentUnion);
|
||||
|
||||
if (WidgetAt->ChildrenRoot)
|
||||
{
|
||||
Editor_DrawWidgetList(State, Context, RenderBuffer, WidgetAt->ChildrenRoot, WidgetParentUnion);
|
||||
}
|
||||
|
||||
WidgetAt = WidgetAt->Next;
|
||||
}
|
||||
}
|
||||
|
||||
#define FOLDHAUS_EDITOR_DRAW_H
|
||||
#endif // FOLDHAUS_EDITOR_DRAW_H
|
|
@ -0,0 +1,463 @@
|
|||
//
|
||||
// File: foldhaus_interface.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_INTERFACE_CPP
|
||||
|
||||
////////////////////////////////////////
|
||||
//
|
||||
// Panels
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
enum panel_edit_mode
|
||||
{
|
||||
PanelEdit_Invalid,
|
||||
|
||||
PanelEdit_Modify,
|
||||
PanelEdit_Destroy,
|
||||
|
||||
PanelEdit_Count,
|
||||
};
|
||||
|
||||
//
|
||||
// Drag Panel Border Operation Mode
|
||||
|
||||
OPERATION_STATE_DEF(drag_panel_border_operation_state)
|
||||
{
|
||||
panel* Panel;
|
||||
|
||||
// NOTE(Peter): InitialPanelBounds is the bounds of the panel we are modifying,
|
||||
// it stores the value calculated when the operation mode is kicked off.
|
||||
rect2 InitialPanelBounds;
|
||||
panel_split_direction PanelEdgeDirection;
|
||||
panel_edit_mode PanelEditMode;
|
||||
};
|
||||
|
||||
OPERATION_RENDER_PROC(UpdateAndRenderDragPanelBorder)
|
||||
{
|
||||
drag_panel_border_operation_state* OpState = (drag_panel_border_operation_state*)Operation.OpStateMemory;
|
||||
rect2 PanelBounds = OpState->InitialPanelBounds;
|
||||
|
||||
if (OpState->PanelEditMode == PanelEdit_Modify)
|
||||
{
|
||||
v4 EdgePreviewColor = v4{.3f, .3f, .3f, 1.f};
|
||||
|
||||
v2 EdgePreviewMin = {};
|
||||
v2 EdgePreviewMax = {};
|
||||
if (OpState->PanelEdgeDirection == PanelSplit_Horizontal)
|
||||
{
|
||||
EdgePreviewMin = v2{PanelBounds.Min.x, Mouse.Pos.y};
|
||||
EdgePreviewMax = v2{PanelBounds.Max.x, Mouse.Pos.y + 1};
|
||||
}
|
||||
else if (OpState->PanelEdgeDirection == PanelSplit_Vertical)
|
||||
{
|
||||
EdgePreviewMin = v2{Mouse.Pos.x, PanelBounds.Min.y};
|
||||
EdgePreviewMax = v2{Mouse.Pos.x + 1, PanelBounds.Max.y};
|
||||
}
|
||||
|
||||
PushRenderQuad2D(RenderBuffer, EdgePreviewMin, EdgePreviewMax, EdgePreviewColor);
|
||||
}
|
||||
else if (OpState->PanelEditMode == PanelEdit_Destroy)
|
||||
{
|
||||
rect2 PanelToDeleteBounds = {};
|
||||
if (OpState->PanelEdgeDirection == PanelSplit_Horizontal)
|
||||
{
|
||||
r32 SplitY = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y);
|
||||
if (Mouse.Pos.y > SplitY)
|
||||
{
|
||||
PanelToDeleteBounds = GetTopPanelBounds(OpState->Panel, PanelBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanelToDeleteBounds = GetBottomPanelBounds(OpState->Panel, PanelBounds);
|
||||
}
|
||||
}
|
||||
else if (OpState->PanelEdgeDirection == PanelSplit_Vertical)
|
||||
{
|
||||
r32 SplitX = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x);
|
||||
if (Mouse.Pos.x > SplitX)
|
||||
{
|
||||
PanelToDeleteBounds = GetRightPanelBounds(OpState->Panel, PanelBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanelToDeleteBounds = GetLeftPanelBounds(OpState->Panel, PanelBounds);
|
||||
}
|
||||
}
|
||||
v4 OverlayColor = v4{0, 0, 0, .3f};
|
||||
PushRenderQuad2D(RenderBuffer, PanelToDeleteBounds.Min, PanelToDeleteBounds.Max, OverlayColor);
|
||||
}
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation)
|
||||
{
|
||||
drag_panel_border_operation_state* OpState = GetCurrentOperationState(State->Modes, drag_panel_border_operation_state);
|
||||
rect2 PanelBounds = OpState->InitialPanelBounds;
|
||||
|
||||
if (OpState->PanelEditMode == PanelEdit_Modify)
|
||||
{
|
||||
if (OpState->Panel->SplitDirection == PanelSplit_Horizontal)
|
||||
{
|
||||
r32 NewSplitY = Mouse.Pos.y;
|
||||
if (NewSplitY <= PanelBounds.Min.y)
|
||||
{
|
||||
ConsolidatePanelsKeepOne(OpState->Panel, OpState->Panel->Top, &State->PanelSystem);
|
||||
}
|
||||
else if (NewSplitY >= PanelBounds.Max.y)
|
||||
{
|
||||
ConsolidatePanelsKeepOne(OpState->Panel, OpState->Panel->Bottom, &State->PanelSystem);
|
||||
}
|
||||
else
|
||||
{
|
||||
OpState->Panel->SplitPercent = (NewSplitY - PanelBounds.Min.y) / Rect2Height(PanelBounds);
|
||||
Panel_UpdateLayout(OpState->Panel, PanelBounds);
|
||||
}
|
||||
}
|
||||
else if (OpState->Panel->SplitDirection == PanelSplit_Vertical)
|
||||
{
|
||||
r32 NewSplitX = Mouse.Pos.x;
|
||||
if (NewSplitX <= PanelBounds.Min.x)
|
||||
{
|
||||
ConsolidatePanelsKeepOne(OpState->Panel, OpState->Panel->Right, &State->PanelSystem);
|
||||
}
|
||||
else if (NewSplitX >= PanelBounds.Max.x)
|
||||
{
|
||||
ConsolidatePanelsKeepOne(OpState->Panel, OpState->Panel->Left, &State->PanelSystem);
|
||||
}
|
||||
else
|
||||
{
|
||||
OpState->Panel->SplitPercent = (NewSplitX - PanelBounds.Min.x) / Rect2Width(PanelBounds);
|
||||
Panel_UpdateLayout(OpState->Panel, PanelBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // PanelEdit_Destroy
|
||||
{
|
||||
if (OpState->PanelEdgeDirection == PanelSplit_Horizontal)
|
||||
{
|
||||
r32 SplitY = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y);
|
||||
if (Mouse.Pos.y > SplitY)
|
||||
{
|
||||
ConsolidatePanelsKeepOne(OpState->Panel, OpState->Panel->Bottom, &State->PanelSystem);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsolidatePanelsKeepOne(OpState->Panel, OpState->Panel->Top, &State->PanelSystem);
|
||||
}
|
||||
}
|
||||
else if (OpState->PanelEdgeDirection == PanelSplit_Vertical)
|
||||
{
|
||||
r32 SplitX = LerpR32(OpState->Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x);
|
||||
if (Mouse.Pos.x > SplitX)
|
||||
{
|
||||
ConsolidatePanelsKeepOne(OpState->Panel, OpState->Panel->Left, &State->PanelSystem);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsolidatePanelsKeepOne(OpState->Panel, OpState->Panel->Right, &State->PanelSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
input_command DragPanelBorderCommands[] = {
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndDragPanelBorderOperation },
|
||||
{ KeyCode_MouseRightButton, KeyCode_Invalid, Command_Ended, EndDragPanelBorderOperation },
|
||||
};
|
||||
|
||||
internal void
|
||||
BeginDragPanelBorder(panel* Panel, panel_edit_mode PanelEditMode, rect2 PanelBounds, panel_split_direction PanelEdgeDirection, mouse_state Mouse, app_state* State)
|
||||
{
|
||||
operation_mode* DragPanelBorder = ActivateOperationModeWithCommands(&State->Modes, DragPanelBorderCommands, UpdateAndRenderDragPanelBorder);
|
||||
drag_panel_border_operation_state* OpState = CreateOperationState(DragPanelBorder, &State->Modes, drag_panel_border_operation_state);
|
||||
OpState->Panel = Panel;
|
||||
OpState->InitialPanelBounds = PanelBounds;
|
||||
OpState->PanelEdgeDirection = PanelEdgeDirection;
|
||||
OpState->PanelEditMode = PanelEditMode;
|
||||
}
|
||||
|
||||
// ----------------
|
||||
|
||||
//
|
||||
// Drag To Split Panel Operation
|
||||
|
||||
|
||||
OPERATION_STATE_DEF(split_panel_operation_state)
|
||||
{
|
||||
panel* Panel;
|
||||
|
||||
// NOTE(Peter): InitialPanelBounds is the bounds of the panel we are modifying,
|
||||
// it stores the value calculated when the operation mode is kicked off.
|
||||
rect2 InitialPanelBounds;
|
||||
};
|
||||
|
||||
OPERATION_RENDER_PROC(UpdateAndRenderSplitPanel)
|
||||
{
|
||||
split_panel_operation_state* OpState = (split_panel_operation_state*)Operation.OpStateMemory;
|
||||
rect2 PanelBounds = OpState->InitialPanelBounds;
|
||||
v4 EdgePreviewColor = v4{.3f, .3f, .3f, 1.f};
|
||||
|
||||
r32 MouseDeltaX = Abs(Mouse.Pos.x - Mouse.DownPos.x);
|
||||
r32 MouseDeltaY = Abs(Mouse.Pos.y - Mouse.DownPos.y);
|
||||
|
||||
v2 EdgePreviewMin = {};
|
||||
v2 EdgePreviewMax = {};
|
||||
if (MouseDeltaY > MouseDeltaX) // Horizontal Split
|
||||
{
|
||||
EdgePreviewMin = v2{PanelBounds.Min.x, Mouse.Pos.y};
|
||||
EdgePreviewMax = v2{PanelBounds.Max.x, Mouse.Pos.y + 1};
|
||||
}
|
||||
else // Vertical Split
|
||||
{
|
||||
EdgePreviewMin = v2{Mouse.Pos.x, PanelBounds.Min.y};
|
||||
EdgePreviewMax = v2{Mouse.Pos.x + 1, PanelBounds.Max.y};
|
||||
}
|
||||
|
||||
PushRenderQuad2D(RenderBuffer, EdgePreviewMin, EdgePreviewMax, EdgePreviewColor);
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation)
|
||||
{
|
||||
split_panel_operation_state* OpState = GetCurrentOperationState(State->Modes, split_panel_operation_state);
|
||||
rect2 PanelBounds = OpState->InitialPanelBounds;
|
||||
|
||||
r32 XDistance = Abs(Mouse.Pos.x - Mouse.DownPos.x);
|
||||
r32 YDistance = Abs(Mouse.Pos.y - Mouse.DownPos.y);
|
||||
|
||||
if (XDistance > YDistance)
|
||||
{
|
||||
r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / Rect2Width(PanelBounds);
|
||||
SplitPanelVertically(Panel, XPercent, &State->PanelSystem, State, Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / Rect2Height(PanelBounds);
|
||||
SplitPanelHorizontally(Panel, YPercent, &State->PanelSystem, State, Context);
|
||||
}
|
||||
|
||||
s32 PanelTypeIndex = Panel->TypeIndex;
|
||||
gs_data PanelStateMemory = Panel->StateMemory;
|
||||
Panel_SetCurrentType(Panel->Left, &State->PanelSystem, PanelTypeIndex, PanelStateMemory, State, Context);
|
||||
|
||||
Panel_SetType(Panel->Right, &State->PanelSystem, PanelTypeIndex, State, Context);
|
||||
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
input_command SplitPanelCommands[] = {
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, EndSplitPanelOperation },
|
||||
};
|
||||
|
||||
internal void
|
||||
BeginSplitPanelOperation(panel* Panel, mouse_state Mouse, app_state* State)
|
||||
{
|
||||
operation_mode* SplitPanel = ActivateOperationModeWithCommands(&State->Modes, SplitPanelCommands, UpdateAndRenderSplitPanel);
|
||||
split_panel_operation_state* OpState = CreateOperationState(SplitPanel, &State->Modes, split_panel_operation_state);
|
||||
OpState->Panel = Panel;
|
||||
OpState->InitialPanelBounds = Panel->Bounds;
|
||||
}
|
||||
|
||||
|
||||
// ----------------
|
||||
|
||||
#define PANEL_EDGE_CLICK_MAX_DISTANCE 6
|
||||
|
||||
internal b32
|
||||
HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEditMode, mouse_state Mouse, app_state* State)
|
||||
{
|
||||
b32 HandledMouseInput = false;
|
||||
|
||||
// TODO(pjs): this can probably live in panel_with_layout
|
||||
rect2 PanelSplitButtonBounds = rect2{ Panel->Bounds.Min, Panel->Bounds.Min + v2{25, 25} };
|
||||
|
||||
if (Panel->SplitDirection == PanelSplit_NoSplit
|
||||
&& PointIsInRect(PanelSplitButtonBounds, Mouse.DownPos))
|
||||
{
|
||||
BeginSplitPanelOperation(Panel, Mouse, State);
|
||||
HandledMouseInput = true;
|
||||
}
|
||||
else if (Panel->SplitDirection != PanelSplit_NoSplit)
|
||||
{
|
||||
u32 ElementIndex = 0;
|
||||
switch(Panel->SplitDirection)
|
||||
{
|
||||
case PanelSplit_Vertical: { ElementIndex = 0; } break;
|
||||
case PanelSplit_Horizontal: { ElementIndex = 1; } break;
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
|
||||
r32 SplitPosition = LerpR32(Panel->SplitPercent, Panel->Bounds.Min.E[ElementIndex], Panel->Bounds.Max.E[ElementIndex]);
|
||||
r32 ClickDistanceFromSplit = Abs(Mouse.DownPos.E[ElementIndex] - SplitPosition);
|
||||
if (ClickDistanceFromSplit < PANEL_EDGE_CLICK_MAX_DISTANCE)
|
||||
{
|
||||
BeginDragPanelBorder(Panel, PanelEditMode, Panel->Bounds, Panel->SplitDirection, Mouse, State);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PointIsInRect(Panel->Bottom->Bounds, Mouse.DownPos))
|
||||
{
|
||||
HandleMouseDownPanelInteractionOrRecurse(Panel->Bottom, PanelEditMode, Mouse, State);
|
||||
}
|
||||
else if (PointIsInRect(Panel->Top->Bounds, Mouse.DownPos))
|
||||
{
|
||||
HandleMouseDownPanelInteractionOrRecurse(Panel->Top, PanelEditMode, Mouse, State);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HandledMouseInput;
|
||||
}
|
||||
|
||||
internal b32
|
||||
HandleMousePanelInteraction(panel_system* PanelSystem, rect2 WindowBounds, mouse_state Mouse, app_state* State)
|
||||
{
|
||||
b32 HandledMouseInput = false;
|
||||
|
||||
panel* FirstPanel = PanelSystem->Panels + 0;
|
||||
panel_edit_mode EditMode = PanelEdit_Invalid;
|
||||
|
||||
if (MouseButtonTransitionedDown(Mouse.LeftButtonState))
|
||||
{
|
||||
EditMode = PanelEdit_Modify;
|
||||
}
|
||||
else if (MouseButtonTransitionedDown(Mouse.RightButtonState))
|
||||
{
|
||||
EditMode = PanelEdit_Destroy;
|
||||
}
|
||||
|
||||
if (EditMode != PanelEdit_Invalid)
|
||||
{
|
||||
HandledMouseInput = HandleMouseDownPanelInteractionOrRecurse(FirstPanel, EditMode, Mouse, State);
|
||||
}
|
||||
|
||||
return HandledMouseInput;
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawPanelBorder(panel Panel, v2 PanelMin, v2 PanelMax, mouse_state* Mouse, render_command_buffer* RenderBuffer)
|
||||
{
|
||||
r32 MouseLeftEdgeDistance = Abs(Mouse->Pos.x - PanelMin.x);
|
||||
r32 MouseRightEdgeDistance = Abs(Mouse->Pos.x - PanelMax.x);
|
||||
r32 MouseTopEdgeDistance = Abs(Mouse->Pos.y - PanelMax.y);
|
||||
r32 MouseBottomEdgeDistance = Abs(Mouse->Pos.y - PanelMin.y);
|
||||
|
||||
v4 Color = BlackV4;
|
||||
PushRenderBoundingBox2D(RenderBuffer, PanelMin, PanelMax, 1, Color);
|
||||
|
||||
v4 HighlightColor = v4{.3f, .3f, .3f, 1.f};
|
||||
r32 HighlightThickness = 1;
|
||||
if (MouseLeftEdgeDistance < PANEL_EDGE_CLICK_MAX_DISTANCE)
|
||||
{
|
||||
v2 LeftEdgeMin = PanelMin;
|
||||
v2 LeftEdgeMax = v2{PanelMin.x + HighlightThickness, PanelMax.y};
|
||||
PushRenderQuad2D(RenderBuffer, LeftEdgeMin, LeftEdgeMax, HighlightColor);
|
||||
Mouse->CursorType = CursorType_HArrows;
|
||||
}
|
||||
else if (MouseRightEdgeDistance < PANEL_EDGE_CLICK_MAX_DISTANCE)
|
||||
{
|
||||
v2 RightEdgeMin = v2{PanelMax.x - HighlightThickness, PanelMin.y};
|
||||
v2 RightEdgeMax = PanelMax;
|
||||
PushRenderQuad2D(RenderBuffer, RightEdgeMin, RightEdgeMax, HighlightColor);
|
||||
Mouse->CursorType = CursorType_HArrows;
|
||||
}
|
||||
else if (MouseTopEdgeDistance < PANEL_EDGE_CLICK_MAX_DISTANCE)
|
||||
{
|
||||
v2 TopEdgeMin = v2{PanelMin.x, PanelMax.y - HighlightThickness};
|
||||
v2 TopEdgeMax = PanelMax;
|
||||
PushRenderQuad2D(RenderBuffer, TopEdgeMin, TopEdgeMax, HighlightColor);
|
||||
Mouse->CursorType = CursorType_VArrows;
|
||||
}
|
||||
else if (MouseBottomEdgeDistance < PANEL_EDGE_CLICK_MAX_DISTANCE)
|
||||
{
|
||||
v2 BottomEdgeMin = PanelMin;
|
||||
v2 BottomEdgeMax = v2{PanelMax.x, PanelMin.y + HighlightThickness};
|
||||
PushRenderQuad2D(RenderBuffer, BottomEdgeMin, BottomEdgeMax, HighlightColor);
|
||||
Mouse->CursorType = CursorType_VArrows;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect2 FooterBounds, mouse_state Mouse, app_state* State, context Context)
|
||||
{
|
||||
PushRenderQuad2D(RenderBuffer, FooterBounds.Min, v2{FooterBounds.Max.x, FooterBounds.Min.y + 25}, v4{.5f, .5f, .5f, 1.f});
|
||||
PushRenderQuad2D(RenderBuffer, FooterBounds.Min, FooterBounds.Min + v2{25, 25}, WhiteV4);
|
||||
|
||||
rect2 PanelSelectBtnBounds = MakeRect2MinDim(FooterBounds.Min + v2{30, 1}, v2{100, 23});
|
||||
|
||||
panel_definition CurrentDef = State->PanelSystem.PanelDefs[Panel->TypeIndex];
|
||||
if (ui_BeginDropdown(&State->Interface, MakeString(CurrentDef.PanelName, CurrentDef.PanelNameLength), PanelSelectBtnBounds))
|
||||
{
|
||||
for (s32 i = 0; i < GlobalPanelDefsCount; i++)
|
||||
{
|
||||
panel_definition Def = State->PanelSystem.PanelDefs[i];
|
||||
gs_string DefName = MakeString(Def.PanelName, Def.PanelNameLength);
|
||||
if (ui_Button(&State->Interface, DefName))
|
||||
{
|
||||
Panel_SetType(Panel, &State->PanelSystem, i, State, Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_EndDropdown(&State->Interface);
|
||||
}
|
||||
|
||||
internal void
|
||||
RenderPanel(panel* Panel, rect2 PanelBounds, rect2 WindowBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse)
|
||||
{
|
||||
u32 PanelType = Panel->TypeIndex;
|
||||
Assert(PanelType >= 0);
|
||||
Assert(PanelType < State->PanelSystem.PanelDefsCount);
|
||||
|
||||
rect2 FooterBounds = rect2{
|
||||
PanelBounds.Min,
|
||||
v2{PanelBounds.Max.x, PanelBounds.Min.y + 25},
|
||||
};
|
||||
rect2 PanelViewBounds = rect2{
|
||||
v2{PanelBounds.Min.x, FooterBounds.Max.y},
|
||||
PanelBounds.Max,
|
||||
};
|
||||
|
||||
panel_definition Definition = State->PanelSystem.PanelDefs[PanelType];
|
||||
Definition.Render(Panel, PanelViewBounds, RenderBuffer, State, Context);
|
||||
|
||||
PushRenderOrthographic(RenderBuffer, WindowBounds);
|
||||
DrawPanelFooter(Panel, RenderBuffer, FooterBounds, Mouse, State, Context);
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawPanelRecursive(panel* Panel, render_command_buffer* RenderBuffer, mouse_state* Mouse, app_state* State, context Context)
|
||||
{
|
||||
rect2 Bounds = Panel->Bounds;
|
||||
switch (Panel->SplitDirection)
|
||||
{
|
||||
case PanelSplit_Horizontal:
|
||||
case PanelSplit_Vertical:
|
||||
{
|
||||
DrawPanelRecursive(Panel->Left, RenderBuffer, Mouse, State, Context);
|
||||
DrawPanelRecursive(Panel->Right, RenderBuffer, Mouse, State, Context);
|
||||
}break;
|
||||
|
||||
case PanelSplit_NoSplit:
|
||||
{
|
||||
panel* OverridePanel = Panel_GetModalOverride(Panel);
|
||||
RenderPanel(OverridePanel, Bounds, State->WindowBounds, RenderBuffer, State, Context, *Mouse);
|
||||
PushRenderOrthographic(RenderBuffer, State->WindowBounds);
|
||||
DrawPanelBorder(*OverridePanel, Bounds.Min, Bounds.Max, Mouse, RenderBuffer);
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawAllPanels(panel_system System, render_command_buffer* RenderBuffer, mouse_state* Mouse, app_state* State, context Context)
|
||||
{
|
||||
panel* PanelAt = System.Panels + 0;
|
||||
DrawPanelRecursive(PanelAt, RenderBuffer, Mouse, State, Context);
|
||||
}
|
||||
|
||||
#define FOLDHAUS_INTERFACE_CPP
|
||||
#endif // FOLDHAUS_INTERFACE_CPP
|
|
@ -0,0 +1,142 @@
|
|||
//
|
||||
// File: foldhaus_operation_mode.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_OPERATION_MODE_H
|
||||
|
||||
typedef struct operation_mode operation_mode;
|
||||
|
||||
#define OPERATION_STATE_DEF(name) struct name
|
||||
|
||||
#define OPERATION_RENDER_PROC(name) void name(app_state* State, render_command_buffer* RenderBuffer, operation_mode Operation, mouse_state Mouse, context Context)
|
||||
typedef OPERATION_RENDER_PROC(operation_render_proc);
|
||||
|
||||
struct operation_mode
|
||||
{
|
||||
input_command_registry Commands;
|
||||
operation_render_proc* Render;
|
||||
gs_memory_cursor Memory;
|
||||
u8* OpStateMemory;
|
||||
};
|
||||
|
||||
#define OPERATION_MODES_MAX 32
|
||||
struct operation_mode_system
|
||||
{
|
||||
s32 ActiveModesCount;
|
||||
operation_mode ActiveModes[OPERATION_MODES_MAX];
|
||||
//arena_snapshot ModeMemorySnapshots[OPERATION_MODES_MAX];
|
||||
gs_data_array ModeMemoryPagesFreeList;
|
||||
|
||||
// NOTE(Peter): This acts as mode scoped memory. When a mode gets activated, it can allocate
|
||||
// temporary memory which then gets freed when the mode is deactivated
|
||||
gs_memory_arena Arena;
|
||||
};
|
||||
|
||||
internal operation_mode_system
|
||||
OperationModeSystemInit(gs_memory_arena* Storage, gs_thread_context ThreadContext)
|
||||
{
|
||||
operation_mode_system Result = {0};
|
||||
// TODO(Peter): Do we really need an arena? Can this just operate in constant memory footprint?
|
||||
Result.Arena.Allocator = ThreadContext.Allocator;
|
||||
|
||||
Result.ModeMemoryPagesFreeList.CountMax = 8;
|
||||
Result.ModeMemoryPagesFreeList.Data = PushArray(Storage, gs_data, Result.ModeMemoryPagesFreeList.CountMax);
|
||||
for (u32 Page = 0; Page < Result.ModeMemoryPagesFreeList.CountMax; Page++)
|
||||
{
|
||||
Result.ModeMemoryPagesFreeList.Data[Page] = PushSize(Storage, KB(4));
|
||||
}
|
||||
Result.ModeMemoryPagesFreeList.Count = Result.ModeMemoryPagesFreeList.CountMax;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal gs_data
|
||||
OperationModeTakeMemoryPage(operation_mode_system* System)
|
||||
{
|
||||
Assert(System->ModeMemoryPagesFreeList.Count > 0);
|
||||
gs_data Result = {0};
|
||||
System->ModeMemoryPagesFreeList.Count -= 1;
|
||||
u64 LastIndex = System->ModeMemoryPagesFreeList.Count;
|
||||
Result = System->ModeMemoryPagesFreeList.Data[LastIndex];
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
OperationModeFreeMemoryPage(operation_mode_system* System, gs_data Data)
|
||||
{
|
||||
Assert(System->ModeMemoryPagesFreeList.Count < System->ModeMemoryPagesFreeList.CountMax);
|
||||
u64 LastIndex = System->ModeMemoryPagesFreeList.Count;
|
||||
System->ModeMemoryPagesFreeList.Count += 1;
|
||||
System->ModeMemoryPagesFreeList.Data[LastIndex] = Data;
|
||||
}
|
||||
|
||||
internal operation_mode*
|
||||
ActivateOperationMode (operation_mode_system* System, operation_render_proc* RenderProc)
|
||||
{
|
||||
Assert(System->ActiveModesCount < OPERATION_MODES_MAX);
|
||||
operation_mode* Result = 0;
|
||||
s32 ModeIndex = System->ActiveModesCount++;
|
||||
|
||||
//System->ModeMemorySnapshots[ModeIndex] = TakeSnapshotOfArena(&System->Arena);
|
||||
|
||||
Result = &System->ActiveModes[ModeIndex];
|
||||
Result->Memory = MemoryCursorCreateFromData(OperationModeTakeMemoryPage(System));
|
||||
Result->Render = RenderProc;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define ActivateOperationModeWithCommands(sys, cmds, render) \
|
||||
ActivateOperationModeWithCommands_(sys, cmds, (s32)(sizeof(cmds) / sizeof(cmds[0])), render);
|
||||
|
||||
internal operation_mode*
|
||||
ActivateOperationModeWithCommands_(operation_mode_system* System, input_command* Commands, s32 CommandsCount, operation_render_proc* RenderProc)
|
||||
{
|
||||
operation_mode* NewMode = ActivateOperationMode(System, RenderProc);
|
||||
|
||||
#if 0
|
||||
InitializeInputCommandRegistry(&NewMode->Commands, CommandsCount, &System->Arena);
|
||||
for (s32 i = 0; i < CommandsCount; i++)
|
||||
{
|
||||
input_command Command = Commands[i];
|
||||
RegisterKeyPressCommand(&NewMode->Commands, Command.Key, Command.Flags, Command.Mdfr, Command.Proc);
|
||||
}
|
||||
#else
|
||||
NewMode->Commands.Commands = Commands;
|
||||
NewMode->Commands.Size = CommandsCount;
|
||||
NewMode->Commands.Used = CommandsCount;
|
||||
#endif
|
||||
return NewMode;
|
||||
}
|
||||
|
||||
internal void
|
||||
DeactivateCurrentOperationMode (operation_mode_system* System)
|
||||
{
|
||||
Assert(System->ActiveModesCount > 0);
|
||||
s32 ModeIndex = --System->ActiveModesCount;
|
||||
OperationModeFreeMemoryPage(System, System->ActiveModes[ModeIndex].Memory.Data);
|
||||
//ClearArenaToSnapshot(&System->Arena, System->ModeMemorySnapshots[ModeIndex]);
|
||||
}
|
||||
|
||||
#define CreateOperationState(mode, modeSystem, stateType) \
|
||||
(stateType*)CreateOperationState_(mode, modeSystem, sizeof(stateType))
|
||||
|
||||
#define GetCurrentOperationState(modeSystem, stateType) \
|
||||
(stateType*)(modeSystem).ActiveModes[(modeSystem).ActiveModesCount - 1].OpStateMemory;
|
||||
|
||||
|
||||
internal u8*
|
||||
CreateOperationState_ (operation_mode* Mode, operation_mode_system* System, s32 StateSize)
|
||||
{
|
||||
// NOTE(Peter): This isn't a problem if this fires, it just means our page size is too small,
|
||||
// and its time to make the pages dynamically sized
|
||||
Assert(Mode->Memory.Data.Size >= StateSize);
|
||||
u8* Result = MemoryCursorPushSize(&Mode->Memory, StateSize).Memory;
|
||||
Mode->OpStateMemory = Result;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_OPERATION_MODE_H
|
||||
#endif // FOLDHAUS_OPERATION_MODE_H
|
|
@ -0,0 +1,442 @@
|
|||
//
|
||||
// File: foldhaus_panel.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2019-12-26
|
||||
//
|
||||
// Usage:
|
||||
// Include this file in ONE file in your project.
|
||||
// Define SetPanelDefinitionExternal
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_H
|
||||
|
||||
enum panel_split_direction
|
||||
{
|
||||
PanelSplit_NoSplit,
|
||||
PanelSplit_Horizontal,
|
||||
PanelSplit_Vertical,
|
||||
|
||||
PanelSplit_Count,
|
||||
};
|
||||
|
||||
typedef struct panel panel;
|
||||
|
||||
#define PANEL_MODAL_OVERRIDE_CALLBACK(name) void name(panel* ReturningFrom, app_state* State, context Context)
|
||||
typedef PANEL_MODAL_OVERRIDE_CALLBACK(panel_modal_override_callback);
|
||||
|
||||
struct panel
|
||||
{
|
||||
s32 TypeIndex;
|
||||
gs_data StateMemory;
|
||||
|
||||
panel* ModalOverride;
|
||||
panel* IsModalOverrideFor;
|
||||
panel_modal_override_callback* ModalOverrideCB;
|
||||
|
||||
rect2 Bounds;
|
||||
panel_split_direction SplitDirection;
|
||||
r32 SplitPercent;
|
||||
|
||||
panel* Parent;
|
||||
|
||||
union{
|
||||
panel* Left;
|
||||
panel* Top;
|
||||
};
|
||||
union{
|
||||
panel* Right;
|
||||
panel* Bottom;
|
||||
};
|
||||
};
|
||||
|
||||
struct free_panel
|
||||
{
|
||||
free_panel* Next;
|
||||
};
|
||||
|
||||
#define PANEL_INIT_PROC(name) void name(panel* Panel, app_state* State, context Context)
|
||||
typedef PANEL_INIT_PROC(panel_init_proc);
|
||||
|
||||
#define PANEL_CLEANUP_PROC(name) void name(panel* Panel, app_state* State)
|
||||
typedef PANEL_CLEANUP_PROC(panel_cleanup_proc);
|
||||
|
||||
#define PANEL_RENDER_PROC(name) void name(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
typedef PANEL_RENDER_PROC(panel_render_proc);
|
||||
|
||||
// NOTE(Peter): This is used by the meta system to generate panel type info
|
||||
struct panel_definition
|
||||
{
|
||||
char* PanelName;
|
||||
s32 PanelNameLength;
|
||||
panel_init_proc* Init;
|
||||
panel_cleanup_proc* Cleanup;
|
||||
panel_render_proc* Render;
|
||||
input_command* InputCommands;
|
||||
s32 InputCommandsCount;
|
||||
};
|
||||
|
||||
#define PANELS_MAX 16
|
||||
struct panel_system
|
||||
{
|
||||
panel_definition* PanelDefs;
|
||||
u32 PanelDefsCount;
|
||||
|
||||
panel* Panels;
|
||||
u32 PanelsUsed;
|
||||
|
||||
free_panel* FreeList;
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
//
|
||||
// Book-Keeping
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
internal void
|
||||
PanelSystem_Init(panel_system* PanelSystem, panel_definition* PanelDefs, u32 PanelDefsCount, gs_memory_arena* Storage)
|
||||
{
|
||||
PanelSystem->FreeList = 0;
|
||||
PanelSystem->PanelDefs = PanelDefs;
|
||||
PanelSystem->PanelDefsCount = PanelDefsCount;
|
||||
|
||||
PanelSystem->Panels = PushArray(Storage, panel, PANELS_MAX);
|
||||
}
|
||||
|
||||
internal panel*
|
||||
PanelSystem_TakePanel(panel_system* PanelSystem)
|
||||
{
|
||||
panel* FreeEntry = 0;
|
||||
if (PanelSystem->FreeList != 0)
|
||||
{
|
||||
free_panel* FreePanel = PanelSystem->FreeList;
|
||||
PanelSystem->FreeList = FreePanel->Next;
|
||||
FreeEntry = (panel*)FreePanel;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(PanelSystem->PanelsUsed < PANELS_MAX);
|
||||
FreeEntry = PanelSystem->Panels + PanelSystem->PanelsUsed++;
|
||||
}
|
||||
return FreeEntry;
|
||||
}
|
||||
|
||||
internal void
|
||||
PanelSystem_FreePanel(panel* Panel, panel_system* PanelSystem)
|
||||
{
|
||||
Assert(Panel >= PanelSystem->Panels && Panel <= PanelSystem->Panels + PANELS_MAX);
|
||||
|
||||
free_panel* FreeEntry = (free_panel*)Panel;
|
||||
FreeEntry->Next = PanelSystem->FreeList;
|
||||
PanelSystem->FreeList = FreeEntry;
|
||||
}
|
||||
|
||||
internal void
|
||||
PanelSystem_FreePanelRecursive(panel* Panel, panel_system* PanelSystem)
|
||||
{
|
||||
if (Panel->SplitDirection != PanelSplit_NoSplit)
|
||||
{
|
||||
PanelSystem_FreePanelRecursive(Panel->Left, PanelSystem);
|
||||
PanelSystem_FreePanelRecursive(Panel->Right, PanelSystem);
|
||||
}
|
||||
PanelSystem_FreePanel(Panel, PanelSystem);
|
||||
}
|
||||
|
||||
internal panel*
|
||||
Panel_GetModalOverride(panel* Panel)
|
||||
{
|
||||
panel* Result = Panel;
|
||||
if (Panel->ModalOverride != 0)
|
||||
{
|
||||
Result = Panel_GetModalOverride(Panel->ModalOverride);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
Panel_PushModalOverride(panel* Root, panel* Override, panel_modal_override_callback* Callback)
|
||||
{
|
||||
Root->ModalOverride = Override;
|
||||
Root->ModalOverrideCB = Callback;
|
||||
Override->IsModalOverrideFor = Root;
|
||||
Override->Bounds = Root->Bounds;
|
||||
}
|
||||
|
||||
internal void
|
||||
Panel_PopModalOverride(panel* Parent, panel_system* System)
|
||||
{
|
||||
// TODO(pjs): Free the overrided panel
|
||||
PanelSystem_FreePanel(Parent->ModalOverride, System);
|
||||
Parent->ModalOverride = 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
Panel_SetCurrentType(panel* Panel, panel_system* System, s32 NewPanelType, gs_data TypeStateMemory, app_state* State, context Context)
|
||||
{
|
||||
s32 OldTypeIndex = Panel->TypeIndex;
|
||||
|
||||
Panel->TypeIndex = NewPanelType;
|
||||
Panel->StateMemory = TypeStateMemory;
|
||||
|
||||
if(OldTypeIndex >= 0)
|
||||
{
|
||||
System->PanelDefs[OldTypeIndex].Cleanup(Panel, State);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
Panel_SetType(panel* Panel, panel_system* System, s32 NewPanelTypeIndex, app_state* State, context Context)
|
||||
{
|
||||
gs_data EmptyStateData = {0};
|
||||
Panel_SetCurrentType(Panel, System, NewPanelTypeIndex, EmptyStateData, State, Context);
|
||||
System->PanelDefs[NewPanelTypeIndex].Init(Panel, State, Context);
|
||||
}
|
||||
|
||||
#define Panel_GetStateStruct(p, type) (type*)Panel_GetStateMemory((p), sizeof(type)).Memory
|
||||
internal gs_data
|
||||
Panel_GetStateMemory(panel* Panel, u64 Size)
|
||||
{
|
||||
Assert(Panel->StateMemory.Size == Size);
|
||||
gs_data Result = Panel->StateMemory;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal panel*
|
||||
PanelSystem_PushPanel(panel_system* PanelSystem, s32 PanelTypeIndex, app_state* State, context Context)
|
||||
{
|
||||
panel* Panel = PanelSystem_TakePanel(PanelSystem);
|
||||
Panel_SetType(Panel, PanelSystem, PanelTypeIndex, State, Context);
|
||||
return Panel;
|
||||
}
|
||||
|
||||
internal void
|
||||
SplitPanel(panel* Parent, r32 Percent, panel_split_direction SplitDirection, panel_system* PanelSystem, app_state* State, context Context)
|
||||
{
|
||||
if (Percent >= 0.0f && Percent <= 1.0f)
|
||||
{
|
||||
Parent->SplitDirection = SplitDirection;
|
||||
Parent->SplitPercent = Percent;
|
||||
|
||||
s32 ParentTypeIndex = Parent->TypeIndex;
|
||||
gs_data ParentStateMemory = Parent->StateMemory;
|
||||
|
||||
Parent->Left = PanelSystem_TakePanel(PanelSystem);
|
||||
Panel_SetCurrentType(Parent->Left, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context);
|
||||
Parent->Left->Parent = Parent;
|
||||
|
||||
Parent->Right = PanelSystem_TakePanel(PanelSystem);
|
||||
Panel_SetCurrentType(Parent->Right, PanelSystem, ParentTypeIndex, ParentStateMemory, State, Context);
|
||||
Parent->Right->Parent = Parent;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
SplitPanelVertically(panel* Parent, r32 Percent, panel_system* PanelSystem, app_state* State, context Context)
|
||||
{
|
||||
SplitPanel(Parent, Percent, PanelSplit_Vertical, PanelSystem, State, Context);
|
||||
}
|
||||
|
||||
internal void
|
||||
SplitPanelHorizontally(panel* Parent, r32 Percent, panel_system* PanelSystem, app_state* State, context Context)
|
||||
{
|
||||
SplitPanel(Parent, Percent, PanelSplit_Horizontal, PanelSystem, State, Context);
|
||||
}
|
||||
|
||||
internal void
|
||||
ConsolidatePanelsKeepOne(panel* Parent, panel* PanelToKeep, panel_system* PanelSystem)
|
||||
{
|
||||
panel* LeftChild = Parent->Left;
|
||||
panel* RightChild = Parent->Right;
|
||||
|
||||
panel* PanelToDestroy = PanelToKeep == LeftChild ? RightChild : LeftChild;
|
||||
|
||||
*Parent = *PanelToKeep;
|
||||
|
||||
PanelSystem_FreePanel(PanelToKeep, PanelSystem);
|
||||
PanelSystem_FreePanelRecursive(PanelToDestroy, PanelSystem);
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
//
|
||||
// Rendering And Interaction
|
||||
//
|
||||
/////////////////////////////////
|
||||
|
||||
internal rect2
|
||||
GetTopPanelBounds(panel* Panel)
|
||||
{
|
||||
rect2 Result = {};
|
||||
Result.Min = v2{
|
||||
Panel->Bounds.Min.x,
|
||||
LerpR32(Panel->SplitPercent, Panel->Bounds.Min.y, Panel->Bounds.Max.y)
|
||||
};
|
||||
Result.Max = Panel->Bounds.Max;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal rect2
|
||||
GetBottomPanelBounds(panel* Panel)
|
||||
{
|
||||
rect2 Result = {};
|
||||
Result.Min = Panel->Bounds.Min;
|
||||
Result.Max = v2{
|
||||
Panel->Bounds.Max.x,
|
||||
LerpR32(Panel->SplitPercent, Panel->Bounds.Min.y, Panel->Bounds.Max.y)
|
||||
};
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal rect2
|
||||
GetRightPanelBounds(panel* Panel)
|
||||
{
|
||||
rect2 Result = {};
|
||||
Result.Min = v2{
|
||||
LerpR32(Panel->SplitPercent, Panel->Bounds.Min.x, Panel->Bounds.Max.x),
|
||||
Panel->Bounds.Min.y
|
||||
};
|
||||
Result.Max = Panel->Bounds.Max;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal rect2
|
||||
GetLeftPanelBounds(panel* Panel)
|
||||
{
|
||||
rect2 Result = {};
|
||||
Result.Min = Panel->Bounds.Min;
|
||||
Result.Max = v2{
|
||||
LerpR32(Panel->SplitPercent, Panel->Bounds.Min.x, Panel->Bounds.Max.x),
|
||||
Panel->Bounds.Max.y
|
||||
};
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal rect2
|
||||
GetTopPanelBounds(panel* Panel, rect2 PanelBounds)
|
||||
{
|
||||
rect2 Result = {};
|
||||
Result.Min = v2{
|
||||
PanelBounds.Min.x,
|
||||
LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y)
|
||||
};
|
||||
Result.Max = PanelBounds.Max;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal rect2
|
||||
GetBottomPanelBounds(panel* Panel, rect2 PanelBounds)
|
||||
{
|
||||
rect2 Result = {};
|
||||
Result.Min = PanelBounds.Min;
|
||||
Result.Max = v2{
|
||||
PanelBounds.Max.x,
|
||||
LerpR32(Panel->SplitPercent, PanelBounds.Min.y, PanelBounds.Max.y)
|
||||
};
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal rect2
|
||||
GetRightPanelBounds(panel* Panel, rect2 PanelBounds)
|
||||
{
|
||||
rect2 Result = {};
|
||||
Result.Min = v2{
|
||||
LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x),
|
||||
PanelBounds.Min.y
|
||||
};
|
||||
Result.Max = PanelBounds.Max;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal rect2
|
||||
GetLeftPanelBounds(panel* Panel, rect2 PanelBounds)
|
||||
{
|
||||
rect2 Result = {};
|
||||
Result.Min = PanelBounds.Min;
|
||||
Result.Max = v2{
|
||||
LerpR32(Panel->SplitPercent, PanelBounds.Min.x, PanelBounds.Max.x),
|
||||
PanelBounds.Max.y
|
||||
};
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
Panel_UpdateLayout(panel* Panel, rect2 Bounds)
|
||||
{
|
||||
Panel->Bounds = Bounds;
|
||||
|
||||
if (Panel->SplitDirection != PanelSplit_NoSplit)
|
||||
{
|
||||
rect2 LeftOrTopBounds = {};
|
||||
rect2 RightOrBottomBounds = {};
|
||||
switch (Panel->SplitDirection)
|
||||
{
|
||||
case PanelSplit_Horizontal:
|
||||
{
|
||||
LeftOrTopBounds = GetTopPanelBounds(Panel);
|
||||
RightOrBottomBounds = GetBottomPanelBounds(Panel);
|
||||
} break;
|
||||
|
||||
case PanelSplit_Vertical:
|
||||
{
|
||||
LeftOrTopBounds = GetLeftPanelBounds(Panel);
|
||||
RightOrBottomBounds = GetRightPanelBounds(Panel);
|
||||
} break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
|
||||
Panel_UpdateLayout(Panel->Left, LeftOrTopBounds);
|
||||
Panel_UpdateLayout(Panel->Right, RightOrBottomBounds);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
PanelSystem_UpdateLayout(panel_system* System, rect2 WindowBounds)
|
||||
{
|
||||
panel* Root = System->Panels;
|
||||
Panel_UpdateLayout(Root, WindowBounds);
|
||||
}
|
||||
|
||||
internal panel*
|
||||
GetPanelContainingPoint(panel* Panel, v2 Point)
|
||||
{
|
||||
panel* Result = 0;
|
||||
|
||||
if (PointIsInRect(Panel->Bounds, Point))
|
||||
{
|
||||
switch (Panel->SplitDirection)
|
||||
{
|
||||
case PanelSplit_NoSplit:
|
||||
{
|
||||
Result = Panel;
|
||||
}break;
|
||||
|
||||
case PanelSplit_Vertical:
|
||||
case PanelSplit_Horizontal:
|
||||
{asdfasdfasdfasdfasdf
|
||||
if (PointIsInRect(Panel->Left->Bounds, Point))
|
||||
{
|
||||
Result = GetPanelContainingPoint(Panel->Left, Point);
|
||||
}
|
||||
else if (PointIsInRect(Panel->Right->Bounds, Point))
|
||||
{
|
||||
Result = GetPanelContainingPoint(Panel->Right, Point);
|
||||
}
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal panel*
|
||||
PanelSystem_GetPanelContainingPoint(panel_system* System, v2 Point)
|
||||
{
|
||||
panel* Result = 0;
|
||||
panel* Root = System->Panels;
|
||||
Result = GetPanelContainingPoint(Root, Point);
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define FOLDHAUS_PANEL_H
|
||||
#endif // FOLDHAUS_PANEL_H
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,146 @@
|
|||
//
|
||||
// File: foldhaus_panel_assembly_debug.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2021-01-15
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_ASSEMBLY_DEBUG_H
|
||||
|
||||
GSMetaTag(panel_init);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
AssemblyDebug_Init(panel* Panel, app_state* State, context Context)
|
||||
{
|
||||
}
|
||||
|
||||
GSMetaTag(panel_cleanup);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
AssemblyDebug_Cleanup(panel* Panel, app_state* State)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// TODO(pjs): This is really blumen specific
|
||||
#define FSC(f,c) FlowerStripToChannel((f), (c))
|
||||
internal u8
|
||||
FlowerStripToChannel(u8 Flower, u8 Channel)
|
||||
{
|
||||
Assert(Flower < 3);
|
||||
Assert(Channel < 8);
|
||||
|
||||
u8 Result = 0;
|
||||
Result |= (Flower & 0x03) << 3;
|
||||
Result |= (Channel & 0x07);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
GSMetaTag(panel_render);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
AssemblyDebug_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
ui_interface* Interface = &State->Interface;
|
||||
ui_PushLayout(Interface, PanelBounds, LayoutDirection_TopDown, MakeString("Assembly Debug Layout"));
|
||||
|
||||
ui_BeginRow(Interface, 2);
|
||||
{
|
||||
if (ui_Button(Interface, MakeString("Assembly")))
|
||||
{
|
||||
State->ShowingUserSpaceDebug = false;
|
||||
}
|
||||
|
||||
if (ui_Button(Interface, MakeString("User Space")))
|
||||
{
|
||||
State->ShowingUserSpaceDebug = true;
|
||||
}
|
||||
}
|
||||
ui_EndRow(Interface);
|
||||
|
||||
if (State->ShowingUserSpaceDebug && State->UserSpaceDesc.CustomDebugUI)
|
||||
{
|
||||
US_CustomDebugUI(&State->UserSpaceDesc, Panel, PanelBounds, RenderBuffer,
|
||||
State, Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
InterfaceAssert(Interface->PerFrameMemory);
|
||||
|
||||
State->AssemblyDebugState.AllAssemblies = ui_ToggleText(Interface, MakeString("All Assemblies"), State->AssemblyDebugState.AllAssemblies);
|
||||
|
||||
gs_string OverrideStr = MakeString(OverrideTypeStrings[State->AssemblyDebugState.Override]);
|
||||
if (ui_BeginLabeledDropdown(Interface, MakeString("Override"), OverrideStr))
|
||||
{
|
||||
for (u32 i = 0; i < ADS_Override_Count; i++)
|
||||
{
|
||||
if (ui_Button(Interface, MakeString(OverrideTypeStrings[i])))
|
||||
{
|
||||
State->AssemblyDebugState.Override = (override_type)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_EndLabeledDropdown(Interface);
|
||||
InterfaceAssert(Interface->PerFrameMemory);
|
||||
|
||||
switch (State->AssemblyDebugState.Override)
|
||||
{
|
||||
case ADS_Override_TagWhite:
|
||||
case ADS_Override_TagStripWhite:
|
||||
{
|
||||
ui_LabeledTextEntry(Interface, MakeString("Tag Name"), &State->AssemblyDebugState.TagName);
|
||||
ui_LabeledTextEntry(Interface, MakeString("Tag Value"), &State->AssemblyDebugState.TagValue);
|
||||
|
||||
if (State->AssemblyDebugState.Override == ADS_Override_TagStripWhite)
|
||||
{
|
||||
State->AssemblyDebugState.TargetAssembly = ui_LabeledTextEntryU64(Interface, MakeString("Assembly"), State->AssemblyDebugState.TargetAssembly);
|
||||
|
||||
State->AssemblyDebugState.TargetStrip = ui_LabeledTextEntryU64(Interface, MakeString("Strip"), State->AssemblyDebugState.TargetStrip);
|
||||
}
|
||||
}break;
|
||||
|
||||
case ADS_Override_ChannelWhite:
|
||||
{
|
||||
u64 Board = 0;
|
||||
u64 Strip = 0;
|
||||
Board = ui_LabeledTextEntryU64(Interface, MakeString("Board"), Board);
|
||||
Strip = ui_LabeledTextEntryU64(Interface, MakeString("Strip"), Strip);
|
||||
|
||||
State->AssemblyDebugState.TargetChannel = FSC(Board, Strip);
|
||||
}break;
|
||||
|
||||
case ADS_Override_AllOff:
|
||||
case ADS_Override_AllRed:
|
||||
case ADS_Override_AllGreen:
|
||||
case ADS_Override_AllBlue:
|
||||
case ADS_Override_AllWhite:
|
||||
{
|
||||
State->AssemblyDebugState.Brightness = (u8)ui_LabeledRangeSlider(Interface, MakeString("Brightness"), (r32)State->AssemblyDebugState.Brightness, 0, 255);
|
||||
State->AssemblyDebugState.TargetAssembly = ui_LabeledTextEntryU64(Interface, MakeString("Assembly"), State->AssemblyDebugState.TargetAssembly);
|
||||
}break;
|
||||
|
||||
case ADS_Override_AllHue:
|
||||
{
|
||||
State->AssemblyDebugState.TargetHue = (u32)ui_LabeledRangeSlider(Interface, MakeString("Hue"), (r32)State->AssemblyDebugState.TargetHue, 0, 360);
|
||||
}break;
|
||||
|
||||
default:
|
||||
{
|
||||
InterfaceAssert(Interface->PerFrameMemory);
|
||||
|
||||
State->AssemblyDebugState.TargetAssembly = ui_LabeledTextEntryU64(Interface, MakeString("Assembly"), State->AssemblyDebugState.TargetAssembly);
|
||||
|
||||
InterfaceAssert(Interface->PerFrameMemory);
|
||||
|
||||
State->AssemblyDebugState.TargetStrip = ui_LabeledTextEntryU64(Interface, MakeString("Strip"), State->AssemblyDebugState.TargetStrip);
|
||||
|
||||
InterfaceAssert(Interface->PerFrameMemory);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
State->SendEmptyPackets = ui_LabeledToggle(Interface, MakeString("Send Empty Packets"), State->SendEmptyPackets);
|
||||
ui_PopLayout(Interface, MakeString("Assembly Debug Layout"));
|
||||
}
|
||||
|
||||
#define FOLDHAUS_PANEL_ASSEMBLY_DEBUG_H
|
||||
#endif // FOLDHAUS_PANEL_ASSEMBLY_DEBUG_H
|
|
@ -0,0 +1,148 @@
|
|||
//
|
||||
// File: foldhaus_panel_dmx_view.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_DMX_VIEW_H
|
||||
|
||||
struct universe_view_operation_state
|
||||
{
|
||||
b32 MouseDown;
|
||||
v2 DisplayOffset;
|
||||
r32 Zoom;
|
||||
};
|
||||
|
||||
input_command DMXView_Commands[] = {{}};
|
||||
s32 DMXView_CommandsCount = 0;
|
||||
|
||||
GSMetaTag(panel_init);
|
||||
GSMetaTag(panel_type_dmx_view);
|
||||
internal void
|
||||
DMXView_Init(panel* Panel, app_state* State, context Context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GSMetaTag(panel_cleanup);
|
||||
GSMetaTag(panel_type_dmx_view);
|
||||
internal void
|
||||
DMXView_Cleanup(panel* Panel, app_state* State)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// NOTE(Peter): Here to illustrate what old SACN Universe drawing looked like
|
||||
// This won't actually function
|
||||
// :NoLongerFunctionalSACNCodeButThatsOk
|
||||
internal void
|
||||
DrawSACNUniversePixels (render_command_buffer* RenderBuffer, sacn_universe* ToDraw,
|
||||
v2 TopLeft, v2 Dimension)
|
||||
{
|
||||
Assert(ToDraw);
|
||||
|
||||
s32 PixelsPerRow = 21;
|
||||
r32 PixelDim = Dimension.x / PixelsPerRow;
|
||||
v2 PixelSize = v2{PixelDim, PixelDim};
|
||||
|
||||
v2 PixelRegister = TopLeft;
|
||||
v4 DisplayColor = {0, 0, 0, 1};
|
||||
|
||||
s32 PixelsToDraw = ToDraw->SizeInSendBuffer - STREAM_HEADER_SIZE;
|
||||
render_quad_batch_constructor BatchConstructor = PushRenderQuad2DBatch(RenderBuffer, PixelsToDraw);
|
||||
|
||||
u8* ColorCursor = (u8*)ToDraw->StartPositionInSendBuffer + STREAM_HEADER_SIZE;
|
||||
s32 PixelsDrawn = 0;
|
||||
for (s32 i = 0; i < PixelsToDraw; i++)
|
||||
{
|
||||
PixelRegister.x = TopLeft.x + (PixelsDrawn % PixelsPerRow) * PixelDim;
|
||||
PixelRegister.y = TopLeft.y - (PixelsDrawn / PixelsPerRow) * PixelDim;
|
||||
|
||||
r32 Value = *ColorCursor++ / 255.f;
|
||||
DisplayColor.r = Value;
|
||||
DisplayColor.g = Value;
|
||||
DisplayColor.b = Value;
|
||||
|
||||
PushQuad2DOnBatch(&BatchConstructor, PixelRegister, PixelRegister + PixelSize, DisplayColor);
|
||||
|
||||
++PixelsDrawn;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GSMetaTag(panel_render);
|
||||
GSMetaTag(panel_type_dmx_view);
|
||||
internal void
|
||||
DMXView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
#if 0
|
||||
// :NoLongerFunctionalSACNCodeButThatsOk
|
||||
DEBUG_TRACK_SCOPE(DrawUniverseOutputDisplay);
|
||||
|
||||
universe_view_operation_state* OpState = (universe_view_operation_state*)Operation.OpStateMemory;
|
||||
|
||||
gs_string TitleBargs_string = InitializeEmptygs_string(PushArray(State->Transient, char, 64), 64);
|
||||
|
||||
v2 DisplayArea_Dimension = v2{600, 600};
|
||||
|
||||
v2 DisplayContents_Offset = OpState->DisplayOffset;
|
||||
|
||||
//
|
||||
// TODO(Peter): I don't like this. Dragging the Universe view should be an operation mode, just
|
||||
// like rotating the 3D view, but modes don't have access to the state of modes above them in the stack
|
||||
// (and attempting to cast those states to the appropriate type seems risky)
|
||||
//
|
||||
// :NeedToPassStateDownModeChain
|
||||
//
|
||||
if (OpState->MouseDown)
|
||||
{
|
||||
DisplayContents_Offset += (Mouse.Pos - Mouse.DownPos);
|
||||
}
|
||||
|
||||
v2 DisplayArea_TopLeft = v2{300, (r32)RenderBuffer->ViewHeight - 50} + DisplayContents_Offset;
|
||||
v2 UniverseDisplayDimension = v2{100, 100} * OpState->Zoom;
|
||||
v2 Padding = v2{25, 50} * OpState->Zoom;
|
||||
|
||||
v2 UniverseDisplayTopLeft = DisplayArea_TopLeft;
|
||||
|
||||
sacn_universe_buffer* UniverseList = State->SACN.UniverseBuffer;
|
||||
while(UniverseList)
|
||||
{
|
||||
for (s32 UniverseIdx = 0;
|
||||
UniverseIdx < UniverseList->Used;
|
||||
UniverseIdx++)
|
||||
{
|
||||
sacn_universe* Universe = UniverseList->Universes + UniverseIdx;
|
||||
DrawSACNUniversePixels(RenderBuffer, Universe, UniverseDisplayTopLeft, UniverseDisplayDimension);
|
||||
|
||||
|
||||
if (OpState->Zoom > .5f)
|
||||
{
|
||||
v2 TitleDisplayStart = UniverseDisplayTopLeft + v2{0, 12};
|
||||
PrintF(&TitleBargs_string, "Universe %d", Universe->Universe);
|
||||
DrawString(RenderBuffer, TitleBargs_string, State->Interface.Font,
|
||||
TitleDisplayStart, WhiteV4);
|
||||
}
|
||||
|
||||
UniverseDisplayTopLeft.x += UniverseDisplayDimension.x + Padding.x;
|
||||
if (UniverseDisplayTopLeft.x > DisplayArea_TopLeft.x + DisplayArea_Dimension.x)
|
||||
{
|
||||
UniverseDisplayTopLeft.x = DisplayArea_TopLeft.x;
|
||||
UniverseDisplayTopLeft.y -= UniverseDisplayDimension.y + Padding.y;
|
||||
}
|
||||
|
||||
if (UniverseDisplayTopLeft.y < DisplayArea_TopLeft.y - DisplayArea_Dimension.y)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
UniverseList = UniverseList->Next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_PANEL_DMX_VIEW_H
|
||||
#endif // FOLDHAUS_PANEL_DMX_VIEW_H
|
|
@ -0,0 +1,200 @@
|
|||
//
|
||||
// File: foldhaus_panel_file_view.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-03-08
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_FILE_VIEW_H
|
||||
|
||||
enum file_view_mode
|
||||
{
|
||||
FileViewMode_Load,
|
||||
FileViewMode_Save,
|
||||
};
|
||||
|
||||
struct file_view_state
|
||||
{
|
||||
file_view_mode Mode;
|
||||
|
||||
gs_string WorkingDirectory;
|
||||
gs_string DisplayDirectory;
|
||||
|
||||
gs_memory_arena FileNamesArena;
|
||||
gs_file_info_array FileNames;
|
||||
|
||||
gs_file_info SelectedFile;
|
||||
};
|
||||
|
||||
internal void
|
||||
FileView_SetMode(panel* Panel, file_view_mode Mode)
|
||||
{
|
||||
file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state);
|
||||
FileViewState->Mode = Mode;
|
||||
}
|
||||
|
||||
internal void
|
||||
FileView_Exit_(panel* FileViewPanel, app_state* State, context Context)
|
||||
{
|
||||
// TODO(pjs): Free State->FileNamesArena
|
||||
|
||||
Assert(FileViewPanel->IsModalOverrideFor != 0);
|
||||
panel* ReturnTo = FileViewPanel->IsModalOverrideFor;
|
||||
if (ReturnTo->ModalOverrideCB)
|
||||
{
|
||||
ReturnTo->ModalOverrideCB(FileViewPanel, State, Context);
|
||||
}
|
||||
Panel_PopModalOverride(ReturnTo, &State->PanelSystem);
|
||||
}
|
||||
|
||||
global input_command* FileView_Commands = 0;
|
||||
s32 FileView_CommandsCount = 0;
|
||||
|
||||
internal void
|
||||
FileView_UpdateWorkingDirectory(gs_const_string WorkingDirectory, file_view_state* State, context Context)
|
||||
{
|
||||
// NOTE(pjs): make sure we're only passing valid directory paths to the
|
||||
// function
|
||||
char LastChar = WorkingDirectory.Str[WorkingDirectory.Length - 1];
|
||||
Assert(LastChar == '\\' || LastChar == '/');
|
||||
MemoryArenaClear(&State->FileNamesArena);
|
||||
|
||||
|
||||
gs_string SanitizedDir = PushString(Context.ThreadContext.Transient, WorkingDirectory.Length + 2);
|
||||
SanitizePath(WorkingDirectory, &SanitizedDir, Context.ThreadContext.Transient);
|
||||
if (SanitizedDir.Str[SanitizedDir.Length - 1] != '\\')
|
||||
{
|
||||
AppendPrintF(&SanitizedDir, "\\");
|
||||
}
|
||||
|
||||
gs_const_string SanitizedDisplayDir = SanitizedDir.ConstString;
|
||||
|
||||
gs_file_info NewWorkingDir = GetFileInfo(Context.ThreadContext.FileHandler, SanitizedDir.ConstString);
|
||||
if (NewWorkingDir.IsDirectory)
|
||||
{
|
||||
AppendPrintF(&SanitizedDir, "*");
|
||||
NullTerminate(&SanitizedDir);
|
||||
|
||||
State->FileNames = EnumerateDirectory(Context.ThreadContext.FileHandler, &State->FileNamesArena, SanitizedDir.ConstString, EnumerateDirectory_IncludeDirectories);
|
||||
|
||||
// NOTE(pjs): we might be printing from State->WorkingDirectory to State->WorkingDirectory
|
||||
// in some cases. Shouldn't be a problem but it is unnecessary
|
||||
PrintF(&State->WorkingDirectory, "%S", SanitizedDir.ConstString);
|
||||
PrintF(&State->DisplayDirectory, "%S", SanitizedDisplayDir);
|
||||
}
|
||||
}
|
||||
|
||||
GSMetaTag(panel_init);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
FileView_Init(panel* Panel, app_state* State, context Context)
|
||||
{
|
||||
// TODO: :FreePanelMemory
|
||||
file_view_state* FileViewState = PushStruct(&State->Permanent, file_view_state);
|
||||
Panel->StateMemory = StructToData(FileViewState, file_view_state);
|
||||
FileViewState->FileNamesArena = MemoryArenaCreate(MB(4), Bytes(8), Context.ThreadContext.Allocator, 0, 0, "File View - File Names Arena");
|
||||
|
||||
// TODO(pjs): this shouldn't be stored in permanent
|
||||
FileViewState->DisplayDirectory = PushString(&State->Permanent, 1024);
|
||||
FileViewState->WorkingDirectory = PushString(&State->Permanent, 1024);
|
||||
|
||||
FileView_UpdateWorkingDirectory(ConstString(".\\"), FileViewState, Context);
|
||||
}
|
||||
|
||||
GSMetaTag(panel_cleanup);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
FileView_Cleanup(panel* Panel, app_state* State)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GSMetaTag(panel_render);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state);
|
||||
|
||||
ui_PushLayout(&State->Interface, PanelBounds, LayoutDirection_TopDown, MakeString("FileView Layout"));
|
||||
{
|
||||
ui_BeginRow(&State->Interface, 3);
|
||||
{
|
||||
if (FileViewState->Mode == FileViewMode_Save)
|
||||
{
|
||||
if (ui_Button(&State->Interface, MakeString("Save")))
|
||||
{
|
||||
if (!FileViewState->SelectedFile.Path.Str)
|
||||
{
|
||||
FileViewState->SelectedFile.Path = FileViewState->DisplayDirectory.ConstString;
|
||||
}
|
||||
|
||||
FileView_Exit_(Panel, State, Context);
|
||||
}
|
||||
}
|
||||
|
||||
if (ui_Button(&State->Interface, MakeString("Exit")))
|
||||
{
|
||||
FileView_Exit_(Panel, State, Context);
|
||||
}
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
|
||||
// Header
|
||||
if (ui_TextEntry(&State->Interface, MakeString("pwd"), &FileViewState->DisplayDirectory))
|
||||
{
|
||||
// if last character is a slash, update pwd, and clear the filter string
|
||||
// otherwise update the filter string
|
||||
gs_string Pwd = FileViewState->DisplayDirectory;
|
||||
char LastChar = Pwd.Str[Pwd.Length - 1];
|
||||
if (LastChar == '\\' || LastChar == '/')
|
||||
{
|
||||
FileView_UpdateWorkingDirectory(Pwd.ConstString, FileViewState, Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// File Display
|
||||
ui_BeginList(&State->Interface, MakeString("Files"), 10, FileViewState->FileNames.Count);
|
||||
for (u32 i = 0; i < FileViewState->FileNames.Count; i++)
|
||||
{
|
||||
gs_file_info File = FileViewState->FileNames.Values[i];
|
||||
|
||||
u32 LastSlashIndex = FindLast(File.Path, File.Path.Length - 2, '\\');
|
||||
gs_const_string FileName = Substring(File.Path, LastSlashIndex + 1, File.Path.Length);
|
||||
gs_string PathString = PushString(State->Transient, FileName.Length);
|
||||
PrintF(&PathString, "%S", FileName);
|
||||
|
||||
if (ui_LayoutListButton(&State->Interface, PathString, i))
|
||||
{
|
||||
if (File.IsDirectory)
|
||||
{
|
||||
FileView_UpdateWorkingDirectory(File.Path, FileViewState, Context);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileViewState->SelectedFile = File;
|
||||
switch (FileViewState->Mode)
|
||||
{
|
||||
case FileViewMode_Load:
|
||||
{
|
||||
FileView_Exit_(Panel, State, Context);
|
||||
} break;
|
||||
|
||||
case FileViewMode_Save:
|
||||
{
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_EndList(&State->Interface);
|
||||
}
|
||||
ui_PopLayout(&State->Interface, MakeString("FileView Layout"));
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_PANEL_FILE_VIEW_H
|
||||
#endif // FOLDHAUS_PANEL_FILE_VIEW_H
|
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// File: foldhaus_panel_hierarchy.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_HIERARCHY_H
|
||||
|
||||
input_command HierarchyView_Commands[] = {{}};
|
||||
s32 HierarchyView_CommandsCount = 0;
|
||||
|
||||
GSMetaTag(panel_init);
|
||||
GSMetaTag(panel_type_hierarchy);
|
||||
internal void
|
||||
HierarchyView_Init(panel* Panel, app_state* State, context Context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GSMetaTag(panel_cleanup);
|
||||
GSMetaTag(panel_type_hierarchy);
|
||||
internal void
|
||||
HierarchyView_Cleanup(panel* Panel, app_state* State)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PANEL_MODAL_OVERRIDE_CALLBACK(LoadAssemblyCallback)
|
||||
{
|
||||
Assert(ReturningFrom->TypeIndex == PanelType_FileView);
|
||||
file_view_state* FileViewState = Panel_GetStateStruct(ReturningFrom, file_view_state);
|
||||
gs_file_info FileInfo = FileViewState->SelectedFile;
|
||||
|
||||
LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, FileInfo.Path, GlobalLogBuffer);
|
||||
}
|
||||
|
||||
GSMetaTag(panel_render);
|
||||
GSMetaTag(panel_type_hierarchy);
|
||||
internal void
|
||||
HierarchyView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
gs_string TempString = PushString(State->Transient, 256);
|
||||
|
||||
ui_PushLayout(&State->Interface, PanelBounds, LayoutDirection_TopDown, MakeString("Hierarchy Layout"));
|
||||
ui_BeginList(&State->Interface, MakeString("Hierarchy List"), 10, State->Assemblies.Count + 1);
|
||||
{
|
||||
ui_column_spec Cols[2] = {
|
||||
ui_column_spec{ UIColumnSize_Fill, 0 },
|
||||
ui_column_spec{ UIColumnSize_MaxWidth, 128 }
|
||||
};
|
||||
for (u32 i = 0; i < State->Assemblies.Count; i++)
|
||||
{
|
||||
ui_BeginRow(&State->Interface, 2, &Cols[0]);
|
||||
|
||||
assembly Assembly = State->Assemblies.Values[i];
|
||||
PrintF(&TempString, "%S", Assembly.Name);
|
||||
|
||||
ui_Label(&State->Interface, TempString);
|
||||
if (ui_Button(&State->Interface, MakeString("X")))
|
||||
{
|
||||
UnloadAssembly(i, State, Context);
|
||||
}
|
||||
|
||||
ui_EndRow(&State->Interface);
|
||||
}
|
||||
|
||||
|
||||
ui_BeginRow(&State->Interface, 2, &Cols[0]);
|
||||
ui_Label(&State->Interface, MakeString(" "));
|
||||
if (ui_Button(&State->Interface, MakeString("+ Add Assembly")))
|
||||
{
|
||||
panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context);
|
||||
FileView_SetMode(FileBrowser, FileViewMode_Load);
|
||||
Panel_PushModalOverride(Panel, FileBrowser, LoadAssemblyCallback);
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
}
|
||||
ui_EndList(&State->Interface);
|
||||
ui_PopLayout(&State->Interface, MakeString("Hierarchy Layout"));
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_PANEL_HIERARCHY_H
|
||||
#endif // FOLDHAUS_PANEL_HIERARCHY_H
|
|
@ -0,0 +1,46 @@
|
|||
/* date = April 12th 2021 4:47 pm */
|
||||
|
||||
#ifndef FOLDHAUS_PANEL_MESSAGE_LOG_H
|
||||
#define FOLDHAUS_PANEL_MESSAGE_LOG_H
|
||||
|
||||
GSMetaTag(panel_init);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
MessageLog_Init(panel* Panel, app_state* State, context Context)
|
||||
{
|
||||
}
|
||||
|
||||
GSMetaTag(panel_cleanup);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
MessageLog_Cleanup(panel* Panel, app_state* State)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GSMetaTag(panel_render);
|
||||
GSMetaTag(panel_type_file_view);
|
||||
internal void
|
||||
MessageLog_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
ui_interface* Interface = &State->Interface;
|
||||
ui_widget* Layout = ui_PushLayout(Interface, PanelBounds, LayoutDirection_TopDown, MakeString("Message Log Layout"));
|
||||
|
||||
ui_BeginList(Interface, MakeString("Message Log List"), 10, GlobalLogBuffer->EntriesCount);
|
||||
|
||||
log_buffer_iter Iter = Log_GetIter(GlobalLogBuffer);
|
||||
while (true)
|
||||
{
|
||||
log_entry* At = Iter.At;
|
||||
ui_Label(Interface, At->String);
|
||||
if (!LogIter_CanAdvance(Iter))
|
||||
{
|
||||
break;
|
||||
}
|
||||
LogIter_Advance(&Iter);
|
||||
}
|
||||
ui_EndList(Interface);
|
||||
|
||||
ui_PopLayout(Interface, MakeString("Message Log Layout"));
|
||||
}
|
||||
#endif //FOLDHAUS_PANEL_MESSAGE_LOG_H
|
|
@ -0,0 +1,360 @@
|
|||
//
|
||||
// File: foldhaus_panel_profiler.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_PROFILER_H
|
||||
|
||||
input_command ProfilerView_Commands[] = {{}};
|
||||
s32 ProfilerView_CommandsCount = 0;
|
||||
|
||||
GSMetaTag(panel_init);
|
||||
GSMetaTag(panel_type_profiler);
|
||||
internal void
|
||||
ProfilerView_Init(panel* Panel, app_state* State, context Context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GSMetaTag(panel_cleanup);
|
||||
GSMetaTag(panel_type_profiler);
|
||||
internal void
|
||||
ProfilerView_Cleanup(panel* Panel, app_state* State)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal void
|
||||
RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_widget* Layout, debug_frame* VisibleFrame, gs_memory_arena* Transient)
|
||||
{
|
||||
rect2 Bounds = ui_LayoutRemaining(*Layout);
|
||||
r32 Width = Rect2Width(Bounds);
|
||||
r32 DepthHeight = 32;
|
||||
|
||||
s64 FrameStartCycles = VisibleFrame->FrameStartCycles;
|
||||
r32 FrameTotalCycles = (r32)(VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles);
|
||||
|
||||
r32 NextThreadTop = Bounds.Max.y;
|
||||
|
||||
for (s32 t = 0; t < VisibleFrame->ThreadCount; t++)
|
||||
{
|
||||
debug_scope_record_list ThreadCalls = VisibleFrame->ThreadCalls[t];
|
||||
|
||||
gs_string String = PushString(Transient, 256);
|
||||
|
||||
r32 ThreadScopeMin = Bounds.Max.y;
|
||||
|
||||
//PrintF(&String, "Thread %d", ThreadCalls.ThreadId);
|
||||
//ui_Label(Interface, String, rect2{ThreadScopeMin);
|
||||
|
||||
r32 Hue = (r32)(t) / (r32)(VisibleFrame->ThreadCount);
|
||||
Hue += (.5f * (t % 2));
|
||||
v4 ThreadHSV = v4{ 360.0f * Hue, .5f, 1.0f, 1.0f };
|
||||
v4 ThreadRGB = HSVToRGB(ThreadHSV);
|
||||
|
||||
for (s32 i = 0; i < ThreadCalls.Count; i++)
|
||||
{
|
||||
scope_record* Record = ThreadCalls.Calls + i;
|
||||
scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash);
|
||||
s64 OffsetStart = Record->StartCycles - FrameStartCycles;
|
||||
s64 OffsetEnd = Record->EndCycles - FrameStartCycles;
|
||||
r32 PercentStart = (r32)(OffsetStart) / FrameTotalCycles;
|
||||
r32 PercentEnd = (r32)(OffsetEnd) / FrameTotalCycles;
|
||||
r32 PercentWidth = PercentEnd - PercentStart;
|
||||
|
||||
rect2 ScopeBounds = {
|
||||
v2{0, 0},
|
||||
v2{PercentWidth * Width, DepthHeight - 4},
|
||||
};
|
||||
v2 Offset = {
|
||||
Bounds.Min.x + (PercentStart * Width),
|
||||
NextThreadTop - ((Record->CallDepth + 1) * DepthHeight)
|
||||
};
|
||||
ScopeBounds = Rect2Translate(ScopeBounds, Offset);
|
||||
ThreadScopeMin = Min(ScopeBounds.Min.y, ThreadScopeMin);
|
||||
|
||||
if (Rect2Width(ScopeBounds) >= 1)
|
||||
{
|
||||
v4 Color = ThreadRGB;
|
||||
if (PointIsInRect(ScopeBounds, Interface->Mouse.Pos))
|
||||
{
|
||||
Color = GreenV4;
|
||||
|
||||
ui_BeginMousePopup(Interface, rect2{ 25, 25, 300, 57 }, LayoutDirection_TopDown, MakeString("Hover"));
|
||||
{
|
||||
s64 Cycles = (Record->EndCycles - Record->StartCycles);
|
||||
r32 PercentFrame = (r32)(Cycles) / FrameTotalCycles;
|
||||
PrintF(&String, "%S : %.2f%% frame | %dcy",
|
||||
Name->Name,
|
||||
PercentFrame,
|
||||
Cycles);
|
||||
ui_Label(Interface, String);
|
||||
}
|
||||
ui_EndMousePopup(Interface);
|
||||
}
|
||||
|
||||
ui_FillRect(Interface, ScopeBounds, Color);
|
||||
ui_OutlineRect(Interface, ScopeBounds, 1, BlackV4);
|
||||
}
|
||||
}
|
||||
|
||||
NextThreadTop = ThreadScopeMin;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
RenderProfiler_ListVisualization(ui_interface* Interface, ui_widget* Layout, debug_frame* VisibleFrame, gs_memory_arena* Memory)
|
||||
{
|
||||
char Backbuffer[256];
|
||||
gs_string String = MakeString(Backbuffer, 0, 256);
|
||||
|
||||
ui_column_spec ColumnWidths[] = {
|
||||
{ UIColumnSize_Fixed, 256 },
|
||||
{ UIColumnSize_Fixed, 128 },
|
||||
{ UIColumnSize_Fixed, 128 },
|
||||
{ UIColumnSize_Fixed, 128 },
|
||||
{ UIColumnSize_Fixed, 128 }};
|
||||
ui_BeginRow(Interface, 5, &ColumnWidths[0]);
|
||||
{
|
||||
ui_Label(Interface, MakeString("Procedure"));
|
||||
ui_Label(Interface, MakeString("% Frame"));
|
||||
ui_Label(Interface, MakeString("Seconds"));
|
||||
ui_Label(Interface, MakeString("Cycles"));
|
||||
ui_Label(Interface, MakeString("Calls"));
|
||||
}
|
||||
ui_EndRow(Interface);
|
||||
|
||||
s32 CountedScopes = 0;
|
||||
for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++)
|
||||
{
|
||||
scope_name NameEntry = VisibleFrame->ScopeNamesHash[n];
|
||||
if (NameEntry.Hash != 0)
|
||||
{
|
||||
CountedScopes += 1;
|
||||
}
|
||||
}
|
||||
|
||||
ui_BeginList(Interface, MakeString("Scope List"), 10, CountedScopes);
|
||||
ui_BeginRow(Interface, 5, &ColumnWidths[0]);
|
||||
for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++)
|
||||
{
|
||||
scope_name NameEntry = VisibleFrame->ScopeNamesHash[n];
|
||||
if (NameEntry.Hash != 0)
|
||||
{
|
||||
collated_scope_record* CollatedRecord = VisibleFrame->CollatedScopes + n;
|
||||
|
||||
PrintF(&String, "%S", NameEntry.Name);
|
||||
ui_Label(Interface, String);
|
||||
|
||||
PrintF(&String, "%f%%", CollatedRecord->PercentFrameTime);
|
||||
ui_Label(Interface, String);
|
||||
|
||||
PrintF(&String, "%fs", CollatedRecord->TotalSeconds);
|
||||
ui_Label(Interface, String);
|
||||
|
||||
PrintF(&String, "%dcy", CollatedRecord->TotalCycles);
|
||||
ui_Label(Interface, String);
|
||||
|
||||
PrintF(&String, "%d", CollatedRecord->CallCount);
|
||||
ui_Label(Interface, String);
|
||||
}
|
||||
}
|
||||
ui_EndRow(Interface);
|
||||
ui_EndList(Interface);
|
||||
}
|
||||
|
||||
struct mem_amt
|
||||
{
|
||||
u64 OrigSize;
|
||||
r64 Size;
|
||||
char* Units;
|
||||
};
|
||||
|
||||
internal mem_amt
|
||||
GetMemAmt (u64 BytesCount)
|
||||
{
|
||||
mem_amt Result = {};
|
||||
Result.OrigSize = BytesCount;
|
||||
Result.Size = (r64)BytesCount;
|
||||
Result.Units = "bytes";
|
||||
|
||||
u32 i = 0;
|
||||
char* UnitList[] = { "kb", "mb", "gb", "tb" };
|
||||
while (Result.Size > 1024) {
|
||||
Result.Size /= 1024.0;
|
||||
Result.Units = UnitList[i++];
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
RenderProfiler_MemoryView(ui_interface* Interface, ui_widget* Layout, app_state* State, context Context, gs_memory_arena* Memory)
|
||||
{
|
||||
gs_debug_allocations_list* DA = Context.ThreadContext.Allocator.DEBUGAllocList;
|
||||
|
||||
gs_string TempString = PushString(State->Transient, 256);
|
||||
|
||||
mem_amt MemFootprint = GetMemAmt(DA->AllocationsSizeTotal);
|
||||
u64 AllocCount = DA->AllocationsCount;
|
||||
|
||||
PrintF(&TempString, "Total Memory Size: %.2f %s | Allocations: %lld", MemFootprint.Size, MemFootprint.Units, AllocCount);
|
||||
ui_Label(Interface, TempString);
|
||||
|
||||
ui_column_spec ColumnWidths[] = {
|
||||
{ UIColumnSize_Fill, 0 },
|
||||
{ UIColumnSize_Fixed,256 },
|
||||
};
|
||||
ui_BeginRow(Interface, 2, &ColumnWidths[0]);
|
||||
{
|
||||
ui_Label(Interface, MakeString("Location"));
|
||||
ui_Label(Interface, MakeString("Alloc Size"));
|
||||
}
|
||||
ui_EndRow(Interface);
|
||||
|
||||
ui_BeginList(Interface, MakeString("Alloc List"), 10, DA->AllocationsCount);
|
||||
ui_BeginRow(Interface, 2, &ColumnWidths[0]);
|
||||
|
||||
for (gs_debug_memory_allocation* A = DA->Root;
|
||||
A && A->Next != 0;
|
||||
A = A->Next)
|
||||
{
|
||||
gs_const_string Str = ConstString(A->Loc.File);
|
||||
u64 LastSlash = FindLastFromSet(Str, "\\/");
|
||||
gs_const_string JustFileName = Substring(Str, LastSlash + 1, Str.Length);
|
||||
PrintF(&TempString, "%s:%s(%d)", JustFileName.Str, A->Loc.Function, A->Loc.Line);
|
||||
ui_Label(Interface, TempString);
|
||||
|
||||
mem_amt Amt = GetMemAmt(A->Size);
|
||||
|
||||
PrintF(&TempString, "%.2f %s", Amt.Size, Amt.Units);
|
||||
ui_Label(Interface, TempString);
|
||||
}
|
||||
ui_EndRow(Interface);
|
||||
ui_EndList(Interface);
|
||||
}
|
||||
|
||||
GSMetaTag(panel_render);
|
||||
GSMetaTag(panel_type_profiler);
|
||||
internal void
|
||||
ProfilerView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
gs_memory_arena* Memory = State->Transient;
|
||||
gs_string String = PushString(Memory, 256);
|
||||
|
||||
v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 };
|
||||
|
||||
r32 FrameListHeight = 64;
|
||||
rect2 FrameListBounds, ProcListBounds;
|
||||
RectHSplitAtDistanceFromTop(PanelBounds, FrameListHeight, &FrameListBounds, &ProcListBounds);
|
||||
rect2 FrameListInner = RectInset(FrameListBounds, 4);
|
||||
|
||||
s32 FramesToDisplay = DEBUG_FRAME_COUNT;
|
||||
if (FramesToDisplay != 0)
|
||||
{
|
||||
r32 SingleFrameStep = Rect2Width(FrameListInner) / FramesToDisplay;
|
||||
r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2);
|
||||
|
||||
ui_OutlineRect(&State->Interface, FrameListBounds, 2, WhiteV4);
|
||||
if (MouseButtonHeldDown(Context.Mouse.LeftButtonState))
|
||||
{
|
||||
if (PointIsInRect(FrameListBounds, Context.Mouse.Pos))
|
||||
{
|
||||
v2 LocalMouse = Rect2GetRectLocalPoint(FrameListBounds, Context.Mouse.Pos);
|
||||
s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep);
|
||||
if (ClosestFrameIndex >= 0 && ClosestFrameIndex < FramesToDisplay)
|
||||
{
|
||||
GlobalDebugServices->RecordFrames = false;
|
||||
GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rect2 FrameBounds = MakeRect2MinDim(FrameListInner.Min, v2{SingleFrameWidth, Rect2Height(FrameListInner)});
|
||||
for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++)
|
||||
{
|
||||
rect2 PositionedFrameBounds = Rect2TranslateX(FrameBounds, F * SingleFrameStep);
|
||||
s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F);
|
||||
if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; }
|
||||
v4 Color = FrameColors[Clamp(0, FramesAgo, 3)];
|
||||
ui_FillRect(&State->Interface, PositionedFrameBounds, Color);
|
||||
}
|
||||
}
|
||||
|
||||
ui_widget* Layout = ui_PushLayout(&State->Interface, ProcListBounds, LayoutDirection_TopDown, MakeString("Profiler Layout"));
|
||||
|
||||
debug_frame* VisibleFrame = GetLastDebugFrame(GlobalDebugServices);
|
||||
if (VisibleFrame)
|
||||
{
|
||||
ui_BeginRow(&State->Interface, 4);
|
||||
{
|
||||
s64 FrameStartCycles = VisibleFrame->FrameStartCycles;
|
||||
s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles;
|
||||
u32 CurrentDebugFrame = GlobalDebugServices->CurrentDebugFrame - 1;
|
||||
PrintF(&String, "Frame %d", CurrentDebugFrame);
|
||||
ui_Label(&State->Interface, String);
|
||||
|
||||
PrintF(&String, "Total Cycles: %lld", FrameTotalCycles);
|
||||
ui_Label(&State->Interface, String);
|
||||
|
||||
// NOTE(NAME): Skipping a space for aesthetic reasons, not functional, and could
|
||||
// be removed, or used for something else
|
||||
ui_ReserveBounds(&State->Interface, Layout, true);
|
||||
|
||||
if (ui_Button(&State->Interface, MakeString("Resume Recording")))
|
||||
{
|
||||
GlobalDebugServices->RecordFrames = true;
|
||||
}
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
}
|
||||
|
||||
ui_BeginRow(&State->Interface, 8);
|
||||
{
|
||||
if (ui_Button(&State->Interface, MakeString("Profiler")))
|
||||
{
|
||||
GlobalDebugServices->Interface.FrameView = DebugUI_Profiler;
|
||||
}
|
||||
if (ui_Button(&State->Interface, MakeString("List View")))
|
||||
{
|
||||
GlobalDebugServices->Interface.FrameView = DebugUI_ScopeList;
|
||||
}
|
||||
if (ui_Button(&State->Interface, MakeString("Memory")))
|
||||
{
|
||||
GlobalDebugServices->Interface.FrameView = DebugUI_MemoryView;
|
||||
}
|
||||
}
|
||||
ui_EndRow(&State->Interface);
|
||||
|
||||
switch (GlobalDebugServices->Interface.FrameView)
|
||||
{
|
||||
case DebugUI_Profiler:
|
||||
{
|
||||
if (VisibleFrame)
|
||||
{
|
||||
RenderProfiler_ScopeVisualization(&State->Interface, Layout, VisibleFrame, Memory);
|
||||
}
|
||||
}break;
|
||||
|
||||
case DebugUI_ScopeList:
|
||||
{
|
||||
if (VisibleFrame)
|
||||
{
|
||||
RenderProfiler_ListVisualization(&State->Interface, Layout, VisibleFrame, Memory);
|
||||
}
|
||||
}break;
|
||||
|
||||
case DebugUI_MemoryView:
|
||||
{
|
||||
RenderProfiler_MemoryView(&State->Interface, Layout, State, Context, Memory);
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
|
||||
ui_PopLayout(&State->Interface, MakeString("Profiler Layout"));
|
||||
}
|
||||
|
||||
|
||||
#define FOLDHAUS_PANEL_PROFILER_H
|
||||
#endif // FOLDHAUS_PANEL_PROFILER_H
|
|
@ -0,0 +1,244 @@
|
|||
//
|
||||
// File: foldhaus_panel_sculpture_view.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_SCULPTURE_VIEW_H
|
||||
|
||||
// Definitions
|
||||
|
||||
#define PIXEL_TO_WORLD_SCALE 0.01f
|
||||
|
||||
//
|
||||
|
||||
struct sculpture_view_panel_state
|
||||
{
|
||||
camera Camera;
|
||||
};
|
||||
|
||||
// 3D Mouse View
|
||||
|
||||
OPERATION_STATE_DEF(mouse_rotate_view_operation_state)
|
||||
{
|
||||
v4 CameraStartPos;
|
||||
camera* Camera;
|
||||
};
|
||||
|
||||
OPERATION_RENDER_PROC(Update3DViewMouseRotate)
|
||||
{
|
||||
mouse_rotate_view_operation_state* OpState = (mouse_rotate_view_operation_state*)Operation.OpStateMemory;
|
||||
|
||||
v2 TotalDeltaPos = Mouse.Pos - Mouse.DownPos;
|
||||
|
||||
m44 XRotation = M44RotationX(-TotalDeltaPos.y * PIXEL_TO_WORLD_SCALE);
|
||||
m44 YRotation = M44RotationY(TotalDeltaPos.x * PIXEL_TO_WORLD_SCALE);
|
||||
m44 Combined = XRotation * YRotation;
|
||||
|
||||
OpState->Camera->Position = (Combined * OpState->CameraStartPos).xyz;
|
||||
}
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(End3DViewMouseRotate)
|
||||
{
|
||||
DeactivateCurrentOperationMode(&State->Modes);
|
||||
}
|
||||
|
||||
input_command MouseRotateViewCommands [] = {
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Ended, End3DViewMouseRotate},
|
||||
};
|
||||
|
||||
FOLDHAUS_INPUT_COMMAND_PROC(Begin3DViewMouseRotate)
|
||||
{
|
||||
sculpture_view_panel_state* PanelState = Panel_GetStateStruct(Panel, sculpture_view_panel_state);
|
||||
|
||||
operation_mode* RotateViewMode = ActivateOperationModeWithCommands(&State->Modes, MouseRotateViewCommands, Update3DViewMouseRotate);
|
||||
mouse_rotate_view_operation_state* OpState = CreateOperationState(RotateViewMode,
|
||||
&State->Modes,
|
||||
mouse_rotate_view_operation_state);
|
||||
OpState->CameraStartPos = ToV4Point(PanelState->Camera.Position);
|
||||
OpState->Camera = &PanelState->Camera;
|
||||
}
|
||||
|
||||
// ----------------
|
||||
|
||||
GSMetaTag(panel_commands);
|
||||
GSMetaTag(panel_type_sculpture_view);
|
||||
global input_command SculptureView_Commands[] = {
|
||||
{ KeyCode_MouseLeftButton, KeyCode_Invalid, Command_Began, Begin3DViewMouseRotate },
|
||||
};
|
||||
global s32 SculptureView_CommandsCount = 1;
|
||||
|
||||
GSMetaTag(panel_init);
|
||||
GSMetaTag(panel_type_sculpture_view);
|
||||
internal void
|
||||
SculptureView_Init(panel* Panel, app_state* State, context Context)
|
||||
{
|
||||
sculpture_view_panel_state* PanelState = PushStruct(&State->Permanent, sculpture_view_panel_state);
|
||||
|
||||
PanelState->Camera.FieldOfView = 45.0f;
|
||||
PanelState->Camera.AspectRatio = RectAspectRatio(State->WindowBounds);
|
||||
PanelState->Camera.Near = .1f;
|
||||
PanelState->Camera.Far = 800.0f;
|
||||
PanelState->Camera.Position = v3{0, 0, 400};
|
||||
PanelState->Camera.LookAt = v3{0, 0, 0};
|
||||
|
||||
Panel->StateMemory = StructToData(PanelState, sculpture_view_panel_state);
|
||||
}
|
||||
|
||||
GSMetaTag(panel_cleanup);
|
||||
GSMetaTag(panel_type_sculpture_view);
|
||||
internal void
|
||||
SculptureView_Cleanup(panel* Panel, app_state* State)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct draw_leds_job_data
|
||||
{
|
||||
v4 CameraPosition;
|
||||
led_buffer LedBuffer;
|
||||
s32 StartIndex;
|
||||
s32 OnePastLastIndex;
|
||||
render_quad_batch_constructor* Batch;
|
||||
quad_batch_constructor_reserved_range BatchReservedRange;
|
||||
r32 LEDHalfWidth;
|
||||
};
|
||||
|
||||
internal void
|
||||
DrawLedsInBuffer(led_buffer LedBuffer, s32 StartIndex, s32 OnePastLastIndex, render_quad_batch_constructor* Batch, quad_batch_constructor_reserved_range ReservedRange, r32 LedHalfWidth)
|
||||
{
|
||||
s32 TrisUsed = 0;
|
||||
|
||||
v4 P0_In = v4{-LedHalfWidth, -LedHalfWidth, 0, 1};
|
||||
v4 P1_In = v4{LedHalfWidth, -LedHalfWidth, 0, 1};
|
||||
v4 P2_In = v4{LedHalfWidth, LedHalfWidth, 0, 1};
|
||||
v4 P3_In = v4{-LedHalfWidth, LedHalfWidth, 0, 1};
|
||||
|
||||
v2 UV0 = v2{0, 0};
|
||||
v2 UV1 = v2{1, 0};
|
||||
v2 UV2 = v2{1, 1};
|
||||
v2 UV3 = v2{0, 1};
|
||||
|
||||
Assert(OnePastLastIndex <= (s32)LedBuffer.LedCount);
|
||||
for (s32 LedIndex = StartIndex; LedIndex < OnePastLastIndex; LedIndex++)
|
||||
{
|
||||
pixel PixelColor = LedBuffer.Colors[LedIndex];
|
||||
v4 Color = v4{PixelColor.R / 255.f, PixelColor.G / 255.f, PixelColor.B / 255.f, 1.0f};
|
||||
|
||||
v4 Position = LedBuffer.Positions[LedIndex];
|
||||
v4 PositionOffset = ToV4Vec(Position.xyz);
|
||||
v4 P0 = P0_In + PositionOffset;
|
||||
v4 P1 = P1_In + PositionOffset;
|
||||
v4 P2 = P2_In + PositionOffset;
|
||||
v4 P3 = P3_In + PositionOffset;
|
||||
|
||||
SetTri3DInBatch(Batch, ReservedRange.Start + TrisUsed++, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color);
|
||||
SetTri3DInBatch(Batch, ReservedRange.Start + TrisUsed++, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawLEDsInBufferRangeJob (gs_thread_context Context, gs_data JobData)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
draw_leds_job_data* Data = (draw_leds_job_data*)JobData.Memory;
|
||||
DrawLedsInBuffer(Data->LedBuffer, Data->StartIndex, Data->OnePastLastIndex, Data->Batch, Data->BatchReservedRange, Data->LEDHalfWidth);
|
||||
}
|
||||
|
||||
internal void
|
||||
DrawQuad(render_command_buffer* RenderBuffer, v4 C, r32 Rad, v4 Color)
|
||||
{
|
||||
v4 P0 = C + v4{-Rad,-Rad,0,0};
|
||||
v4 P1 = C + v4{ Rad,-Rad,0,0};
|
||||
v4 P2 = C + v4{ Rad,Rad,0,0};
|
||||
v4 P3 = C + v4{ -Rad,Rad,0,0};
|
||||
PushRenderQuad3D(RenderBuffer, P0, P1, P2, P3, Color);
|
||||
}
|
||||
|
||||
internal v2
|
||||
SculptureView_WorldToScreenPosition(v4 WorldPosition, camera Camera, rect2 PanelBounds)
|
||||
{
|
||||
v2 Result = {0};
|
||||
|
||||
r32 PanelW = Rect2Width(PanelBounds);
|
||||
r32 PanelH = Rect2Height(PanelBounds);
|
||||
|
||||
m44 Matrix = GetCameraPerspectiveProjectionMatrix(Camera) * GetCameraModelViewMatrix(Camera);
|
||||
v4 WorldPos = Matrix * WorldPosition;
|
||||
|
||||
// this is the Perspective Divide
|
||||
v2 ProjectedPos = WorldPos.xy / WorldPos.w;
|
||||
|
||||
// Projection gets us in a range [-1, 1], and we want [0, width]
|
||||
ProjectedPos.x = ((ProjectedPos.x / 2) * PanelW) + (PanelW / 2);
|
||||
ProjectedPos.y = ((ProjectedPos.y / 2) * PanelH) + (PanelH / 2);
|
||||
|
||||
Result = ProjectedPos + PanelBounds.Min;
|
||||
return Result;
|
||||
}
|
||||
|
||||
GSMetaTag(panel_render);
|
||||
GSMetaTag(panel_type_sculpture_view);
|
||||
internal void
|
||||
SculptureView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||
{
|
||||
DEBUG_TRACK_SCOPE(RenderSculpture);
|
||||
sculpture_view_panel_state* PanelState = Panel_GetStateStruct(Panel, sculpture_view_panel_state);
|
||||
PanelState->Camera.AspectRatio = RectAspectRatio(PanelBounds);
|
||||
|
||||
PushRenderPerspective(RenderBuffer, PanelBounds, PanelState->Camera);
|
||||
|
||||
u32 MaxLEDsPerJob = 2048;
|
||||
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal);
|
||||
|
||||
u32 FocusPixel = 100;
|
||||
|
||||
for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++)
|
||||
{
|
||||
led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, BufferIndex);
|
||||
u32 JobsNeeded = U32DivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob);
|
||||
u32 NextLEDIndex = 0;
|
||||
for (u32 Job = 0; Job < JobsNeeded; Job++)
|
||||
{
|
||||
gs_data Data = PushSize(State->Transient, sizeof(draw_leds_job_data));
|
||||
draw_leds_job_data* JobData = (draw_leds_job_data*)Data.Memory;
|
||||
JobData->LedBuffer = *LedBuffer;
|
||||
JobData->StartIndex = NextLEDIndex;
|
||||
JobData->OnePastLastIndex = Min(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount);
|
||||
s32 JobLedCount = JobData->OnePastLastIndex - JobData->StartIndex;
|
||||
JobData->Batch = &RenderLEDsBatch;
|
||||
JobData->BatchReservedRange = ReserveRangeInQuadConstructor(JobData->Batch, JobLedCount * 2);
|
||||
JobData->LEDHalfWidth = .5f;
|
||||
JobData->CameraPosition = ToV4Point(PanelState->Camera.Position);
|
||||
#if 1
|
||||
Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue, (thread_proc*)DrawLEDsInBufferRangeJob, Data, ConstString("Sculpture Draw LEDS"));
|
||||
#else
|
||||
DrawLedsInBuffer(JobData->LedBuffer, JobData->StartIndex, JobData->OnePastLastIndex, JobData->Batch, JobData->BatchReservedRange, JobData->LEDHalfWidth);
|
||||
#endif
|
||||
NextLEDIndex = JobData->OnePastLastIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(Peter): I don't like the fact that setting an orthographic view inside a panel render function
|
||||
// needs to relyon the window bounds rather than the panel bounds. Ideally the panel only needs to know where
|
||||
// itself is, and nothing else.
|
||||
PushRenderOrthographic(RenderBuffer, State->WindowBounds);
|
||||
if (State->Assemblies.Count > 0)
|
||||
{
|
||||
assembly Assembly = State->Assemblies.Values[0];
|
||||
led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex);
|
||||
|
||||
v4 LedPosition = LedBuffer->Positions[FocusPixel];
|
||||
v2 LedOnScreenPosition = SculptureView_WorldToScreenPosition(LedPosition, PanelState->Camera, PanelBounds);
|
||||
|
||||
gs_string Tempgs_string = PushString(State->Transient, 256);
|
||||
PrintF(&Tempgs_string, "Hot Id: %u, ZIndex: %u | Active Id: %u", State->Interface.HotWidget.Id,
|
||||
State->Interface.HotWidget.ZIndex,State->Interface.ActiveWidget.Id);
|
||||
DrawString(RenderBuffer, Tempgs_string, State->Interface.Style.Font, v2{PanelBounds.Min.x + 100, PanelBounds.Max.y - 200}, WhiteV4, -1, GreenV4);
|
||||
|
||||
}
|
||||
Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext);
|
||||
}
|
||||
|
||||
#define FOLDHAUS_PANEL_SCULPTURE_VIEW_H
|
||||
#endif // FOLDHAUS_PANEL_SCULPTURE_VIEW_H
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// File: foldhaus_panel_types.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-10-17
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_TYPES_CPP
|
||||
global s32 GlobalPanelDefsCount = 8;
|
||||
global panel_definition GlobalPanelDefs[] = {
|
||||
{ "File View", 9, FileView_Init, FileView_Cleanup, FileView_Render, FileView_Commands, FileView_CommandsCount },
|
||||
{ "Sculpture View", 14, SculptureView_Init, SculptureView_Cleanup, SculptureView_Render, SculptureView_Commands, SculptureView_CommandsCount },
|
||||
{ "Animation Timeline", 18, AnimationTimeline_Init, AnimationTimeline_Cleanup, AnimationTimeline_Render, AnimationTimeline_Commands, AnimationTimeline_CommandsCount },
|
||||
{ "Dmx View", 8, DMXView_Init, DMXView_Cleanup, DMXView_Render, DMXView_Commands, DMXView_CommandsCount },
|
||||
{ "Hierarchy", 9, HierarchyView_Init, HierarchyView_Cleanup, HierarchyView_Render, HierarchyView_Commands, HierarchyView_CommandsCount },
|
||||
{ "Profiler", 8, ProfilerView_Init, ProfilerView_Cleanup, ProfilerView_Render, ProfilerView_Commands, ProfilerView_CommandsCount },
|
||||
{ "Assembly Debug", 14, AssemblyDebug_Init, AssemblyDebug_Cleanup, AssemblyDebug_Render, 0, 0 },
|
||||
{ "Message Log", 11, MessageLog_Init, MessageLog_Cleanup, MessageLog_Render, 0, 0 },
|
||||
};
|
||||
#define FOLDHAUS_PANEL_TYPES_CPP
|
||||
#endif // FOLDHAUS_PANEL_TYPES_CPP
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// File: foldhaus_panel_types.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-10-17
|
||||
//
|
||||
#ifndef FOLDHAUS_PANEL_TYPES_H
|
||||
enum panel_type {
|
||||
PanelType_FileView,
|
||||
PanelType_SculptureView,
|
||||
PanelType_AnimationTimeline,
|
||||
PanelType_DMXView,
|
||||
PanelType_HierarchyView,
|
||||
PanelType_ProfilerView,
|
||||
PanelType_AssemblyDebug,
|
||||
PanelType_MessageLog
|
||||
};
|
||||
#define FOLDHAUS_PANEL_TYPES_H
|
||||
#endif // FOLDHAUS_PANEL_TYPES_H
|
|
@ -0,0 +1,843 @@
|
|||
//
|
||||
// File: foldhaus_animation.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_ANIMATION
|
||||
|
||||
#define ANIMATION_PROC(name) void name(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
||||
typedef ANIMATION_PROC(animation_proc);
|
||||
|
||||
struct frame_range
|
||||
{
|
||||
s32 Min;
|
||||
s32 Max;
|
||||
};
|
||||
|
||||
struct animation_pattern_handle
|
||||
{
|
||||
s32 IndexPlusOne;
|
||||
};
|
||||
|
||||
// NOTE(pjs): An animation block is a time range paired with an
|
||||
// animation_pattern (see below). While a timeline's current time
|
||||
// is within the range of a block, that particular block's animation
|
||||
// will run
|
||||
struct animation_block
|
||||
{
|
||||
frame_range Range;
|
||||
animation_pattern_handle AnimationProcHandle;
|
||||
u32 Layer;
|
||||
};
|
||||
|
||||
struct animation_block_array
|
||||
{
|
||||
u32* Generations;
|
||||
animation_block* Values;
|
||||
u32 Count;
|
||||
u32 CountMax;
|
||||
};
|
||||
|
||||
enum blend_mode
|
||||
{
|
||||
BlendMode_Overwrite,
|
||||
BlendMode_Add,
|
||||
BlendMode_Multiply,
|
||||
BlendMode_Count,
|
||||
};
|
||||
|
||||
// TODO(pjs): This really doesn't belong here
|
||||
global gs_string BlendModeStrings[] = {
|
||||
MakeString("Overwrite"),
|
||||
MakeString("Add"),
|
||||
MakeString("Multiply"),
|
||||
MakeString("Count"),
|
||||
};
|
||||
|
||||
struct anim_layer
|
||||
{
|
||||
gs_string Name;
|
||||
blend_mode BlendMode;
|
||||
};
|
||||
|
||||
struct anim_layer_array
|
||||
{
|
||||
anim_layer* Values;
|
||||
u32 Count;
|
||||
u32 CountMax;
|
||||
};
|
||||
|
||||
// NOTE(pjs): An animation is a stack of layers, each of which
|
||||
// is a timeline of animation blocks.
|
||||
struct animation
|
||||
{
|
||||
gs_string Name;
|
||||
|
||||
anim_layer_array Layers;
|
||||
animation_block_array Blocks_;
|
||||
|
||||
frame_range PlayableRange;
|
||||
|
||||
// The information / path to the file where this animation is to be saved / where it is loaded from
|
||||
gs_file_info FileInfo;
|
||||
};
|
||||
|
||||
struct animation_handle
|
||||
{
|
||||
s32 Index;
|
||||
};
|
||||
|
||||
struct animation_handle_array
|
||||
{
|
||||
u32 Count;
|
||||
animation_handle* Handles;
|
||||
};
|
||||
|
||||
internal animation_handle InvalidAnimHandle () { return { -1 }; }
|
||||
internal bool IsValid (animation_handle H) { return H.Index >= 0; }
|
||||
internal void Clear (animation_handle* H) { H->Index = -1; }
|
||||
internal bool AnimHandlesAreEqual (animation_handle A, animation_handle B)
|
||||
{
|
||||
return A.Index == B.Index;
|
||||
}
|
||||
|
||||
struct animation_array
|
||||
{
|
||||
animation* Values;
|
||||
u32 Count;
|
||||
u32 CountMax;
|
||||
};
|
||||
|
||||
struct animation_layer_frame
|
||||
{
|
||||
animation_block Hot;
|
||||
bool HasHot;
|
||||
|
||||
animation_block NextHot;
|
||||
bool HasNextHot;
|
||||
|
||||
r32 NextHotOpacity;
|
||||
|
||||
blend_mode BlendMode;
|
||||
};
|
||||
|
||||
// NOTE(pjs): This is an evaluated frame - across all layers in an
|
||||
// animation, these are the blocks that need to be run
|
||||
struct animation_frame
|
||||
{
|
||||
animation_layer_frame* Layers;
|
||||
u32 LayersCount;
|
||||
};
|
||||
|
||||
enum animation_repeat_mode
|
||||
{
|
||||
AnimationRepeat_Single,
|
||||
AnimationRepeat_Loop,
|
||||
AnimationRepeat_Invalid,
|
||||
};
|
||||
|
||||
global gs_const_string AnimationRepeatModeStrings[] = {
|
||||
ConstString("Repeat Single"),
|
||||
ConstString("Loop"),
|
||||
ConstString("Invalid"),
|
||||
};
|
||||
|
||||
struct animation_fade_group
|
||||
{
|
||||
animation_handle From;
|
||||
animation_handle To;
|
||||
r32 FadeElapsed;
|
||||
r32 FadeDuration;
|
||||
};
|
||||
|
||||
#define ANIMATION_SYSTEM_LAYERS_MAX 128
|
||||
#define ANIMATION_SYSTEM_BLOCKS_MAX 128
|
||||
struct animation_system
|
||||
{
|
||||
gs_memory_arena* Storage;
|
||||
animation_array Animations;
|
||||
|
||||
animation_repeat_mode RepeatMode;
|
||||
animation_handle_array Playlist;
|
||||
u32 PlaylistAt;
|
||||
r32 PlaylistFadeTime;
|
||||
|
||||
// NOTE(Peter): The frame currently being displayed/processed. you
|
||||
// can see which frame you're on by looking at the time slider on the timeline
|
||||
// panel
|
||||
animation_fade_group ActiveFadeGroup;
|
||||
|
||||
r32 SecondsOnCurrentFrame;
|
||||
s32 CurrentFrame;
|
||||
s32 LastUpdatedFrame;
|
||||
r32 SecondsPerFrame;
|
||||
b32 TimelineShouldAdvance;
|
||||
u32 UpdatesThisFrame;
|
||||
|
||||
// Settings
|
||||
bool Multithreaded;
|
||||
};
|
||||
|
||||
// NOTE(pjs): A Pattern is a named procedure which can be used as
|
||||
// an element of an animation. Patterns are sequenced on a timeline
|
||||
// and blended via layers to create an animation
|
||||
struct animation_pattern
|
||||
{
|
||||
char* Name;
|
||||
s32 NameLength;
|
||||
animation_proc* Proc;
|
||||
bool Multithreaded;
|
||||
};
|
||||
|
||||
struct animation_pattern_array
|
||||
{
|
||||
animation_pattern* Values;
|
||||
u32 Count;
|
||||
u32 CountMax;
|
||||
};
|
||||
|
||||
// Serialization
|
||||
|
||||
enum animation_field
|
||||
{
|
||||
AnimField_FileIdent,
|
||||
AnimField_AnimName,
|
||||
AnimField_LayersCount,
|
||||
AnimField_BlocksCount,
|
||||
|
||||
AnimField_PlayableRange,
|
||||
AnimField_PlayableRangeMin,
|
||||
AnimField_PlayableRangeMax,
|
||||
|
||||
AnimField_LayersArray,
|
||||
AnimField_Layer,
|
||||
AnimField_LayerName,
|
||||
AnimField_LayerBlendMode,
|
||||
|
||||
AnimField_BlocksArray,
|
||||
AnimField_Block,
|
||||
AnimField_BlockFrameRange,
|
||||
AnimField_BlockFrameRangeMin,
|
||||
AnimField_BlockFrameRangeMax,
|
||||
AnimField_BlockLayerIndex,
|
||||
AnimField_BlockAnimName,
|
||||
|
||||
AnimField_Count,
|
||||
};
|
||||
|
||||
global gs_const_string AnimationFieldStrings[] = {
|
||||
ConstString("lumenarium_animation_file"), // AnimField_FileIdent
|
||||
ConstString("animation_name"),// AnimField_AnimName
|
||||
ConstString("layers_count"),// AnimField_LayersCount
|
||||
ConstString("blocks_count"),// AnimField_BlocksCount
|
||||
|
||||
ConstString("playable_range"),// AnimField_PlayableRange
|
||||
ConstString("min"),// AnimField_PlayableRangeMin
|
||||
ConstString("max"),// AnimField_PlayableRangeMax
|
||||
|
||||
ConstString("layers"),// AnimField_LayersArray
|
||||
ConstString("layer"),// AnimField_Layer
|
||||
ConstString("name"),// AnimField_LayerName
|
||||
ConstString("blend"),// AnimField_LayerBlendMode
|
||||
|
||||
ConstString("blocks"),// AnimField_BlocksArray
|
||||
ConstString("block"),// AnimField_Block
|
||||
ConstString("frame_range"),// AnimField_BlockFrameRange
|
||||
ConstString("min"),// AnimField_BlockFrameRangeMin
|
||||
ConstString("max"),// AnimField_BlockFrameRangeMax
|
||||
ConstString("layer_index"),// AnimField_BlockLayerIndex
|
||||
ConstString("animation_name"),// AnimField_BlockAnimName
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
// Patterns List
|
||||
|
||||
internal animation_pattern_array
|
||||
Patterns_Create(gs_memory_arena* Arena, s32 CountMax)
|
||||
{
|
||||
animation_pattern_array Result = {0};
|
||||
Result.CountMax = CountMax;
|
||||
Result.Values = PushArray(Arena, animation_pattern, Result.CountMax);
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define PATTERN_MULTITHREADED true
|
||||
#define PATTERN_SINGLETHREADED false
|
||||
|
||||
#define Patterns_PushPattern(array, proc, multithread) \
|
||||
Patterns_PushPattern_((array), (proc), Stringify(proc), sizeof(Stringify(proc)) - 1, (multithread))
|
||||
|
||||
internal void
|
||||
Patterns_PushPattern_(animation_pattern_array* Array, animation_proc* Proc, char* Name, u32 NameLength, bool Multithreaded)
|
||||
{
|
||||
Assert(Array->Count < Array->CountMax);
|
||||
|
||||
animation_pattern Pattern = {0};
|
||||
Pattern.Name = Name;
|
||||
Pattern.NameLength = NameLength;
|
||||
Pattern.Proc = Proc;
|
||||
Pattern.Multithreaded = Multithreaded;
|
||||
|
||||
Array->Values[Array->Count++] = Pattern;
|
||||
}
|
||||
|
||||
internal animation_pattern_handle
|
||||
Patterns_IndexToHandle(s32 Index)
|
||||
{
|
||||
animation_pattern_handle Result = {};
|
||||
Result.IndexPlusOne = Index + 1;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
IsValid(animation_pattern_handle Handle)
|
||||
{
|
||||
bool Result = Handle.IndexPlusOne > 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal animation_pattern
|
||||
Patterns_GetPattern(animation_pattern_array Patterns, animation_pattern_handle Handle)
|
||||
{
|
||||
animation_pattern Result = {0};
|
||||
if (Handle.IndexPlusOne > 0)
|
||||
{
|
||||
u32 Index = Handle.IndexPlusOne - 1;
|
||||
Assert(Index < Patterns.Count);
|
||||
Result = Patterns.Values[Index];
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
// Anim Block Array
|
||||
|
||||
internal animation_block_array
|
||||
AnimBlockArray_Create(gs_memory_arena* Storage, u32 CountMax)
|
||||
{
|
||||
animation_block_array Result = {0};
|
||||
Result.CountMax = Max(CountMax, 32);
|
||||
Result.Values = PushArray(Storage, animation_block, Result.CountMax);
|
||||
Result.Generations = PushArray(Storage, u32, Result.CountMax);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal handle
|
||||
AnimBlockArray_Push(animation_block_array* Array, animation_block Value)
|
||||
{
|
||||
Assert(Array->Count < Array->CountMax);
|
||||
handle Result = {0};
|
||||
Result.Index = Array->Count++;
|
||||
// NOTE(pjs): pre-increment so that generation 0 is always invalid
|
||||
Result.Generation = ++Array->Generations[Result.Index];
|
||||
|
||||
Array->Values[Result.Index] = Value;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimBlockArray_Remove(animation_block_array* Array, handle Handle)
|
||||
{
|
||||
Assert(Handle.Index < Array->Count);
|
||||
Assert(Handle_IsValid(Handle));
|
||||
Array->Generations[Handle.Index]++;
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimBlockArray_RemoveAt(animation_block_array* Array, u32 Index)
|
||||
{
|
||||
Assert(Index < Array->Count);
|
||||
|
||||
handle Handle = {};
|
||||
Handle.Index = Index;
|
||||
Handle.Generation = Array->Generations[Index];
|
||||
AnimBlockArray_Remove(Array, Handle);
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
// Anim Layers Array
|
||||
|
||||
internal anim_layer_array
|
||||
AnimLayerArray_Create(gs_memory_arena* Storage, u32 CountMax)
|
||||
{
|
||||
anim_layer_array Result = {0};
|
||||
Result.CountMax = Max(CountMax, 32);
|
||||
Result.Values = PushArray(Storage, anim_layer, Result.CountMax);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
AnimLayerArray_Push(anim_layer_array* Array, anim_layer Value)
|
||||
{
|
||||
Assert(Array->Count < Array->CountMax);
|
||||
u32 Index = Array->Count++;
|
||||
Array->Values[Index] = Value;
|
||||
return Index;
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimLayerArray_Remove(anim_layer_array* Array, u32 Index)
|
||||
{
|
||||
Assert(Index < Array->Count);
|
||||
for (u32 i = Index; i < Array->Count - 1; i++)
|
||||
{
|
||||
Array->Values[i] = Array->Values[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
// Animation Array
|
||||
|
||||
internal animation_array
|
||||
AnimationArray_Create(gs_memory_arena* Storage, u32 CountMax)
|
||||
{
|
||||
animation_array Result = {0};
|
||||
Result.CountMax = CountMax;
|
||||
Result.Values = PushArray(Storage, animation, Result.CountMax);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal animation_handle
|
||||
AnimationArray_Push(animation_array* Array, animation Value)
|
||||
{
|
||||
Assert(Array->Count < Array->CountMax);
|
||||
animation_handle Result = {0};
|
||||
Result.Index = Array->Count++;
|
||||
Array->Values[Result.Index] = Value;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal animation*
|
||||
AnimationArray_Get(animation_array Array, animation_handle Handle)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
animation* Result = 0;
|
||||
if (IsValid(Handle) && Handle.Index < (s32)Array.Count)
|
||||
{
|
||||
Result = Array.Values + Handle.Index;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal animation*
|
||||
AnimationArray_GetSafe(animation_array Array, animation_handle Handle)
|
||||
{
|
||||
Assert(IsValid(Handle));
|
||||
Assert(Handle.Index < (s32)Array.Count);
|
||||
return AnimationArray_Get(Array, Handle);
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
// Animation
|
||||
|
||||
typedef struct animation_desc
|
||||
{
|
||||
u32 NameSize;
|
||||
char* Name;
|
||||
|
||||
u32 LayersCount;
|
||||
u32 BlocksCount;
|
||||
|
||||
u32 MinFrames;
|
||||
u32 MaxFrames;
|
||||
} animation_desc;
|
||||
|
||||
internal animation
|
||||
Animation_Create(animation_desc Desc, animation_system* System)
|
||||
{
|
||||
animation Result = {};
|
||||
u32 NameLen = Desc.NameSize;
|
||||
if (Desc.Name)
|
||||
{
|
||||
NameLen = Max(CStringLength(Desc.Name), NameLen);
|
||||
Result.Name = PushStringF(System->Storage, NameLen, "%s", Desc.Name);
|
||||
} else {
|
||||
Result.Name = PushStringF(System->Storage, NameLen, "[New Animation]");
|
||||
}
|
||||
|
||||
Result.Layers = AnimLayerArray_Create(System->Storage, Desc.LayersCount);
|
||||
Result.Blocks_ = AnimBlockArray_Create(System->Storage, Desc.BlocksCount);
|
||||
Result.PlayableRange.Min = Desc.MinFrames;
|
||||
Result.PlayableRange.Max = Desc.MaxFrames;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal handle
|
||||
Animation_AddBlock(animation* Animation, u32 StartFrame, s32 EndFrame, animation_pattern_handle AnimationProcHandle, u32 LayerIndex)
|
||||
{
|
||||
Assert(LayerIndex < Animation->Layers.Count);
|
||||
|
||||
animation_block NewBlock = {0};
|
||||
NewBlock.Range.Min = StartFrame;
|
||||
NewBlock.Range.Max = EndFrame;
|
||||
NewBlock.AnimationProcHandle = AnimationProcHandle;
|
||||
NewBlock.Layer = LayerIndex;
|
||||
|
||||
handle Handle = AnimBlockArray_Push(&Animation->Blocks_, NewBlock);
|
||||
return Handle;
|
||||
}
|
||||
|
||||
internal void
|
||||
Animation_RemoveBlock(animation* Animation, handle AnimHandle)
|
||||
{
|
||||
AnimBlockArray_Remove(&Animation->Blocks_, AnimHandle);
|
||||
}
|
||||
|
||||
internal animation_block*
|
||||
Animation_GetBlockFromHandle(animation* Animation, handle AnimHandle)
|
||||
{
|
||||
animation_block* Result = 0;
|
||||
|
||||
if (AnimHandle.Generation != 0 &&
|
||||
Animation->Blocks_.Generations[AnimHandle.Index] == AnimHandle.Generation)
|
||||
{
|
||||
Result = Animation->Blocks_.Values + AnimHandle.Index;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
Animation_AddLayer(animation* Animation, anim_layer Layer)
|
||||
{
|
||||
return AnimLayerArray_Push(&Animation->Layers, Layer);
|
||||
}
|
||||
|
||||
internal u32
|
||||
Animation_AddLayer (animation* Animation, gs_string Name, blend_mode BlendMode, animation_system* System)
|
||||
{
|
||||
anim_layer NewLayer = {0};
|
||||
NewLayer.Name = PushStringF(System->Storage, 256, "%S", Name);
|
||||
NewLayer.BlendMode = BlendMode;
|
||||
|
||||
return Animation_AddLayer(Animation, NewLayer);
|
||||
}
|
||||
|
||||
internal void
|
||||
Animation_RemoveLayer (animation* Animation, u32 LayerIndex)
|
||||
{
|
||||
AnimLayerArray_Remove(&Animation->Layers, LayerIndex);
|
||||
for (u32 i = Animation->Blocks_.Count - 1; i >= 0; i--)
|
||||
{
|
||||
animation_block* Block = Animation->Blocks_.Values + i;
|
||||
if (Block->Layer > LayerIndex)
|
||||
{
|
||||
Block->Layer -= 1;
|
||||
}
|
||||
else if (Block->Layer == LayerIndex)
|
||||
{
|
||||
AnimBlockArray_RemoveAt(&Animation->Blocks_, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
internal u32
|
||||
SecondsToFrames(r32 Seconds, animation_system System)
|
||||
{
|
||||
u32 Result = Seconds * (1.0f / System.SecondsPerFrame);
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline frame_range
|
||||
FrameRange_Overlap(frame_range A, frame_range B)
|
||||
{
|
||||
frame_range Result = {};
|
||||
|
||||
}
|
||||
|
||||
inline bool
|
||||
FrameIsInRange(frame_range Range, s32 Frame)
|
||||
{
|
||||
bool Result = (Frame >= Range.Min) && (Frame <= Range.Max);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
GetFrameCount(frame_range Range)
|
||||
{
|
||||
u32 Result = (u32)Max(0, Range.Max - Range.Min);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal r32
|
||||
FrameToPercentRange(s32 Frame, frame_range Range)
|
||||
{
|
||||
r32 Result = (r32)(Frame - Range.Min);
|
||||
Result = Result / GetFrameCount(Range);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
PercentToFrameInRange(r32 Percent, frame_range Range)
|
||||
{
|
||||
s32 Result = Range.Min + (s32)(Percent * GetFrameCount(Range));
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal s32
|
||||
ClampFrameToRange(s32 Frame, frame_range Range)
|
||||
{
|
||||
s32 Result = Frame;
|
||||
if (Result < Range.Min)
|
||||
{
|
||||
Result = Range.Min;
|
||||
}
|
||||
else if (Result > Range.Max)
|
||||
{
|
||||
Result = Range.Max;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
// Blocks
|
||||
|
||||
// Layers
|
||||
|
||||
// Fade Group
|
||||
|
||||
internal bool
|
||||
AnimationFadeGroup_ShouldRender (animation_fade_group FadeGroup)
|
||||
{
|
||||
return IsValid(FadeGroup.From);
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimationFadeGroup_Advance(animation_fade_group* Group)
|
||||
{
|
||||
Group->From = Group->To;
|
||||
Clear(&Group->To);
|
||||
Group->FadeElapsed = 0;
|
||||
Group->FadeDuration = 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimationFadeGroup_Update(animation_fade_group* Group, r32 DeltaTime)
|
||||
{
|
||||
if (IsValid(Group->To))
|
||||
{
|
||||
r32 FadeBefore = Group->FadeElapsed;
|
||||
Group->FadeElapsed += DeltaTime;
|
||||
|
||||
if (Group->FadeElapsed >= Group->FadeDuration)
|
||||
{
|
||||
AnimationFadeGroup_Advance(Group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimationFadeGroup_FadeTo(animation_fade_group* Group, animation_handle To, r32 Duration)
|
||||
{
|
||||
if (IsValid(Group->From))
|
||||
{
|
||||
// complete current fade if there is one in progress
|
||||
if (IsValid(Group->To))
|
||||
{
|
||||
AnimationFadeGroup_Advance(Group);
|
||||
}
|
||||
|
||||
Group->To = To;
|
||||
Group->FadeDuration = Duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
Group->From = To;
|
||||
}
|
||||
}
|
||||
|
||||
// System
|
||||
|
||||
struct animation_system_desc
|
||||
{
|
||||
gs_memory_arena* Storage;
|
||||
u32 AnimArrayCount;
|
||||
r32 SecondsPerFrame;
|
||||
};
|
||||
|
||||
internal animation_system
|
||||
AnimationSystem_Init(animation_system_desc Desc)
|
||||
{
|
||||
animation_system Result = {};
|
||||
Result.Storage = Desc.Storage;
|
||||
Result.Animations = AnimationArray_Create(Result.Storage, Desc.AnimArrayCount);
|
||||
Result.SecondsPerFrame = Desc.SecondsPerFrame;
|
||||
|
||||
Clear(&Result.ActiveFadeGroup.From);
|
||||
Clear(&Result.ActiveFadeGroup.To);
|
||||
Result.ActiveFadeGroup.FadeElapsed = 0;
|
||||
|
||||
// Settings
|
||||
Result.Multithreaded = false;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal animation*
|
||||
AnimationSystem_GetActiveAnimation(animation_system* System)
|
||||
{
|
||||
return AnimationArray_Get(System->Animations, System->ActiveFadeGroup.From);
|
||||
}
|
||||
|
||||
internal animation_frame
|
||||
AnimationSystem_CalculateAnimationFrame(animation_system* System,
|
||||
animation* Animation,
|
||||
gs_memory_arena* Arena)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
animation_frame Result = {0};
|
||||
Result.LayersCount = Animation->Layers.Count;
|
||||
Result.Layers = PushArray(Arena, animation_layer_frame, Result.LayersCount);
|
||||
ZeroArray(Result.Layers, animation_layer_frame, Result.LayersCount);
|
||||
|
||||
for (u32 l = 0; l < Animation->Layers.Count; l++)
|
||||
{
|
||||
animation_layer_frame* Layer = Result.Layers + l;
|
||||
Layer->BlendMode = Animation->Layers.Values[l].BlendMode;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < Animation->Blocks_.Count; i++)
|
||||
{
|
||||
animation_block Block = Animation->Blocks_.Values[i];
|
||||
|
||||
if (FrameIsInRange(Block.Range, System->CurrentFrame))
|
||||
{
|
||||
animation_layer_frame* Layer = Result.Layers + Block.Layer;
|
||||
if (Layer->HasHot)
|
||||
{
|
||||
// NOTE(pjs): With current implementation, we don't allow
|
||||
// animations to hvae more than 2 concurrent blocks in the
|
||||
// timeline
|
||||
Assert(!Layer->HasNextHot);
|
||||
|
||||
// NOTE(pjs): Make sure that Hot comes before NextHot
|
||||
if (Layer->Hot.Range.Min < Block.Range.Min)
|
||||
{
|
||||
Layer->NextHot = Block;
|
||||
}
|
||||
else
|
||||
{
|
||||
Layer->NextHot = Layer->Hot;
|
||||
Layer->Hot = Block;
|
||||
}
|
||||
Layer->HasNextHot = true;
|
||||
|
||||
frame_range BlendRange = {};
|
||||
BlendRange.Min = Layer->NextHot.Range.Min;
|
||||
BlendRange.Max = Layer->Hot.Range.Max;
|
||||
Layer->NextHotOpacity = FrameToPercentRange(System->CurrentFrame, BlendRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
Layer->Hot = Block;
|
||||
Layer->NextHotOpacity = 0.0f;
|
||||
Layer->HasHot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimationSystem_Update(animation_system* System, r32 DeltaTime)
|
||||
{
|
||||
if (!System->TimelineShouldAdvance) { return; }
|
||||
if (!AnimationFadeGroup_ShouldRender(System->ActiveFadeGroup)) { return; }
|
||||
|
||||
System->UpdatesThisFrame = 0;
|
||||
|
||||
AnimationFadeGroup_Update(&System->ActiveFadeGroup, DeltaTime);
|
||||
|
||||
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System);
|
||||
if (ActiveAnim)
|
||||
{
|
||||
System->SecondsOnCurrentFrame += DeltaTime;
|
||||
while (System->SecondsOnCurrentFrame > System->SecondsPerFrame)
|
||||
{
|
||||
System->CurrentFrame += 1;
|
||||
System->SecondsOnCurrentFrame -= System->SecondsPerFrame;
|
||||
System->UpdatesThisFrame += 1;
|
||||
}
|
||||
|
||||
// Loop back to the beginning
|
||||
if (System->CurrentFrame > ActiveAnim->PlayableRange.Max)
|
||||
{
|
||||
// NOTE(PS): There's no long term reason why this needs to be true
|
||||
// but I don't want to implement dealing with PlayableRanges that
|
||||
// don't start at zero right now becuse there's literally no reason
|
||||
// I can think of where that's useful.
|
||||
Assert(ActiveAnim->PlayableRange.Min == 0);
|
||||
|
||||
s32 FramesPastEnd = System->CurrentFrame;
|
||||
while (FramesPastEnd > ActiveAnim->PlayableRange.Max)
|
||||
{
|
||||
FramesPastEnd -= ActiveAnim->PlayableRange.Max;
|
||||
}
|
||||
|
||||
switch (System->RepeatMode)
|
||||
{
|
||||
case AnimationRepeat_Single:
|
||||
{
|
||||
System->CurrentFrame = 0;
|
||||
}break;
|
||||
|
||||
case AnimationRepeat_Loop:
|
||||
{
|
||||
Assert(System->Playlist.Count > 0);
|
||||
u32 NextIndex = System->PlaylistAt;
|
||||
System->PlaylistAt = (System->PlaylistAt + 1) % System->Playlist.Count;
|
||||
animation_handle Next = System->Playlist.Handles[NextIndex];
|
||||
|
||||
AnimationFadeGroup_FadeTo(&System->ActiveFadeGroup,
|
||||
Next,
|
||||
System->PlaylistFadeTime);
|
||||
System->CurrentFrame = 0;
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimationSystem_FadeToPlaylist(animation_system* System, animation_handle_array Playlist)
|
||||
{
|
||||
System->Playlist = Playlist;
|
||||
System->PlaylistAt = 0;
|
||||
|
||||
if (System->Playlist.Count > 0)
|
||||
{
|
||||
AnimationFadeGroup_FadeTo(&System->ActiveFadeGroup, Playlist.Handles[0], System->PlaylistFadeTime);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
AnimationSystem_NeedsRender(animation_system System)
|
||||
{
|
||||
bool Result = (System.CurrentFrame != System.LastUpdatedFrame);
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline r32
|
||||
AnimationSystem_GetCurrentTime(animation_system System)
|
||||
{
|
||||
r32 Result = System.CurrentFrame * System.SecondsPerFrame;
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define FOLDHAUS_ANIMATION
|
||||
#endif // FOLDHAUS_ANIMATION
|
|
@ -0,0 +1,375 @@
|
|||
//
|
||||
// File: foldhaus_animation_renderer.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-11-14
|
||||
//
|
||||
#ifndef FOLDHAUS_ANIMATION_RENDERER_CPP
|
||||
|
||||
internal pixel
|
||||
LedBlend_Overwrite(pixel PixelA, pixel PixelB, u8* UserData)
|
||||
{
|
||||
r32 MagB = (r32)(PixelB.R + PixelB.G + PixelB.B) / (255 * 3);
|
||||
|
||||
pixel Result = {};
|
||||
Result.R = (u8)LerpR32(MagB, PixelA.R, PixelB.R);
|
||||
Result.G = (u8)LerpR32(MagB, PixelA.G, PixelB.G);
|
||||
Result.B = (u8)LerpR32(MagB, PixelA.B, PixelB.B);
|
||||
|
||||
#if 0
|
||||
pixel Result = PixelB;
|
||||
if (PixelB.R == 0 &&
|
||||
PixelB.G == 0 &&
|
||||
PixelB.B == 0)
|
||||
{
|
||||
Result = PixelA;
|
||||
}
|
||||
#endif
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal pixel
|
||||
LedBlend_Lerp(pixel PixelA, pixel PixelB, u8* UserData)
|
||||
{
|
||||
r32 BOpacity = *(r32*)UserData;
|
||||
|
||||
pixel Result = {};
|
||||
|
||||
r32 AOpacity = 1.0f - BOpacity;
|
||||
Result.R = (u8)((PixelA.R * AOpacity) + (PixelB.R * BOpacity));
|
||||
Result.G = (u8)((PixelA.G * AOpacity) + (PixelB.G * BOpacity));
|
||||
Result.B = (u8)((PixelA.B * AOpacity) + (PixelB.B * BOpacity));
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal pixel
|
||||
LedBlend_Add(pixel PixelA, pixel PixelB, u8* UserData)
|
||||
{
|
||||
pixel Result = {};
|
||||
|
||||
u32 R = (u32)PixelA.R + (u32)PixelB.R;
|
||||
u32 G = (u32)PixelA.G + (u32)PixelB.G;
|
||||
u32 B = (u32)PixelA.B + (u32)PixelB.B;
|
||||
|
||||
Result.R = (u8)Min(R, (u32)255);
|
||||
Result.G = (u8)Min(G, (u32)255);
|
||||
Result.B = (u8)Min(B, (u32)255);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal pixel
|
||||
LedBlend_Multiply(pixel PixelA, pixel PixelB, u8* UserData)
|
||||
{
|
||||
pixel Result = {};
|
||||
|
||||
r32 DR = (r32)PixelA.R / 255.f;
|
||||
r32 DG = (r32)PixelA.G / 255.f;
|
||||
r32 DB = (r32)PixelA.B / 255.f;
|
||||
|
||||
r32 SR = (r32)PixelB.R / 255.f;
|
||||
r32 SG = (r32)PixelB.G / 255.f;
|
||||
r32 SB = (r32)PixelB.B / 255.f;
|
||||
|
||||
Result.R = (u8)((DR * SR) * 255.f);
|
||||
Result.G = (u8)((DG * SG) * 255.f);
|
||||
Result.B = (u8)((DB * SB) * 255.f);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal pixel
|
||||
LedBlend_Overlay(pixel PixelA, pixel PixelB, u8* UserData)
|
||||
{
|
||||
pixel Result = {};
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal led_blend_proc*
|
||||
LedBlend_GetProc(blend_mode BlendMode)
|
||||
{
|
||||
led_blend_proc* Result = 0;
|
||||
switch (BlendMode)
|
||||
{
|
||||
case BlendMode_Overwrite: { Result = LedBlend_Overwrite; }break;
|
||||
case BlendMode_Add: { Result = LedBlend_Add; }break;
|
||||
case BlendMode_Multiply: { Result = LedBlend_Multiply; }break;
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
struct pattern_args
|
||||
{
|
||||
assembly Assembly;
|
||||
gs_memory_arena* Transient;
|
||||
u8* UserData;
|
||||
};
|
||||
|
||||
struct render_anim_to_led_buffer_job_data
|
||||
{
|
||||
animation_pattern Pattern;
|
||||
led_buffer Buffer;
|
||||
led_buffer_range BufferRange;
|
||||
pattern_args PatternArgs;
|
||||
r32 SecondsIntoBlock;
|
||||
};
|
||||
|
||||
internal void
|
||||
AnimationSystem_RenderAnimationToLedBufferJob(gs_thread_context Context, gs_data Data)
|
||||
{
|
||||
render_anim_to_led_buffer_job_data JobData = *(render_anim_to_led_buffer_job_data*)Data.Memory;
|
||||
JobData.Pattern.Proc(&JobData.Buffer,
|
||||
JobData.BufferRange,
|
||||
JobData.PatternArgs.Assembly,
|
||||
JobData.SecondsIntoBlock,
|
||||
JobData.PatternArgs.Transient,
|
||||
JobData.PatternArgs.UserData);
|
||||
}
|
||||
|
||||
#define MULTITHREAD_PATTERN_RENDERING 1
|
||||
|
||||
internal void
|
||||
AnimationSystem_BeginRenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, animation_pattern_array Patterns, pattern_args PatternArgs,
|
||||
context Context)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min;
|
||||
r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame;
|
||||
|
||||
animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle);
|
||||
Assert(Pattern.Proc);
|
||||
|
||||
if (System->Multithreaded && Pattern.Multithreaded)
|
||||
{
|
||||
u32 JobsCount = 4;
|
||||
u32 LedsPerJob = Buffer->LedCount / JobsCount;
|
||||
|
||||
for (u32 i = 0; i < JobsCount; i++)
|
||||
{
|
||||
gs_data Data = PushSize(Context.ThreadContext.Transient, sizeof(render_anim_to_led_buffer_job_data));
|
||||
render_anim_to_led_buffer_job_data* JobData = (render_anim_to_led_buffer_job_data*)Data.Memory;
|
||||
JobData->Pattern = Pattern;
|
||||
JobData->Buffer = *Buffer;
|
||||
JobData->BufferRange.First = LedsPerJob * i;
|
||||
JobData->BufferRange.OnePastLast = LedsPerJob * (i + 1);
|
||||
JobData->PatternArgs = PatternArgs;
|
||||
JobData->SecondsIntoBlock = SecondsIntoBlock;
|
||||
|
||||
Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue,
|
||||
(thread_proc*)AnimationSystem_RenderAnimationToLedBufferJob,
|
||||
Data,
|
||||
ConstString("Render Pattern To Buffer"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
led_buffer_range Range = {};
|
||||
Range.First = 0;
|
||||
Range.OnePastLast = Buffer->LedCount;
|
||||
|
||||
Pattern.Proc(Buffer, Range, PatternArgs.Assembly, SecondsIntoBlock, PatternArgs.Transient, PatternArgs.UserData);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimationSystem_EndRenderBlockToLedBuffer (animation_system* System, context Context)
|
||||
{
|
||||
if (System->Multithreaded)
|
||||
{
|
||||
Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(pjs): This mirrors animation_layer_frame to account
|
||||
// for overlapping
|
||||
struct layer_led_buffer
|
||||
{
|
||||
led_buffer HotBuffer;
|
||||
led_buffer NextHotBuffer;
|
||||
};
|
||||
|
||||
internal led_buffer
|
||||
RenderAnimationToLedBuffer (animation_system* System,
|
||||
pattern_args PatternArgs,
|
||||
animation_frame CurrFrame,
|
||||
layer_led_buffer* LayerBuffers,
|
||||
led_buffer* AssemblyLedBuffer,
|
||||
animation_pattern_array Patterns,
|
||||
gs_memory_arena* Transient,
|
||||
context Context)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
led_buffer AccBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient);
|
||||
|
||||
// Create the LayerLEDBuffers
|
||||
for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++)
|
||||
{
|
||||
layer_led_buffer TempBuffer = {};
|
||||
|
||||
if (CurrFrame.Layers[Layer].HasHot)
|
||||
{
|
||||
TempBuffer.HotBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient);
|
||||
|
||||
if (CurrFrame.Layers[Layer].HasNextHot)
|
||||
{
|
||||
TempBuffer.NextHotBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient);
|
||||
}
|
||||
}
|
||||
|
||||
LayerBuffers[Layer] = TempBuffer;
|
||||
}
|
||||
|
||||
// Render Each layer's block to the appropriate temp buffer
|
||||
for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++)
|
||||
{
|
||||
animation_layer_frame LayerFrame = CurrFrame.Layers[Layer];
|
||||
if (LayerFrame.HasHot)
|
||||
{
|
||||
led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer;
|
||||
animation_block Block = LayerFrame.Hot;
|
||||
AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context);
|
||||
}
|
||||
|
||||
if (LayerFrame.HasNextHot)
|
||||
{
|
||||
led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer;
|
||||
animation_block Block = LayerFrame.NextHot;
|
||||
AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context);
|
||||
}
|
||||
|
||||
AnimationSystem_EndRenderBlockToLedBuffer(System, Context);
|
||||
}
|
||||
|
||||
// Blend together any layers that have a hot and next hot buffer
|
||||
for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++)
|
||||
{
|
||||
animation_layer_frame LayerFrame = CurrFrame.Layers[Layer];
|
||||
layer_led_buffer LayerBuffer = LayerBuffers[Layer];
|
||||
if (LayerFrame.HasNextHot)
|
||||
{
|
||||
LedBuffer_Blend(LayerBuffer.HotBuffer,
|
||||
LayerBuffer.NextHotBuffer,
|
||||
&LayerBuffer.HotBuffer,
|
||||
LedBlend_Lerp,
|
||||
(u8*)&LayerFrame.NextHotOpacity);
|
||||
}
|
||||
}
|
||||
|
||||
// Consolidate Temp Buffers back into AssemblyLedBuffer
|
||||
// We do this in reverse order so that they go from top to bottom
|
||||
for (u32 Layer = 0; Layer < CurrFrame.LayersCount; Layer++)
|
||||
{
|
||||
if (CurrFrame.Layers[Layer].HasHot)
|
||||
{
|
||||
led_blend_proc* Blend = LedBlend_GetProc(CurrFrame.Layers[Layer].BlendMode);
|
||||
LedBuffer_Blend(AccBuffer,
|
||||
LayerBuffers[Layer].HotBuffer,
|
||||
&AccBuffer,
|
||||
Blend,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
return AccBuffer;
|
||||
}
|
||||
|
||||
internal void
|
||||
AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Assemblies,
|
||||
led_system* LedSystem,
|
||||
animation_pattern_array Patterns,
|
||||
gs_memory_arena* Transient,
|
||||
context Context,
|
||||
u8* UserData)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
r32 FrameTime = AnimationSystem_GetCurrentTime(*System);
|
||||
|
||||
#if 1
|
||||
animation_array Animations = System->Animations;
|
||||
animation_fade_group FadeGroup = System->ActiveFadeGroup;
|
||||
|
||||
animation* FromAnim = AnimationArray_Get(Animations, FadeGroup.From);
|
||||
animation_frame FromFrame = AnimationSystem_CalculateAnimationFrame(System, FromAnim, Transient);
|
||||
layer_led_buffer* FromLayerBuffers = PushArray(Transient, layer_led_buffer, FromFrame.LayersCount);
|
||||
|
||||
animation* ToAnim = AnimationArray_Get(Animations, FadeGroup.To);
|
||||
animation_frame ToFrame = {0};
|
||||
layer_led_buffer* ToLayerBuffers = 0;
|
||||
if (ToAnim)
|
||||
{
|
||||
ToFrame = AnimationSystem_CalculateAnimationFrame(System, ToAnim, Transient);
|
||||
ToLayerBuffers = PushArray(Transient, layer_led_buffer, ToFrame.LayersCount);
|
||||
}
|
||||
|
||||
for (u32 AssemblyIndex = 0; AssemblyIndex < Assemblies.Count; AssemblyIndex++)
|
||||
{
|
||||
assembly Assembly = Assemblies.Values[AssemblyIndex];
|
||||
led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex);
|
||||
|
||||
pattern_args PatternArgs = {};
|
||||
PatternArgs.Assembly = Assembly;
|
||||
PatternArgs.Transient = Transient;
|
||||
PatternArgs.UserData = UserData;
|
||||
|
||||
led_buffer FromBuffer = RenderAnimationToLedBuffer(System,
|
||||
PatternArgs,
|
||||
FromFrame,
|
||||
FromLayerBuffers,
|
||||
AssemblyLedBuffer,
|
||||
Patterns,
|
||||
Transient,
|
||||
Context);
|
||||
led_buffer ConsolidatedBuffer = FromBuffer;
|
||||
|
||||
if (ToAnim) {
|
||||
led_buffer ToBuffer = RenderAnimationToLedBuffer(System,
|
||||
PatternArgs,
|
||||
ToFrame,
|
||||
ToLayerBuffers,
|
||||
AssemblyLedBuffer,
|
||||
Patterns,
|
||||
Transient,
|
||||
Context);
|
||||
|
||||
r32 BlendPercent = FadeGroup.FadeElapsed / FadeGroup.FadeDuration;
|
||||
LedBuffer_Blend(FromBuffer, ToBuffer, &ConsolidatedBuffer, LedBlend_Lerp, (u8*)&BlendPercent);
|
||||
}
|
||||
|
||||
LedBuffer_Copy(ConsolidatedBuffer, AssemblyLedBuffer);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(System);
|
||||
animation_frame CurrFrame = AnimationSystem_CalculateAnimationFrame(System, ActiveAnim, Transient);
|
||||
|
||||
for (u32 AssemblyIndex = 0; AssemblyIndex < Assemblies.Count; AssemblyIndex++)
|
||||
{
|
||||
assembly Assembly = Assemblies.Values[AssemblyIndex];
|
||||
led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex);
|
||||
|
||||
pattern_args PatternArgs = {};
|
||||
PatternArgs.Assembly = Assembly;
|
||||
PatternArgs.Transient = Transient;
|
||||
PatternArgs.UserData = UserData;
|
||||
|
||||
led_buffer AccBuffer = RenderAnimationToLedBuffer(System,
|
||||
PatternArgs,
|
||||
CurrFrame,
|
||||
LayerBuffers,
|
||||
AssemblyLedBuffer,
|
||||
Patterns,
|
||||
Transient);
|
||||
LedBuffer_Copy(AccBuffer, AssemblyLedBuffer);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
System->LastUpdatedFrame = System->CurrentFrame;
|
||||
}
|
||||
|
||||
#define FOLDHAUS_ANIMATION_RENDERER_CPP
|
||||
#endif // FOLDHAUS_ANIMATION_RENDERER_CPP
|
|
@ -0,0 +1,207 @@
|
|||
//
|
||||
// File: foldhaus_animation_serializer.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-10-04
|
||||
//
|
||||
#ifndef FOLDHAUS_ANIMATION_SERIALIZER_CPP
|
||||
|
||||
internal gs_string
|
||||
AnimSerializer_Serialize(animation Anim, animation_pattern_array Patterns, gs_memory_arena* Arena)
|
||||
{
|
||||
serializer Serializer = {0};
|
||||
Serializer.String = PushString(Arena, 4096);
|
||||
Serializer.Identifiers = AnimationFieldStrings;
|
||||
Serializer.IdentifiersCount = AnimField_Count;
|
||||
|
||||
Serializer_WriteF(&Serializer, "%S;\n", AnimationFieldStrings[AnimField_FileIdent]);
|
||||
Serializer_WriteStringValue(&Serializer, AnimField_AnimName, Anim.Name.ConstString);
|
||||
Serializer_WriteValue(&Serializer, AnimField_LayersCount, Anim.Layers.Count);
|
||||
Serializer_WriteValue(&Serializer, AnimField_BlocksCount, Anim.Blocks_.Count);
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_PlayableRange);
|
||||
{
|
||||
Serializer_WriteValue(&Serializer, AnimField_PlayableRangeMin, (u32)Anim.PlayableRange.Min);
|
||||
Serializer_WriteValue(&Serializer, AnimField_PlayableRangeMax, (u32)Anim.PlayableRange.Max);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_LayersArray);
|
||||
for (u32 i = 0; i < Anim.Layers.Count; i++)
|
||||
{
|
||||
anim_layer LayerAt = Anim.Layers.Values[i];
|
||||
Serializer_OpenStruct(&Serializer, AnimField_Layer);
|
||||
{
|
||||
Serializer_WriteStringValue(&Serializer, AnimField_LayerName, LayerAt.Name.ConstString);
|
||||
Serializer_WriteStringValue(&Serializer, AnimField_LayerBlendMode, BlendModeStrings[LayerAt.BlendMode].ConstString);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_BlocksArray);
|
||||
for (u32 i = 0; i < Anim.Blocks_.Count; i++)
|
||||
{
|
||||
// TODO(pjs): Handle free'd animation blocks
|
||||
animation_block AnimationBlockAt = Anim.Blocks_.Values[i];
|
||||
|
||||
animation_pattern Animation = Patterns_GetPattern(Patterns, AnimationBlockAt.AnimationProcHandle);
|
||||
|
||||
Serializer_OpenStruct(&Serializer, AnimField_Block);
|
||||
{
|
||||
Serializer_OpenStruct(&Serializer, AnimField_BlockFrameRange);
|
||||
{
|
||||
Serializer_WriteValue(&Serializer, AnimField_BlockFrameRangeMin, (u32)AnimationBlockAt.Range.Min);
|
||||
Serializer_WriteValue(&Serializer, AnimField_BlockFrameRangeMax, (u32)AnimationBlockAt.Range.Max);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
|
||||
Serializer_WriteValue(&Serializer, AnimField_BlockLayerIndex, AnimationBlockAt.Layer);
|
||||
Serializer_WriteStringValue(&Serializer, AnimField_BlockAnimName, ConstString(Animation.Name));
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
}
|
||||
Serializer_CloseStruct(&Serializer);
|
||||
|
||||
return Serializer.String;
|
||||
}
|
||||
|
||||
internal animation
|
||||
AnimParser_Parse(gs_string File, gs_memory_arena* Arena, animation_pattern_array AnimPatterns)
|
||||
{
|
||||
animation Result = {0};
|
||||
|
||||
parser Parser = {0};
|
||||
Parser.String = File;
|
||||
Parser.At = Parser.String.Str;
|
||||
Parser.Identifiers = AnimationFieldStrings;
|
||||
Parser.IdentifiersCount = AnimField_Count;
|
||||
Parser.Arena = Arena;
|
||||
|
||||
if (Parser_ReadString(&Parser, AnimationFieldStrings[AnimField_FileIdent]))
|
||||
{
|
||||
Result.Name = Parser_ReadStringValue(&Parser, AnimField_AnimName);
|
||||
|
||||
u32 LayersNeeded = Parser_ReadU32Value(&Parser, AnimField_LayersCount);
|
||||
u32 BlocksNeeded = Parser_ReadU32Value(&Parser, AnimField_BlocksCount);
|
||||
Result.Layers = AnimLayerArray_Create(Arena, LayersNeeded);
|
||||
Result.Blocks_ = AnimBlockArray_Create(Arena, BlocksNeeded);
|
||||
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_PlayableRange))
|
||||
{
|
||||
Result.PlayableRange.Min = Parser_ReadU32Value(&Parser, AnimField_PlayableRangeMin);
|
||||
Result.PlayableRange.Max = Parser_ReadU32Value(&Parser, AnimField_PlayableRangeMax);
|
||||
|
||||
if (Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_LayersArray))
|
||||
{
|
||||
while (!Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
anim_layer Layer = {0};
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_Layer))
|
||||
{
|
||||
Layer.Name = Parser_ReadStringValue(&Parser, AnimField_LayerName);
|
||||
|
||||
gs_string BlendModeName = Parser_ReadStringValue(&Parser, AnimField_LayerBlendMode);
|
||||
for (u32 i = 0; i < BlendMode_Count; i++)
|
||||
{
|
||||
if (StringsEqual(BlendModeName, BlendModeStrings[i]))
|
||||
{
|
||||
Layer.BlendMode = (blend_mode)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
Animation_AddLayer(&Result, Layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_BlocksArray))
|
||||
{
|
||||
while(!Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
animation_block Block = {0};
|
||||
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_Block))
|
||||
{
|
||||
if (Parser_ReadOpenStruct(&Parser, AnimField_BlockFrameRange))
|
||||
{
|
||||
Block.Range.Min = Parser_ReadU32Value(&Parser, AnimField_BlockFrameRangeMin);
|
||||
Block.Range.Max = Parser_ReadU32Value(&Parser, AnimField_BlockFrameRangeMax);
|
||||
|
||||
Parser_ReadCloseStruct(&Parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
|
||||
Block.Layer = Parser_ReadU32Value(&Parser, AnimField_BlockLayerIndex);
|
||||
|
||||
// TODO(pjs): AnimName -> Animation Proc Handle
|
||||
gs_string AnimName = Parser_ReadStringValue(&Parser, AnimField_BlockAnimName);
|
||||
Block.AnimationProcHandle = {0};
|
||||
for (u32 i = 0; i < AnimPatterns.Count; i++)
|
||||
{
|
||||
animation_pattern Pattern = AnimPatterns.Values[i];
|
||||
if (StringEqualsCharArray(AnimName.ConstString, Pattern.Name, Pattern.NameLength))
|
||||
{
|
||||
Block.AnimationProcHandle = Patterns_IndexToHandle(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert(IsValid(Block.AnimationProcHandle));
|
||||
if (Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
AnimBlockArray_Push(&Result.Blocks_, Block);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(pjs): Error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
internal animation
|
||||
AnimParser_Parse(gs_data File, gs_memory_arena* Arena, animation_pattern_array AnimPatterns)
|
||||
{
|
||||
gs_string FileString = MakeString((char*)File.Memory, File.Size);
|
||||
return AnimParser_Parse(FileString, Arena, AnimPatterns);
|
||||
}
|
||||
|
||||
internal animation_handle
|
||||
AnimationSystem_LoadAnimationFromFile(animation_system* System, animation_pattern_array AnimPatterns, context Context, gs_const_string FilePath)
|
||||
{
|
||||
animation_handle NewAnimHandle = InvalidAnimHandle();
|
||||
gs_file AnimFile = ReadEntireFile(Context.ThreadContext.FileHandler, FilePath);
|
||||
if (AnimFile.Size > 0)
|
||||
{
|
||||
animation NewAnim = AnimParser_Parse(AnimFile.Data, System->Storage, AnimPatterns);
|
||||
NewAnim.FileInfo = AnimFile.FileInfo;
|
||||
NewAnim.FileInfo.Path = PushStringF(System->Storage, AnimFile.FileInfo.Path.Length, "%S", AnimFile.FileInfo.Path).ConstString;
|
||||
NewAnimHandle = AnimationArray_Push(&System->Animations, NewAnim);
|
||||
}
|
||||
return NewAnimHandle;
|
||||
}
|
||||
#define FOLDHAUS_ANIMATION_SERIALIZER_CPP
|
||||
#endif // FOLDHAUS_ANIMATION_SERIALIZER_CPP
|
|
@ -0,0 +1,10 @@
|
|||
//
|
||||
// File: artnet.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
/* For future artnet implementation */
|
||||
#ifndef ARTNET_H
|
||||
|
||||
#define ARTNET_H
|
||||
#endif // ARTNET_H
|
|
@ -0,0 +1,283 @@
|
|||
//
|
||||
// File: foldhaus_assembly.cpp
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_ASSEMBLY_CPP
|
||||
|
||||
///////////////////////////
|
||||
//
|
||||
// Assembly Array
|
||||
//
|
||||
///////////////////////////
|
||||
|
||||
internal assembly_array
|
||||
AssemblyArray_Create(u32 CountMax, gs_memory_arena* Storage)
|
||||
{
|
||||
assembly_array Result = {0};
|
||||
Result.CountMax = CountMax;
|
||||
Result.Values = PushArray(Storage, assembly, Result.CountMax);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
AssemblyArray_Push(assembly_array* Array, assembly Assembly)
|
||||
{
|
||||
Assert(Array->Count < Array->CountMax);
|
||||
u32 Index = Array->Count++;
|
||||
Array->Values[Index] = Assembly;
|
||||
Array->Values[Index].AssemblyIndex = Index;
|
||||
return Index;
|
||||
}
|
||||
|
||||
internal assembly*
|
||||
AssemblyArray_Take(assembly_array* Array)
|
||||
{
|
||||
u32 Index = AssemblyArray_Push(Array, {});
|
||||
assembly* Result = Array->Values + Index;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
AssemblyArray_RemoveAt(assembly_array* Array, u32 Index)
|
||||
{
|
||||
u32 LastAssemblyIndex = --Array->Count;
|
||||
Array->Values[Index] = Array->Values[LastAssemblyIndex];
|
||||
}
|
||||
|
||||
typedef bool assembly_array_filter_proc(assembly A);
|
||||
bool AssemblyFilter_OutputsViaSACN(assembly A) { return A.OutputMode == NetworkProtocol_SACN; }
|
||||
bool AssemblyFilter_OutputsViaUART(assembly A) { return A.OutputMode == NetworkProtocol_UART; }
|
||||
|
||||
internal assembly_array
|
||||
AssemblyArray_Filter(assembly_array Array, assembly_array_filter_proc* Filter, gs_memory_arena* Storage)
|
||||
{
|
||||
assembly_array Result = AssemblyArray_Create(Array.Count, Storage);
|
||||
|
||||
for (u32 i = 0; i < Array.Count; i++)
|
||||
{
|
||||
assembly At = Array.Values[i];
|
||||
if (Filter(At))
|
||||
{
|
||||
AssemblyArray_Push(&Result, At);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
//
|
||||
// LedSystem
|
||||
//
|
||||
///////////////////////////
|
||||
|
||||
internal led_system
|
||||
LedSystem_Create(gs_allocator PlatformMemory, u32 BuffersMax)
|
||||
{
|
||||
led_system Result = {};
|
||||
Result.PlatformMemory = PlatformMemory;
|
||||
// TODO(Peter): Since we have access to PlatformMemory, just realloc Buffers when we fill it up
|
||||
Result.BuffersCountMax = BuffersMax;
|
||||
Result.Buffers = AllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax, "led system");
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
LedSystemTakeFreeBuffer(led_system* System, u32 LedCount)
|
||||
{
|
||||
s32 Result = -1;
|
||||
|
||||
if (System->BuffersCount < System->BuffersCountMax)
|
||||
{
|
||||
Result = System->BuffersCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE(Peter): Look for a buffer that's flagged as empty
|
||||
for (u32 i = 0; i < System->BuffersCount; i++)
|
||||
{
|
||||
if (System->Buffers[i].LedCount == 0
|
||||
&& System->Buffers[i].Colors == 0
|
||||
&& System->Buffers[i].Positions == 0)
|
||||
{
|
||||
Result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert(Result >= 0); // NOTE(Peter): We ran out of room for led buffers
|
||||
}
|
||||
|
||||
led_buffer* Buffer = &System->Buffers[Result];
|
||||
Buffer->A = MemoryArenaCreate(KB(16),Bytes(8),System->PlatformMemory,0,0,"Led Buffer Arena");
|
||||
Buffer->LedCount = LedCount;
|
||||
Buffer->Colors = PushArray(&Buffer->A, pixel, Buffer->LedCount);
|
||||
Buffer->Positions = PushArray(&Buffer->A, v4, Buffer->LedCount);
|
||||
|
||||
System->LedsCountTotal += LedCount;
|
||||
|
||||
return (u32)Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
LedSystemFreeBuffer(led_system* System, u32 BufferIndex)
|
||||
{
|
||||
Assert(BufferIndex < System->BuffersCountMax);
|
||||
led_buffer* Buffer = &System->Buffers[BufferIndex];
|
||||
MemoryArenaFree(&Buffer->A);
|
||||
System->LedsCountTotal -= Buffer->LedCount;
|
||||
*Buffer = {};
|
||||
}
|
||||
|
||||
internal void
|
||||
LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position)
|
||||
{
|
||||
Assert(Led < Buffer->LedCount);
|
||||
Buffer->Positions[Led] = Position;
|
||||
}
|
||||
|
||||
internal u32
|
||||
Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* StripAt, strip_gen_data GenData, v4 RootPosition, u32 LedStartIndex, u32 LedLUTStartIndex)
|
||||
{
|
||||
u32 LedsAdded = 0;
|
||||
|
||||
switch (GenData.Method)
|
||||
{
|
||||
case StripGeneration_InterpolatePoints:
|
||||
{
|
||||
strip_gen_interpolate_points InterpPoints = GenData.InterpolatePoints;
|
||||
v4 WS_StripStart = RootPosition + ToV4Point(InterpPoints.StartPosition * Assembly->Scale);
|
||||
v4 WS_StripEnd = RootPosition + ToV4Point(InterpPoints.EndPosition * Assembly->Scale);
|
||||
|
||||
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)InterpPoints.LedCount;
|
||||
for (u32 Step = 0; Step < InterpPoints.LedCount; Step++)
|
||||
{
|
||||
s32 LedIndex = LedStartIndex + LedsAdded++;
|
||||
v4 LedPosition = WS_StripStart + (SingleStep * Step);
|
||||
LedBufferSetLed(LedBuffer, LedIndex, LedPosition);
|
||||
StripAt->LedLUT[Step + LedLUTStartIndex] = LedIndex;
|
||||
}
|
||||
}break;
|
||||
|
||||
case StripGeneration_Sequence:
|
||||
{
|
||||
strip_gen_sequence Sequence = GenData.Sequence;
|
||||
for (u32 i = 0; i < Sequence.ElementsCount; i++)
|
||||
{
|
||||
strip_gen_data SegmentGenData = Sequence.Elements[i];
|
||||
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded, LedsAdded);
|
||||
}
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
|
||||
return LedsAdded;
|
||||
}
|
||||
|
||||
internal void
|
||||
ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem)
|
||||
{
|
||||
Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal);
|
||||
led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex);
|
||||
|
||||
v4 RootPosition = ToV4Vec(Assembly->Center);
|
||||
|
||||
// Add Leds
|
||||
u32 LedsAdded = 0;
|
||||
for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++)
|
||||
{
|
||||
v2_strip* StripAt = &Assembly->Strips[StripIdx];
|
||||
StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount);
|
||||
|
||||
strip_gen_data GenData = StripAt->GenerationData;
|
||||
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded, 0);
|
||||
}
|
||||
}
|
||||
|
||||
internal assembly*
|
||||
LoadAssembly (assembly_array* Assemblies, led_system* LedSystem, gs_memory_arena* Scratch, context Context, gs_const_string Path, log_buffer* GlobalLog)
|
||||
{
|
||||
assembly* NewAssembly = 0;
|
||||
|
||||
gs_file AssemblyFile = ReadEntireFile(Context.ThreadContext.FileHandler, Path);
|
||||
if (FileNoError(AssemblyFile))
|
||||
{
|
||||
gs_string AssemblyFileText = MakeString((char*)AssemblyFile.Memory);
|
||||
|
||||
s32 IndexOfLastSlash = FindLast(Path, '\\');
|
||||
gs_const_string FileName = Substring(Path, IndexOfLastSlash + 1, Path.Length);
|
||||
|
||||
NewAssembly = AssemblyArray_Take(Assemblies);
|
||||
NewAssembly->Arena = MemoryArenaCreate(MB(4), Bytes(8), Context.ThreadContext.Allocator, 0, 0, "Assembly Arena");
|
||||
|
||||
parser AssemblyParser = ParseAssemblyFile(NewAssembly, FileName, AssemblyFileText, Scratch);
|
||||
if (AssemblyParser.Success)
|
||||
{
|
||||
ConstructAssemblyFromDefinition(NewAssembly, LedSystem);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryArenaFree(&NewAssembly->Arena);
|
||||
Assemblies->Count -= 1;
|
||||
}
|
||||
|
||||
for (parser_error* ErrorAt = AssemblyParser.ErrorsRoot;
|
||||
ErrorAt != 0;
|
||||
ErrorAt = ErrorAt->Next)
|
||||
{
|
||||
Log_Error(GlobalLogBuffer, ErrorAt->Message.Str);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_Error(GlobalLog, "Unable to load assembly file");
|
||||
}
|
||||
|
||||
return NewAssembly;
|
||||
}
|
||||
|
||||
internal void
|
||||
UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context)
|
||||
{
|
||||
Assert(AssemblyIndex < State->Assemblies.Count);
|
||||
assembly* Assembly = &State->Assemblies.Values[AssemblyIndex];
|
||||
LedSystemFreeBuffer(&State->LedSystem, Assembly->LedBufferIndex);
|
||||
MemoryArenaFree(&Assembly->Arena);
|
||||
AssemblyArray_RemoveAt(&State->Assemblies, AssemblyIndex);
|
||||
}
|
||||
|
||||
// Querying Assemblies
|
||||
|
||||
internal led_strip_list
|
||||
AssemblyStripsGetWithTagValue(assembly Assembly, gs_const_string TagName, gs_const_string TagValue, gs_memory_arena* Storage)
|
||||
{
|
||||
led_strip_list Result = {0};
|
||||
// TODO(pjs): @Optimization
|
||||
// We can probably come back here and do this allocation procedurally, or in buckets, or with
|
||||
// a linked list. But for now, I just want to get this up and running
|
||||
Result.CountMax = Assembly.StripCount;
|
||||
Result.StripIndices = PushArray(Storage, u32, Result.CountMax);
|
||||
|
||||
u64 NameHash = HashDJB2ToU32(StringExpand(TagName));
|
||||
u64 ValueHash = 0;
|
||||
if (TagValue.Length > 0)
|
||||
{
|
||||
ValueHash = HashDJB2ToU32(StringExpand(TagValue));
|
||||
}
|
||||
|
||||
for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++)
|
||||
{
|
||||
v2_strip StripAt = Assembly.Strips[StripIndex];
|
||||
if (AssemblyStrip_HasTagValue(StripAt, NameHash, ValueHash))
|
||||
{
|
||||
Result.StripIndices[Result.Count++] = StripIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define FOLDHAUS_ASSEMBLY_CPP
|
||||
#endif // FOLDHAUS_ASSEMBLY_CPP
|
|
@ -0,0 +1,298 @@
|
|||
//
|
||||
// File: foldhaus_assembly.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_ASSEMBLY_H
|
||||
|
||||
enum network_protocol
|
||||
{
|
||||
NetworkProtocol_SACN,
|
||||
NetworkProtocol_ArtNet,
|
||||
NetworkProtocol_UART,
|
||||
|
||||
NetworkProtocol_Count,
|
||||
};
|
||||
|
||||
union pixel
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 R;
|
||||
u8 G;
|
||||
u8 B;
|
||||
};
|
||||
u8 Channels[3];
|
||||
};
|
||||
|
||||
struct led_buffer
|
||||
{
|
||||
// NOTE(PS): This is just a tracking structure,
|
||||
// that enables allocations for a particular buffer
|
||||
// to occur all in contiguous memory
|
||||
// and should not be pushed to after the initial
|
||||
// allocation
|
||||
gs_memory_arena A;
|
||||
|
||||
u32 LedCount;
|
||||
pixel* Colors;
|
||||
v4* Positions;
|
||||
};
|
||||
|
||||
struct led_buffer_range
|
||||
{
|
||||
u32 First;
|
||||
u32 OnePastLast;
|
||||
};
|
||||
|
||||
struct led_system
|
||||
{
|
||||
gs_allocator PlatformMemory;
|
||||
|
||||
u32 BuffersCountMax;
|
||||
u32 BuffersCount;
|
||||
led_buffer* Buffers;
|
||||
|
||||
u32 LedsCountTotal;
|
||||
};
|
||||
|
||||
struct v2_tag
|
||||
{
|
||||
u64 NameHash;
|
||||
u64 ValueHash;
|
||||
};
|
||||
|
||||
struct strip_sacn_addr
|
||||
{
|
||||
s32 StartUniverse;
|
||||
s32 StartChannel;
|
||||
};
|
||||
|
||||
struct strip_uart_addr
|
||||
{
|
||||
u8 Channel;
|
||||
|
||||
gs_string ComPort;
|
||||
// This may not be used based on the value of the parent
|
||||
// assembly's NetworkPortMode field
|
||||
};
|
||||
|
||||
enum strip_gen_method
|
||||
{
|
||||
StripGeneration_InterpolatePoints,
|
||||
StripGeneration_Sequence,
|
||||
|
||||
StripGeneration_Count,
|
||||
};
|
||||
|
||||
typedef struct strip_gen_data strip_gen_data;
|
||||
|
||||
struct strip_gen_interpolate_points
|
||||
{
|
||||
v3 StartPosition;
|
||||
v3 EndPosition;
|
||||
u32 LedCount;
|
||||
};
|
||||
|
||||
struct strip_gen_sequence
|
||||
{
|
||||
strip_gen_data* Elements;
|
||||
u32 ElementsCount;
|
||||
};
|
||||
|
||||
struct strip_gen_data
|
||||
{
|
||||
strip_gen_method Method;
|
||||
|
||||
strip_gen_interpolate_points InterpolatePoints;
|
||||
strip_gen_sequence Sequence;
|
||||
};
|
||||
|
||||
struct v2_strip
|
||||
{
|
||||
s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore
|
||||
|
||||
strip_sacn_addr SACNAddr;
|
||||
strip_uart_addr UARTAddr;
|
||||
|
||||
strip_gen_data GenerationData;
|
||||
|
||||
u32 LedCount;
|
||||
u32* LedLUT;
|
||||
|
||||
u32 TagsCount;
|
||||
v2_tag* Tags;
|
||||
};
|
||||
|
||||
struct led_strip_list
|
||||
{
|
||||
u32 Count;
|
||||
u32 CountMax;
|
||||
u32* StripIndices;
|
||||
};
|
||||
|
||||
enum network_port_mode
|
||||
{
|
||||
// This enum defines the scope which contains what network
|
||||
// port each address should be sent over.
|
||||
|
||||
NetworkPortMode_GlobalPort,
|
||||
// GlobalPort means that the port is defined in the assembly structure
|
||||
|
||||
NetworkPortMode_PortPerStrip,
|
||||
// PortPerStrip means that the address stored in the strip structure
|
||||
// should be used, and each strip might have a different port
|
||||
|
||||
NetworkPortMode_Count,
|
||||
};
|
||||
|
||||
struct assembly
|
||||
{
|
||||
gs_memory_arena Arena;
|
||||
|
||||
u32 AssemblyIndex;
|
||||
gs_string Name;
|
||||
gs_string FilePath;
|
||||
|
||||
r32 Scale;
|
||||
v3 Center;
|
||||
v3 MinLedPos, MaxLedPos;
|
||||
s32 LedCountTotal;
|
||||
u32 LedBufferIndex;
|
||||
|
||||
u32 StripCount;
|
||||
v2_strip* Strips;
|
||||
|
||||
network_protocol OutputMode;
|
||||
network_port_mode NetPortMode;
|
||||
gs_string UARTComPort;
|
||||
};
|
||||
|
||||
struct assembly_array
|
||||
{
|
||||
u32 CountMax;
|
||||
u32 Count;
|
||||
assembly* Values;
|
||||
};
|
||||
|
||||
typedef pixel led_blend_proc(pixel A, pixel B, u8* UserData);
|
||||
|
||||
internal led_buffer*
|
||||
LedSystemGetBuffer(led_system* System, u32 Index)
|
||||
{
|
||||
led_buffer* Result = &System->Buffers[Index];
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
LedBuffer_ClearToBlack(led_buffer* Buffer)
|
||||
{
|
||||
for (u32 i = 0; i < Buffer->LedCount; i++)
|
||||
{
|
||||
Buffer->Colors[i].R = 0;
|
||||
Buffer->Colors[i].G = 0;
|
||||
Buffer->Colors[i].B = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
LedBuffer_Copy(led_buffer From, led_buffer* To)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
Assert(From.LedCount == To->LedCount);
|
||||
u32 LedCount = To->LedCount;
|
||||
for (u32 i = 0; i < LedCount; i++)
|
||||
{
|
||||
To->Colors[i] = From.Colors[i];
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
LedBuffer_Blend(led_buffer A, led_buffer B, led_buffer* Dest, led_blend_proc* BlendProc, u8* UserData)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
Assert(A.LedCount == B.LedCount);
|
||||
Assert(Dest->LedCount == A.LedCount);
|
||||
Assert(BlendProc);
|
||||
|
||||
u32 LedCount = Dest->LedCount;
|
||||
for (u32 i = 0; i < LedCount; i++)
|
||||
{
|
||||
pixel PA = A.Colors[i];
|
||||
pixel PB = B.Colors[i];
|
||||
Dest->Colors[i] = BlendProc(PA, PB, UserData);
|
||||
}
|
||||
}
|
||||
|
||||
internal led_buffer
|
||||
LedBuffer_CreateCopyCleared (led_buffer Buffer, gs_memory_arena* Arena)
|
||||
{
|
||||
DEBUG_TRACK_FUNCTION;
|
||||
|
||||
led_buffer Result = {};
|
||||
Result.LedCount = Buffer.LedCount;
|
||||
Result.Positions = Buffer.Positions;
|
||||
Result.Colors = PushArray(Arena, pixel, Buffer.LedCount);
|
||||
LedBuffer_ClearToBlack(&Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
StripGenData_CountLeds(strip_gen_data Data)
|
||||
{
|
||||
u32 Result = 0;
|
||||
|
||||
switch (Data.Method)
|
||||
{
|
||||
case StripGeneration_InterpolatePoints:
|
||||
{
|
||||
Result += Data.InterpolatePoints.LedCount;
|
||||
}break;
|
||||
|
||||
case StripGeneration_Sequence:
|
||||
{
|
||||
for (u32 i = 0; i < Data.Sequence.ElementsCount; i++)
|
||||
{
|
||||
Result += StripGenData_CountLeds(Data.Sequence.Elements[i]);
|
||||
}
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
AssemblyStrip_HasTagValue(v2_strip Strip, u64 NameHash, u64 ValueHash)
|
||||
{
|
||||
bool Result = false;
|
||||
for (u32 i = 0; i < Strip.TagsCount; i++)
|
||||
{
|
||||
v2_tag TagAt = Strip.Tags[i];
|
||||
if (TagAt.NameHash == NameHash)
|
||||
{
|
||||
// NOTE(pjs): We can pass an empty string to the Value parameter,
|
||||
// and it will match all values of Tag
|
||||
if (ValueHash == 0 || ValueHash == TagAt.ValueHash)
|
||||
{
|
||||
Result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
AssemblyStrip_HasTagValueSLOW(v2_strip Strip, char* Name, char* Value)
|
||||
{
|
||||
u64 NameHash = HashDJB2ToU32(Name);
|
||||
u64 ValueHash = HashDJB2ToU32(Value);
|
||||
return AssemblyStrip_HasTagValue(Strip, NameHash, ValueHash);
|
||||
}
|
||||
|
||||
#define FOLDHAUS_ASSEMBLY_H
|
||||
#endif // FOLDHAUS_ASSEMBLY_H
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue