mirror of
https://github.com/nicbarker/clay.git
synced 2025-04-15 10:48:04 +00:00
Added C3 Bindings
This commit is contained in:
parent
e9f2e6c4f1
commit
f48ee0b9fd
73
bindings/c3/README.md
Normal file
73
bindings/c3/README.md
Normal file
@ -0,0 +1,73 @@
|
||||
# Clay-C3-Bindings
|
||||
C3 Bindings for [Clay](https://github.com/nicbarker/clay.git), a UI layout library written in C.
|
||||
This directory contains the clay.c3 bindings file as well as a recreation of the clay-raylibs binding and the video-example raylib project.
|
||||
|
||||
Special thanks to:
|
||||
- [Christoffer L](https://github.com/lerno) C3's core developer (as I understand it)
|
||||
- Book-reader in the [C3-lang Discord](https://discord.gg/qN76R87)
|
||||
|
||||
## TODO:
|
||||
- Find out how to build a static-lib with additional C sources
|
||||
|
||||
## - C3 macros
|
||||
Traditional Clay C Macro System
|
||||
|
||||
```cpp
|
||||
/* FILTER BUTTON */
|
||||
CLAY(
|
||||
CLAY_ID("FilterButton"),
|
||||
Clay_Hovered() ? CLAY_RECTANGLE({
|
||||
.color = Clay_Hovered() ? FIRE_ORANGE : (Clay_Color){80, 25, 200, 255},
|
||||
.cornerRadius = 8,
|
||||
}) : 0,
|
||||
CLAY_LAYOUT({
|
||||
.sizing = {
|
||||
.width = CLAY_SIZING_FIT(),
|
||||
.height = CLAY_SIZING_GROW()
|
||||
},
|
||||
.padding = 10
|
||||
})
|
||||
) {
|
||||
// define children...
|
||||
}
|
||||
```
|
||||
|
||||
Clay C3 Macro System
|
||||
```cpp
|
||||
/* FILTER BUTTON */
|
||||
clay::clay(
|
||||
clay::id("FilterButton"),
|
||||
clay::@bodyIf(clay::hovered(), clay::rectangle({
|
||||
.color = clay::hovered() ? FIRE_ORANGE : {80, 25, 200, 255},
|
||||
.cornerRadius = clay::cornerRadiusUni(8)
|
||||
})
|
||||
),
|
||||
clay::layout({
|
||||
.sizing = {
|
||||
.width = clay::sizingFit(),
|
||||
.height = clay::sizingGrow()
|
||||
},
|
||||
.padding = clay::paddingUni(8)
|
||||
})
|
||||
){
|
||||
// define children...
|
||||
};
|
||||
```
|
||||
|
||||
## To Get Started:
|
||||
- Download c3c [here](https://c3-lang.org/getting-started/prebuilt-binaries/)
|
||||
- If you wish to compile the website-example, I've already provided a target to build in the [project.json](project.json)
|
||||
[Photo of project.json goes here]
|
||||
- - set your `cd` to this project dir
|
||||
- - The use the `c3c vendor-fetch raylib55` command to download a c3 compressed archive of raylib
|
||||
- - - *once you have raylib55.c3l in the [lib](lib) folder you've got it right*
|
||||
- - - (*note: for the current configuration you'll need to modify the default raylib module name in th raylib.c3i file in [build](build) directory from `raylib55::li` to `module raylib`*)
|
||||
- - then simple use the command `c3c run video-example` to compile and run that video example
|
||||
- - - (*note: to use the `c3c build <target>` command with video-example, you'll need to copy the resource folder into the [build](build) directory with the execute to run it
|
||||
- - - `run` executes the build result from the project directory, somehow. This means that `run` will look for the resource folder in [c3](../c3), while `build` will look for it in [build](build))
|
||||
|
||||
## RESOURCES:
|
||||
### - [C3](https://github.com/c3lang/c3c.git) (A C-a-like, that aims to bring modern language QA features and a revamped Macro system to C)
|
||||
### - [Raylib](https://github.com/raysan5/raylib.git) (C Videogame and Graphical API)
|
||||
### - [Lexend](https://github.com/googlefonts/lexend.git) (Accessible/ Dyslexic Friendly Font)
|
||||
|
4126
bindings/c3/c-lang/source/clay.c
Normal file
4126
bindings/c3/c-lang/source/clay.c
Normal file
File diff suppressed because it is too large
Load Diff
33
bindings/c3/project.json
Normal file
33
bindings/c3/project.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"langrev": "1",
|
||||
"authors": [ "Jefferey Schlueter <jefferey.l.schlueter@gmail.com>" ],
|
||||
"version": "0.1.0",
|
||||
"targets": {
|
||||
|
||||
// TODO: found out how to stop this from outputting a .lib and .pdb in addition to the .exe (they don't do anything)
|
||||
"video-example": {
|
||||
"output": "build/video-example/",
|
||||
"c-sources": [ "c-lang/source/clay.c" ],
|
||||
"cflags": "-DCLAY_IMPLEMENTATION", // makes the clay source actually define things
|
||||
"type": "executable",
|
||||
"dependency-search-paths": [ "lib" ],
|
||||
"dependencies": [ "raylib55" ],
|
||||
"sources": [ "source/clay.c3", "source/clay-raylib-renderer.c3", "examples/video-example.c3" ],
|
||||
// "link-libc": false, // TODO; leads to duplicate definitions (eg math_nolibc)
|
||||
// "use-stdlib": false, // TODO: leads to ZString being undefined -> then mising main @main_to_void_main
|
||||
// "features": ["NO_STDLIB"]
|
||||
},
|
||||
|
||||
// TODO: figure out why creating static/dynamic libraries with C sources doesn't work (emits no errors just crashes out and dumps an empty clay-win.h into the project dir)
|
||||
// "clay-win": {
|
||||
// "output": "build/clay.c3l/windows-x64",
|
||||
// "c-sources": [ "c-lang/source/clay.c" ],
|
||||
// "sources": [ "source/clay.c3" ],
|
||||
// "type": "static-lib"
|
||||
// },
|
||||
// build args with no C references
|
||||
//../c3c.exe --link-libc=no --use-stdlib=no -o clay --template static-lib --output-dir build/clay.c3l/windows-x64 --print-linking --print-output -vvv static-lib source/clay-slim.c3
|
||||
},
|
||||
"cc": "gcc",
|
||||
"cpu": "generic",
|
||||
}
|
BIN
bindings/c3/resources/Lexend-Regular.ttf
Normal file
BIN
bindings/c3/resources/Lexend-Regular.ttf
Normal file
Binary file not shown.
700
bindings/c3/source/clay-depracated.c3
Normal file
700
bindings/c3/source/clay-depracated.c3
Normal file
@ -0,0 +1,700 @@
|
||||
// TODO: including additional structures required for Clay_Context led to bloat
|
||||
|
||||
// module clay;
|
||||
|
||||
// // import std::core::cinterop ;
|
||||
// import clay::carray;
|
||||
|
||||
// // =======================
|
||||
// // ===== USER MACROS =====
|
||||
// // =======================
|
||||
// macro @clay(...; @body()) @builtin
|
||||
// {
|
||||
// clay::openElement();
|
||||
// $for (var $i = 0; $i < $vacount; $i++)
|
||||
// $vaexpr[$i]; // If you get an error here consisder the @body[...]() macros
|
||||
// $endfor
|
||||
// clay::elementPostConfiguration();
|
||||
// @body();
|
||||
// clay::closeElement();
|
||||
// }
|
||||
|
||||
// macro text(String text, TextElementConfig *config) { clay::openTextElement({text.len, text}, config); }
|
||||
|
||||
// <*Provides you conditional calls (eg #booleanCondition ? #doA : 0) within the condifuration of @clay(...)*>
|
||||
// macro @bodyIf(#condition, #ifRes) { if (#condition) { #ifRes; } }
|
||||
|
||||
// <*Provides you conditional calls (eg #booleanCondition ? #doA : #doB) within the condifuration of @clay(...)*>
|
||||
// macro @bodyIfElse(#condition, #ifRes, #elseRes) { if (#condition) { #ifRes; } else { #elseRes; } }
|
||||
|
||||
// // <*Facilitates non-method calls (eg { #doWhatever }, { #booleanExpression ? #doA : #doB}, etc.) within the parameters of @clay(...)*>
|
||||
// // macro @inline(; @body()) { @body(); }
|
||||
|
||||
// <*attaches a RectangleElementConfig to the clay element when called within @clay(...)*>
|
||||
// macro rectangle(RectangleElementConfig config) { clay::attachElementConfig({ .rectangleElementConfig = clay::storeRectangleElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_RECTANGLE ); }
|
||||
|
||||
// <*attaches a LayoutConfig to the clay element when called within @clay(...)*>
|
||||
// macro layout(LayoutConfig config) { clay::attachLayoutConfig( clay::storeLayoutConfig(config) ); }
|
||||
|
||||
// <*attaches a LayoutConfig to the clay element when called within @clay(...)*>
|
||||
// macro scroll(ScrollElementConfig config) { clay::attachElementConfig({ .scrollElementConfig = clay::storeScrollElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER ); }
|
||||
|
||||
// <*attaches a FloatingElementConfig to the clay element when called within @clay(...)*>
|
||||
// macro floating(FloatingElementConfig config) { clay::attachElementConfig({ .floatingElementConfig = clay::storeFloatingElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER ); }
|
||||
|
||||
// <*attaches a BorderElementConfig to the clay element when called within @clay(...)*>
|
||||
// macro @borderRadiusUni(uint #width, ClayColor #color, float #cornerRadius = 0) { clay::attachElementConfig({ .borderElementConfig = clay::storeBorderElementConfig({ .left = { #width, #color }, .right = { #width, #color }, .top = { #width, #color }, .bottom = { #width, #color }, .#cornerRadius = {#cornerRadius, #cornerRadius, #cornerRadius, #cornerRadius}})}, clay::ELEMENT_CONFIG_TYPE_BORDER_CONTAINER); }
|
||||
|
||||
// macro id(String idString) { clay::attachId(clay::hashString({idString.len, idString}, 0, 0)); }
|
||||
|
||||
// macro TextElementConfig* textConfig(TextElementConfig config) { return clay::storeTextElementConfig(config); }
|
||||
|
||||
// macro SizingAxis sizingFit(float min = 0, float max = float.max) { return { .size.minMax = {min, max}, .type = SizingType.FIT }; }
|
||||
|
||||
// macro SizingAxis sizingGrow() { return { .size.minMax = {0, 0}, .type = SizingType.GROW }; }
|
||||
|
||||
// macro SizingAxis sizingFixed(float pixels) { return { .size.minMax = {pixels, pixels}, .type = SizingType.FIXED }; }
|
||||
|
||||
// macro SizingAxis sizingPercent(float percent) { return { .size.percent = percent, .type = SizingType.PERCENT }; }
|
||||
|
||||
// macro Padding paddingUni(ushort uniform) { return {uniform, uniform, uniform, uniform}; }
|
||||
|
||||
// macro Padding padding(ushort horizontal, ushort vertical) { return {horizontal, horizontal, vertical, vertical}; }
|
||||
|
||||
// macro CornerRadius cornerRadiusUni(float uniform) { return {uniform, uniform, uniform, uniform}; }
|
||||
|
||||
// macro SizingAxis sizingFitCT(float $min = 0, float $max = float.max) { return { .size.minMax = {$min, $max}, .type = SizingType.FIT }; }
|
||||
|
||||
// macro SizingAxis sizingFixedCT(float $pixels) { return { .size.minMax = {$pixels, $pixels}, .type = SizingType.FIXED }; }
|
||||
|
||||
// macro SizingAxis sizingPercentCT(float $percent) { return { .size.percent = $percent, .type = SizingType.PERCENT }; }
|
||||
|
||||
// macro Padding paddingCT(ushort $a, ushort $b, ushort $c, ushort $d) { return { $a, $b, $c, $d }; }
|
||||
|
||||
// macro CornerRadius @cornerRadiusUniCT(float #uniform) { return {#uniform, #uniform, #uniform, #uniform}; }
|
||||
|
||||
// // ===================
|
||||
// // ===== STRUCTS =====
|
||||
// // ===================
|
||||
// struct ClayString
|
||||
// {
|
||||
// int length;
|
||||
// char *chars;
|
||||
// }
|
||||
// def ClayStringArray = carray::Array(<ClayString>) @private;
|
||||
|
||||
// struct Arena
|
||||
// {
|
||||
// uint128 nextAllocation;
|
||||
// uint128 capacity;
|
||||
// char *memory;
|
||||
// }
|
||||
|
||||
// struct Dimensions
|
||||
// {
|
||||
// float width, height;
|
||||
// }
|
||||
|
||||
// struct ClayVector2
|
||||
// {
|
||||
// float x, y;
|
||||
// }
|
||||
|
||||
// struct ClayColor
|
||||
// {
|
||||
// float r, g, b, a;
|
||||
// }
|
||||
|
||||
// struct ClayBoundingBox
|
||||
// {
|
||||
// float x, y, width, height;
|
||||
// }
|
||||
|
||||
// struct ElementId
|
||||
// {
|
||||
// uint id;
|
||||
// uint offset;
|
||||
// uint baseId;
|
||||
// ClayString stringId;
|
||||
// }
|
||||
|
||||
// struct CornerRadius
|
||||
// {
|
||||
// float topLeft;
|
||||
// float topRight;
|
||||
// float bottomLeft;
|
||||
// float bottomRight;
|
||||
// }
|
||||
|
||||
// // ===== Element Configs =====
|
||||
// distinct ElementConfigType @private = char;
|
||||
// const ElementConfigType ELEMENT_CONFIG_TYPE_NONE @private = 0;
|
||||
// const ElementConfigType ELEMENT_CONFIG_TYPE_RECTANGLE @private = 1;
|
||||
// const ElementConfigType ELEMENT_CONFIG_TYPE_BORDER_CONTAINER @private = 2;
|
||||
// const ElementConfigType ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER @private = 4;
|
||||
// const ElementConfigType ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER @private = 8;
|
||||
// const ElementConfigType ELEMENT_CONFIG_TYPE_IMAGE @private = 16;
|
||||
// const ElementConfigType ELEMENT_CONFIG_TYPE_TEXT @private = 32;
|
||||
// const ElementConfigType ELEMENT_CONFIG_TYPE_CUSTOM @private = 64;
|
||||
|
||||
// enum LayoutDirection : char @export
|
||||
// {
|
||||
// LEFT_TO_RIGHT,
|
||||
// TOP_TO_BOTTOM,
|
||||
// }
|
||||
|
||||
// enum AlignX : char @export
|
||||
// {
|
||||
// LEFT,
|
||||
// RIGHT,
|
||||
// CENTER,
|
||||
// }
|
||||
|
||||
// enum AlignY : char @export
|
||||
// {
|
||||
// TOP,
|
||||
// BOTTOM,
|
||||
// CENTER,
|
||||
// }
|
||||
|
||||
// enum SizingType : char @export
|
||||
// {
|
||||
// FIT,
|
||||
// GROW,
|
||||
// PERCENT,
|
||||
// FIXED,
|
||||
// }
|
||||
|
||||
// struct ChildAlignment
|
||||
// {
|
||||
// AlignX x;
|
||||
// AlignY y;
|
||||
// }
|
||||
|
||||
// struct SizingMinMax
|
||||
// {
|
||||
// float min;
|
||||
// float max;
|
||||
// }
|
||||
|
||||
// struct SizingAxis
|
||||
// {
|
||||
// union size
|
||||
// {
|
||||
// SizingMinMax minMax;
|
||||
// float percent;
|
||||
// }
|
||||
// SizingType type;
|
||||
// }
|
||||
|
||||
// struct Sizing
|
||||
// {
|
||||
// SizingAxis width;
|
||||
// SizingAxis height;
|
||||
// }
|
||||
|
||||
// struct Padding
|
||||
// {
|
||||
// ushort left;
|
||||
// ushort right;
|
||||
// ushort top;
|
||||
// ushort bottom;
|
||||
// }
|
||||
|
||||
// struct LayoutConfig
|
||||
// {
|
||||
// Sizing sizing;
|
||||
// Padding padding;
|
||||
// ushort childGap;
|
||||
// ChildAlignment childAlignment;
|
||||
// LayoutDirection layoutDirection;
|
||||
// }
|
||||
|
||||
// struct RectangleElementConfig
|
||||
// {
|
||||
// ClayColor color;
|
||||
// CornerRadius cornerRadius;
|
||||
// // #ifdef CLAY_EXTEND_CONFIG_RECTANGLE
|
||||
// // CLAY_EXTEND_CONFIG_RECTANGLE
|
||||
// // #endif
|
||||
// }
|
||||
|
||||
// enum WrapMode @export
|
||||
// {
|
||||
// WORDS,
|
||||
// NEWLINES,
|
||||
// NONE,
|
||||
// }
|
||||
|
||||
// struct TextElementConfig
|
||||
// {
|
||||
// ClayColor textColor;
|
||||
// ushort fontId;
|
||||
// ushort fontSize;
|
||||
// ushort letterSpacing;
|
||||
// ushort lineHeight;
|
||||
// WrapMode wrapMode;
|
||||
// // #ifdef CLAY_EXTEND_CONFIG_TEXT
|
||||
// // CLAY_EXTEND_CONFIG_TEXT
|
||||
// // #endif
|
||||
// }
|
||||
|
||||
// struct ImageElementConfig
|
||||
// {
|
||||
// void *imageData;
|
||||
// Dimensions sourceDimensions;
|
||||
// // #ifdef CLAY_EXTEND_CONFIG_IMAGE
|
||||
// // CLAY_EXTEND_CONFIG_IMAGE
|
||||
// // #endif
|
||||
// }
|
||||
|
||||
// enum AttachPoint : char @export
|
||||
// {
|
||||
// LEFT_TOP,
|
||||
// LEFT_CENTER,
|
||||
// LEFT_BOTTOM,
|
||||
// CENTER_TOP,
|
||||
// CENTER_CENTER,
|
||||
// CENTER_BOTTOM,
|
||||
// RIGHT_TOP,
|
||||
// RIGHT_CENTER,
|
||||
// RIGHT_BOTTOM,
|
||||
// }
|
||||
|
||||
// struct FloatingAttachPoints
|
||||
// {
|
||||
// AttachPoint element;
|
||||
// AttachPoint parent;
|
||||
// }
|
||||
|
||||
// enum PointerCaptureMode @export
|
||||
// {
|
||||
// CAPTURE,
|
||||
// // MODE_PASSTHROUGH,
|
||||
// PARENT,
|
||||
// }
|
||||
|
||||
// struct FloatingElementConfig
|
||||
// {
|
||||
// ClayVector2 offset;
|
||||
// Dimensions expand;
|
||||
// ushort zIndex;
|
||||
// uint parentId;
|
||||
// FloatingAttachPoints attachment;
|
||||
// PointerCaptureMode pointerCaptureMode;
|
||||
// }
|
||||
|
||||
|
||||
// struct CustomElementConfig
|
||||
// {
|
||||
// // #ifndef CLAY_EXTEND_CONFIG_CUSTOM
|
||||
// void *customData;
|
||||
// // #else
|
||||
// // CLAY_EXTEND_CONFIG_CUSTOM
|
||||
// // #endif
|
||||
// }
|
||||
|
||||
// struct ScrollElementConfig
|
||||
// {
|
||||
// bool horizontal;
|
||||
// bool vertical;
|
||||
// }
|
||||
|
||||
// // Border
|
||||
// struct Border
|
||||
// {
|
||||
// uint width;
|
||||
// ClayColor color;
|
||||
// }
|
||||
|
||||
// struct BorderElementConfig
|
||||
// {
|
||||
// Border left;
|
||||
// Border right;
|
||||
// Border top;
|
||||
// Border bottom;
|
||||
// Border betweenChildren;
|
||||
// CornerRadius cornerRadius;
|
||||
// // #ifdef CLAY_EXTEND_CONFIG_BORDER
|
||||
// // CLAY_EXTEND_CONFIG_BORDER
|
||||
// // #endif
|
||||
// }
|
||||
|
||||
// union ElementConfigUnion
|
||||
// {
|
||||
// RectangleElementConfig *rectangleElementConfig;
|
||||
// TextElementConfig *textElementConfig;
|
||||
// ImageElementConfig *imageElementConfig;
|
||||
// FloatingElementConfig *floatingElementConfig;
|
||||
// CustomElementConfig *customElementConfig;
|
||||
// ScrollElementConfig *scrollElementConfig;
|
||||
// BorderElementConfig *borderElementConfig;
|
||||
// }
|
||||
|
||||
// struct ElementConfig
|
||||
// {
|
||||
// ElementConfigType type;
|
||||
// ElementConfigUnion config;
|
||||
// }
|
||||
|
||||
// // Miscellaneous Structs & Enums ---------------------------------
|
||||
// struct ScrollContainerData
|
||||
// {
|
||||
// // Note: This is a pointer to the real internal scroll position, mutating it may cause a change in final layout.
|
||||
// // Intended for use with external functionality that modifies scroll position, such as scroll bars or auto scrolling.
|
||||
// ClayVector2 *scrollPosition;
|
||||
// Dimensions scrollContainerDimensions;
|
||||
// Dimensions contentDimensions;
|
||||
// ScrollElementConfig config;
|
||||
// // Indicates whether an actual scroll container matched the provided ID or if the default struct was returned.
|
||||
// bool found;
|
||||
// }
|
||||
|
||||
// <*
|
||||
// @
|
||||
// *>
|
||||
// struct ElementData
|
||||
// {
|
||||
// ClayBoundingBox boundingBox;
|
||||
// // Indicates whether an actual Element matched the provided ID or if the default struct was returned.
|
||||
// bool found;
|
||||
// }
|
||||
|
||||
// enum RenderCommandType : char @export
|
||||
// {
|
||||
// NONE,
|
||||
// RECTANGLE,
|
||||
// BORDER,
|
||||
// TEXT,
|
||||
// IMAGE,
|
||||
// SCISSOR_START,
|
||||
// SCISSOR_END,
|
||||
// CUSTOM,
|
||||
// }
|
||||
|
||||
// struct RenderCommand
|
||||
// {
|
||||
// ClayBoundingBox boundingBox;
|
||||
// ElementConfigUnion config;
|
||||
// ClayString text;
|
||||
// uint id;
|
||||
// RenderCommandType commandType;
|
||||
// }
|
||||
// def RenderCommandArray = carray::Array(<RenderCommand>);
|
||||
|
||||
// enum PointerState @export
|
||||
// {
|
||||
// PRESSED_THIS_FRAME,
|
||||
// PRESSED,
|
||||
// RELEASED_THIS_FRAME,
|
||||
// RELEASED,
|
||||
// }
|
||||
|
||||
// struct PointerData
|
||||
// {
|
||||
// ClayVector2 position;
|
||||
// PointerState state;
|
||||
// }
|
||||
|
||||
// enum ErrorType @export
|
||||
// {
|
||||
// TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED,
|
||||
// ARENA_CAPACITY_EXCEEDED,
|
||||
// ELEMENTS_CAPACITY_EXCEEDED,
|
||||
// TEXT_MEASUREMENT_CAPACITY_EXCEEDED,
|
||||
// DUPLICATE_ID,
|
||||
// FLOATING_CONTAINER_PARENT_NOT_FOUND,
|
||||
// INTERNAL_ERROR,
|
||||
// }
|
||||
|
||||
// struct ErrorData
|
||||
// {
|
||||
// ErrorType errorType;
|
||||
// ClayString errorText;
|
||||
// uint128 userData;
|
||||
// }
|
||||
|
||||
// def ErrorHandleFunc = fn void(ErrorData errorText);
|
||||
|
||||
// struct ErrorHandler
|
||||
// {
|
||||
// ErrorHandleFunc errorHandler;
|
||||
// uint128 userData;
|
||||
// }
|
||||
|
||||
// struct BooleanWarnings
|
||||
// {
|
||||
// bool maxElementsExceeded;
|
||||
// bool maxRenderCommandsExceeded;
|
||||
// bool maxTextMeasureCacheExceeded;
|
||||
// }
|
||||
|
||||
// struct Warning
|
||||
// {
|
||||
// ClayString baseMessage;
|
||||
// ClayString dynamicMessage;
|
||||
// }
|
||||
|
||||
// def WarningArray = carray::Array(<Warning>);
|
||||
|
||||
// struct LayoutElementChildren
|
||||
// {
|
||||
// int *elements;
|
||||
// ushort length;
|
||||
// }
|
||||
|
||||
// struct LayoutElement
|
||||
// {
|
||||
// union childrenOrTextContent {
|
||||
// LayoutElementChildren children;
|
||||
// TextElementData *textElementData;
|
||||
// }
|
||||
// Dimensions dimensions;
|
||||
// Dimensions minDimensions;
|
||||
// LayoutConfig *layoutConfig;
|
||||
// ElementConfigArraySlice elementConfigs;
|
||||
// uint configsEnabled;
|
||||
// uint id;
|
||||
// }
|
||||
|
||||
// struct WrappedTextLine
|
||||
// {
|
||||
// Dimensions dimensions;
|
||||
// ClayString line;
|
||||
// }
|
||||
|
||||
// struct WrappedTextLineArraySlice
|
||||
// {
|
||||
// int length;
|
||||
// WrappedTextLine *internalArray;
|
||||
// }
|
||||
|
||||
// struct TextElementData
|
||||
// {
|
||||
// ClayString text;
|
||||
// Dimensions preferredDimensions;
|
||||
// int elementIndex;
|
||||
// WrappedTextLineArraySlice wrappedLines;
|
||||
// }
|
||||
|
||||
// struct ElementConfigArraySlice
|
||||
// {
|
||||
// int length;
|
||||
// ElementConfig *internalArray;
|
||||
// }
|
||||
|
||||
|
||||
// def DebugElementData = bool[<2>];
|
||||
|
||||
// struct LayoutElementHashMapItem
|
||||
// {
|
||||
// ClayBoundingBox boundingBox;
|
||||
// ElementId elementId;
|
||||
// LayoutElement* layoutElement;
|
||||
// OnHoverEvent onHoverFunction;
|
||||
// int128 hoverFunctionUserData;
|
||||
// int nextIndex;
|
||||
// uint128 generation;
|
||||
// DebugElementData *debugData;
|
||||
// }
|
||||
|
||||
// struct LayoutElementTreeRoot @private
|
||||
// {
|
||||
// int layoutElementIndex;
|
||||
// uint parentId; // This can be zero in the case of the root layout tree
|
||||
// uint clipElementId; // This can be zero if there is no clip element
|
||||
// int zIndex;
|
||||
// ClayVector2 pointerOffset; // Only used when scroll containers are managed externally
|
||||
// }
|
||||
|
||||
// struct LayoutElementTreeNode @private
|
||||
// {
|
||||
// LayoutElement *layoutElement;
|
||||
// ClayVector2 position;
|
||||
// ClayVector2 nextChildOffset;
|
||||
// }
|
||||
|
||||
// struct MeasuredWord @private
|
||||
// {
|
||||
// int startOffset;
|
||||
// int length;
|
||||
// float width;
|
||||
// int next;
|
||||
// }
|
||||
|
||||
// struct MeasureTextCacheItem @private
|
||||
// {
|
||||
// Dimensions unwrappedDimensions;
|
||||
// int measuredWordsStartIndex;
|
||||
// bool containsNewlines;
|
||||
// // Hash map data
|
||||
// uint id;
|
||||
// int nextIndex;
|
||||
// uint generation;
|
||||
// }
|
||||
|
||||
// def LayoutElementArray = carray::Array(<LayoutElement>);
|
||||
// def CIntArray = carray::Array(<int>);
|
||||
// def TextElementDataArray = carray::Array(<TextElementData>);
|
||||
// def RectangleElementConfigArray = carray::Array(<RectangleElementConfig>);
|
||||
// def TextElementConfigArray = carray::Array(<TextElementConfig>);
|
||||
// def ImageElementConfigArray = carray::Array(<ImageElementConfig>);
|
||||
// def FloatingElementConfigArray = carray::Array(<FloatingElementConfig>);
|
||||
// def ScrollElementConfigArray = carray::Array(<ScrollElementConfig>);
|
||||
// def CustomElementConfigArray = carray::Array(<CustomElementConfig>);
|
||||
// def BorderElementConfigArray = carray::Array(<BorderElementConfig>);
|
||||
// def LayoutElementPointerArray = carray::Array(<LayoutElement*>);
|
||||
// def LayoutConfigArray = carray::Array(<LayoutConfig>);
|
||||
// def ElementConfigArray = carray::Array(<ElementConfig>);
|
||||
// def WrappedTextLineArray = carray::Array(<WrappedTextLine>);
|
||||
// def LayoutElementTreeNodeArray = carray::Array(<LayoutElementTreeNode>);
|
||||
// def LayoutElementTreeRootArray = carray::Array(<LayoutElementTreeRoot>);
|
||||
// def LayoutElementHashMapItemArray = carray::Array(<LayoutElementHashMapItem>);
|
||||
// def MeasureTextCacheItemArray = carray::Array(<MeasureTextCacheItem>);
|
||||
// def MeasuredWordArray = carray::Array(<MeasuredWord>);
|
||||
// def ElementIdArray = carray::Array(<ElementId>);
|
||||
// def ScrollContainerDataInternalArray = carray::Array(<ScrollContainerData>);
|
||||
// def BoolArray = carray::Array(<bool>);
|
||||
// def CharArray = carray::Array(<char>);
|
||||
// def DebugElementDataArray = carray::Array(<DebugElementData>);
|
||||
|
||||
// struct Context @extern ("Clay_Context")
|
||||
// {
|
||||
// int maxElementCount;
|
||||
// int maxMeasureTextCacheWordCount;
|
||||
// bool warningsEnabled;
|
||||
// ErrorHandler errorHandler;
|
||||
// BooleanWarnings booleanWarnings;
|
||||
// WarningArray warnings;
|
||||
|
||||
// PointerData pointerInfo;
|
||||
// Dimensions layoutDimensions;
|
||||
// ElementId dynamicElementIndexBaseHash;
|
||||
// uint dynamicElementIndex;
|
||||
// bool debugModeEnabled;
|
||||
// bool disableCulling;
|
||||
// bool externalScrollHandlingEnabled;
|
||||
// uint debugSelectedElementId;
|
||||
// uint generation;
|
||||
// uint128 arenaResetOffset;
|
||||
// Arena internalArena;
|
||||
|
||||
// // Layout Elements / Render Commands
|
||||
// LayoutElementArray layoutElements;
|
||||
// RenderCommandArray renderCommands;
|
||||
// CIntArray openLayoutElementStack;
|
||||
// CIntArray layoutElementChildren;
|
||||
// CIntArray layoutElementChildrenBuffer;
|
||||
// TextElementDataArray textElementData;
|
||||
// LayoutElementPointerArray imageElementPointers;
|
||||
// CIntArray reusableElementIndexBuffer;
|
||||
// CIntArray layoutElementClipElementIds;
|
||||
|
||||
// // Configs
|
||||
// LayoutConfigArray layoutConfigs;
|
||||
// ElementConfigArray elementConfigBuffer;
|
||||
// ElementConfigArray elementConfigs;
|
||||
// RectangleElementConfigArray rectangleElementConfigs;
|
||||
// TextElementConfigArray textElementConfigs;
|
||||
// ImageElementConfigArray imageElementConfigs;
|
||||
// FloatingElementConfigArray floatingElementConfigs;
|
||||
// ScrollElementConfigArray scrollElementConfigs;
|
||||
// CustomElementConfigArray customElementConfigs;
|
||||
// BorderElementConfigArray borderElementConfigs;
|
||||
|
||||
// // Misc Data Structures
|
||||
// ClayStringArray layoutElementIdStrings;
|
||||
// WrappedTextLineArray wrappedTextLines;
|
||||
// LayoutElementTreeNodeArray layoutElementTreeNodeArray1;
|
||||
// LayoutElementTreeRootArray layoutElementTreeRoots;
|
||||
// LayoutElementHashMapItemArray layoutElementsHashMapInternal;
|
||||
// CIntArray layoutElementsHashMap;
|
||||
// MeasureTextCacheItemArray measureTextHashMapInternal;
|
||||
// CIntArray measureTextHashMapInternalFreeList;
|
||||
// CIntArray measureTextHashMap;
|
||||
// MeasuredWordArray measuredWords;
|
||||
// CIntArray measuredWordsFreeList;
|
||||
// CIntArray openClipElementStack;
|
||||
// ElementIdArray pointerOverIds;
|
||||
// ScrollContainerDataInternalArray scrollContainerDatas;
|
||||
// BoolArray treeNodeVisited;
|
||||
// CharArray dynamicStringData;
|
||||
// DebugElementDataArray debugElementData;
|
||||
// }
|
||||
|
||||
// def OnHoverEvent = fn void(ElementId elementId, PointerData pointerData, iptr userData);
|
||||
// def MeasureTextFunc = fn Dimensions(ClayString *text, TextElementConfig *config);
|
||||
// def QueryScrollOffsetFunc = fn ClayVector2(uint elementId);
|
||||
|
||||
// // =====================
|
||||
// // ===== FUNCTIONS =====
|
||||
// // =====================
|
||||
|
||||
// // ===== Public Clay API C3 Functions (String replacement) =====
|
||||
// fn ElementId getElementIdWithIndex(String idString, uint index) @export @inline
|
||||
// { return __getElementIdWithIndex({idString.len, idString}, (uint)index); }
|
||||
// fn ElementId getElementId(String idString) @export @inline
|
||||
// { return __getElementId({idString.len, idString}); }
|
||||
|
||||
|
||||
// // ===== Public Clay API Functions =====
|
||||
// extern fn uint minMemorySize() @extern("Clay_MinMemorySize") @wasm @export;
|
||||
// extern fn Arena createArena(uint capacity, void* offset) @extern("Clay_CreateArenaWithCapacityAndMemory") @wasm @export;
|
||||
// extern fn void setPointerState(ClayVector2 position, bool pointerDown) @extern("Clay_SetPointerState") @export;
|
||||
// extern fn Context* initialize(Arena arena, Dimensions layoutDimensions, ErrorHandler errorHandler) @extern("Clay_Initialize") @wasm @export;
|
||||
// extern fn Context* getCurrentContext() @extern("Clay_GetCurrentContext") @export;
|
||||
// extern fn void setCurrentContext(Context* context) @extern("Clay_SetCurrentContext") @export;
|
||||
// extern fn void updateScrollContainer(bool enableDragScrolling, ClayVector2 scrollDelta, float deltaTime) @extern("Clay_UpdateScrollContainers") @export;
|
||||
// extern fn void setLayoutDimensions (Dimensions dimensions) @extern("Clay_SetLayoutDimensions") @export;
|
||||
// extern fn ElementData getElementData(ElementId id) @extern("Clay_GetElementData") @export;
|
||||
// extern fn bool hovered() @extern("Clay_Hovered") @export;
|
||||
// extern fn void onHover(OnHoverEvent onHover, iptr userData) @extern("Clay_OnHover") @export;
|
||||
// extern fn bool pointerOver(ElementId elementId) @extern("Clay_PointerOver") @wasm @export;
|
||||
// extern fn ScrollContainerData getScrollContainerData(ElementId id) @extern("Clay_GetScrollContainerData") @export;
|
||||
// extern fn void setMeasureTextFunction(MeasureTextFunc measureText) @extern("Clay_SetMeasureTextFunction") @export;
|
||||
// extern fn void setQueryScrollOffsetFunction(QueryScrollOffsetFunc queryScrollOffset) @extern("Clay_SetQueryScrollOffsetFunction") @export;
|
||||
// extern fn RenderCommand * RenderCommandArray.get(RenderCommandArray* array, int index) @extern("Clay_RenderCommandArray_Get") @export;
|
||||
// extern fn void setDebugModeEnabled(bool enabled) @extern("Clay_SetDebugModeEnabled") @export;
|
||||
// extern fn bool isDebugModeEnabled() @extern("Clay_IsDebugModeEnabled") @export;
|
||||
// extern fn void setCullingEnabled(bool enabled) @extern("Clay_SetCullingEnabled") @export;
|
||||
// extern fn int getMaxMeasuredTextCachedWordCount() @extern("Clay_GetMaxElementCount") @export;
|
||||
// extern fn void setMaxElementCount(int maxElementCount) @extern("Clay_SetMaxElementCount") @export;
|
||||
// extern fn int getMaxElementCount() @extern("Clay_GetMaxMeasureTextCacheWordCount") @export;
|
||||
// extern fn void setMaxMeasureTextCacheWordCount(int maxMeasureTextCacheWordCount) @extern("Clay_SetMaxMeasureTextCacheWordCount") @export;
|
||||
// extern fn void resetMeasureTextCache() @extern("Clay_ResetMeasureTextCache") @export;
|
||||
// extern fn void beginLayout() @extern("Clay_BeginLayout") @export;
|
||||
// extern fn RenderCommandArray endLayout() @extern("Clay_EndLayout") @export;
|
||||
|
||||
// // ===== (NEW) Internal Clay API Functions (String replacement) =====
|
||||
// extern fn ElementId __getElementIdWithIndex(ClayString idString, uint index) @extern("Clay_GetElementIdWithIndex") @export @private;
|
||||
// extern fn ElementId __getElementId(ClayString idString) @extern("Clay_GetElementId") @export @private;
|
||||
|
||||
// // ===== Internal Clay API Functions =====
|
||||
// extern fn void openElement() @extern ("Clay__OpenElement") @export @private;
|
||||
// extern fn void closeElement() @extern("Clay__CloseElement") @export @private;
|
||||
// extern fn void openTextElement(ClayString text, TextElementConfig *textConfig) @extern("Clay__OpenTextElement") @export @private;
|
||||
// extern fn void elementPostConfiguration() @extern("Clay__ElementPostConfiguration") @export @private;
|
||||
// extern fn LayoutConfig * storeLayoutConfig(LayoutConfig config) @extern("Clay__StoreLayoutConfig") @export @private;
|
||||
// extern fn void attachId(ElementId id) @extern("Clay__AttachId") @export @private;
|
||||
// extern fn void attachLayoutConfig(LayoutConfig *config) @extern("Clay__AttachLayoutConfig") @export @private;
|
||||
// extern fn void attachElementConfig(ElementConfigUnion config, ElementConfigType type) @extern("Clay__AttachElementConfig") @export @private;
|
||||
// extern fn RectangleElementConfig * storeRectangleElementConfig(RectangleElementConfig config) @extern("Clay__StoreRectangleElementConfig") @export @private;
|
||||
// extern fn TextElementConfig * storeTextElementConfig(TextElementConfig config) @extern("Clay__StoreTextElementConfig") @export @private;
|
||||
// extern fn ImageElementConfig * storeImageElementConfig(ImageElementConfig config) @extern("Clay__StoreImageElementConfig") @export @private;
|
||||
// extern fn FloatingElementConfig * storeFloatingElementConfig(FloatingElementConfig config) @extern("Clay__StoreFloatingElementConfig") @export @private;
|
||||
// extern fn CustomElementConfig * storeCustomElementConfig(CustomElementConfig config) @extern("Clay__StoreCustomElementConfig") @export @private;
|
||||
// extern fn ScrollElementConfig * storeScrollElementConfig(ScrollElementConfig config) @extern("Clay__StoreScrollElementConfig") @export @private;
|
||||
// extern fn BorderElementConfig * storeBorderElementConfig(BorderElementConfig config) @extern("Clay__StoreBorderElementConfig") @export @private;
|
||||
// extern fn ElementId hashString(ClayString key, uint offset, uint seed) @extern("Clay__HashString") @export @private;
|
||||
// extern fn uint getParentElementId() @extern("Clay__GetParentElementId") @export @private;
|
||||
|
||||
// // ==========================================================================
|
||||
// // ===== An internal module for wrapping Struct Array's defined in Clay =====
|
||||
// // ==========================================================================
|
||||
// module clay::carray(<ElementType>);
|
||||
|
||||
// struct Array {
|
||||
// int capacity;
|
||||
// int length;
|
||||
// ElementType *data;
|
||||
// }
|
448
bindings/c3/source/clay-raylib-renderer.c3
Normal file
448
bindings/c3/source/clay-raylib-renderer.c3
Normal file
@ -0,0 +1,448 @@
|
||||
module raylib @if($feature(NO_STDLIB));
|
||||
|
||||
distinct ZString = inline char*;
|
||||
|
||||
module clay::renderer;
|
||||
|
||||
import raylib;
|
||||
|
||||
// TODO: this entire file was very rushed so it can probably be cleaned up a LOT
|
||||
fn double calculate_sine(double x) {
|
||||
double term = x;
|
||||
double sum = term;
|
||||
double n = 1;
|
||||
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
term *= (-1) * x * x / ((2 * n) * (2 * n + 1));
|
||||
sum += term;
|
||||
n++;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
fn double calculate_cosine(double x) {
|
||||
double term = 1;
|
||||
double sum = term;
|
||||
double n = 1;
|
||||
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
term *= (-1) * x * x / ((2 * n - 1) * (2 * n));
|
||||
sum += term;
|
||||
n++;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
macro double calculate_tangent(double x) {
|
||||
double sine = calculate_sine(x);
|
||||
double cosine = calculate_cosine(x);
|
||||
// Check for cases where cosine is zero (tangent is undefined)
|
||||
if (cosine == 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
return sine / cosine;
|
||||
}
|
||||
|
||||
|
||||
fn Color clayToRaylibColor(ClayColor color) @inline
|
||||
{
|
||||
return { (char)$$round(color.r), (char)$$round(color.g), (char)$$round(color.b), (char)$$round(color.a)};
|
||||
}
|
||||
|
||||
struct RaylibFont
|
||||
{
|
||||
int fontId;
|
||||
raylib::Font font;
|
||||
}
|
||||
|
||||
RaylibFont[10] raylibFonts;
|
||||
raylib::Camera raylibCamera;
|
||||
|
||||
const Matrix MATRIX_IDENTITY = {
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1,
|
||||
};
|
||||
|
||||
enum CustomLayoutElementType
|
||||
{
|
||||
MODEL_3D
|
||||
}
|
||||
|
||||
struct Model3DLayoutElement
|
||||
{
|
||||
raylib::Model model;
|
||||
float scale;
|
||||
raylib::Vector3 position;
|
||||
raylib::Matrix rotation;
|
||||
}
|
||||
|
||||
struct CustomLayoutElement
|
||||
{
|
||||
CustomLayoutElementType type;
|
||||
union element
|
||||
{
|
||||
Model3DLayoutElement model;
|
||||
}
|
||||
}
|
||||
|
||||
fn Matrix matrixPerspective(double fovY, double aspect, double nearPlane, double farPlane)
|
||||
{
|
||||
Matrix result = { 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 };
|
||||
|
||||
double top = nearPlane * calculate_tangent(fovY*0.5*raylib::RAD2DEG);
|
||||
double bottom = -top;
|
||||
double right = top*aspect;
|
||||
double left = -right;
|
||||
|
||||
// MatrixFrustum(-right, right, -top, top, near, far);
|
||||
float rl = (float)(right - left);
|
||||
float tb = (float)(top - bottom);
|
||||
float far_near = (float)(farPlane - nearPlane);
|
||||
|
||||
result.m0 = ((float)nearPlane*2.0f)/rl;
|
||||
result.m5 = ((float)nearPlane*2.0f)/tb;
|
||||
result.m8 = ((float)right + (float)left)/rl;
|
||||
result.m9 = ((float)top + (float)bottom)/tb;
|
||||
result.m10 = -((float)farPlane + (float)nearPlane)/far_near;
|
||||
result.m11 = -1.0f;
|
||||
result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/far_near;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn Vector3 vector3Unproject(Vector3 source, Matrix projection, Matrix view)
|
||||
{
|
||||
Vector3 result = { 0, 0, 0 };
|
||||
|
||||
// Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it
|
||||
Matrix matViewProj = { // MatrixMultiply(view, projection);
|
||||
view.m0*projection.m0 + view.m1*projection.m4 + view.m2*projection.m8 + view.m3*projection.m12,
|
||||
view.m0*projection.m1 + view.m1*projection.m5 + view.m2*projection.m9 + view.m3*projection.m13,
|
||||
view.m0*projection.m2 + view.m1*projection.m6 + view.m2*projection.m10 + view.m3*projection.m14,
|
||||
view.m0*projection.m3 + view.m1*projection.m7 + view.m2*projection.m11 + view.m3*projection.m15,
|
||||
view.m4*projection.m0 + view.m5*projection.m4 + view.m6*projection.m8 + view.m7*projection.m12,
|
||||
view.m4*projection.m1 + view.m5*projection.m5 + view.m6*projection.m9 + view.m7*projection.m13,
|
||||
view.m4*projection.m2 + view.m5*projection.m6 + view.m6*projection.m10 + view.m7*projection.m14,
|
||||
view.m4*projection.m3 + view.m5*projection.m7 + view.m6*projection.m11 + view.m7*projection.m15,
|
||||
view.m8*projection.m0 + view.m9*projection.m4 + view.m10*projection.m8 + view.m11*projection.m12,
|
||||
view.m8*projection.m1 + view.m9*projection.m5 + view.m10*projection.m9 + view.m11*projection.m13,
|
||||
view.m8*projection.m2 + view.m9*projection.m6 + view.m10*projection.m10 + view.m11*projection.m14,
|
||||
view.m8*projection.m3 + view.m9*projection.m7 + view.m10*projection.m11 + view.m11*projection.m15,
|
||||
view.m12*projection.m0 + view.m13*projection.m4 + view.m14*projection.m8 + view.m15*projection.m12,
|
||||
view.m12*projection.m1 + view.m13*projection.m5 + view.m14*projection.m9 + view.m15*projection.m13,
|
||||
view.m12*projection.m2 + view.m13*projection.m6 + view.m14*projection.m10 + view.m15*projection.m14,
|
||||
view.m12*projection.m3 + view.m13*projection.m7 + view.m14*projection.m11 + view.m15*projection.m15 };
|
||||
|
||||
// Calculate inverted matrix . MatrixInvert(matViewProj);
|
||||
// Cache the matrix values (speed optimization)
|
||||
float a00 = matViewProj.m0;
|
||||
float a01 = matViewProj.m1;
|
||||
float a02 = matViewProj.m2;
|
||||
float a03 = matViewProj.m3;
|
||||
float a10 = matViewProj.m4;
|
||||
float a11 = matViewProj.m5;
|
||||
float a12 = matViewProj.m6;
|
||||
float a13 = matViewProj.m7;
|
||||
float a20 = matViewProj.m8;
|
||||
float a21 = matViewProj.m9;
|
||||
float a22 = matViewProj.m10;
|
||||
float a23 = matViewProj.m11;
|
||||
float a30 = matViewProj.m12;
|
||||
float a31 = matViewProj.m13;
|
||||
float a32 = matViewProj.m14;
|
||||
float a33 = matViewProj.m15;
|
||||
|
||||
float b00 = a00*a11 - a01*a10;
|
||||
float b01 = a00*a12 - a02*a10;
|
||||
float b02 = a00*a13 - a03*a10;
|
||||
float b03 = a01*a12 - a02*a11;
|
||||
float b04 = a01*a13 - a03*a11;
|
||||
float b05 = a02*a13 - a03*a12;
|
||||
float b06 = a20*a31 - a21*a30;
|
||||
float b07 = a20*a32 - a22*a30;
|
||||
float b08 = a20*a33 - a23*a30;
|
||||
float b09 = a21*a32 - a22*a31;
|
||||
float b10 = a21*a33 - a23*a31;
|
||||
float b11 = a22*a33 - a23*a32;
|
||||
|
||||
// Calculate the invert determinant (inlined to avoid double-caching)
|
||||
float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
|
||||
|
||||
Matrix matViewProjInv = {
|
||||
(a11*b11 - a12*b10 + a13*b09)*invDet,
|
||||
(-a01*b11 + a02*b10 - a03*b09)*invDet,
|
||||
(a31*b05 - a32*b04 + a33*b03)*invDet,
|
||||
(-a21*b05 + a22*b04 - a23*b03)*invDet,
|
||||
(-a10*b11 + a12*b08 - a13*b07)*invDet,
|
||||
(a00*b11 - a02*b08 + a03*b07)*invDet,
|
||||
(-a30*b05 + a32*b02 - a33*b01)*invDet,
|
||||
(a20*b05 - a22*b02 + a23*b01)*invDet,
|
||||
(a10*b10 - a11*b08 + a13*b06)*invDet,
|
||||
(-a00*b10 + a01*b08 - a03*b06)*invDet,
|
||||
(a30*b04 - a31*b02 + a33*b00)*invDet,
|
||||
(-a20*b04 + a21*b02 - a23*b00)*invDet,
|
||||
(-a10*b09 + a11*b07 - a12*b06)*invDet,
|
||||
(a00*b09 - a01*b07 + a02*b06)*invDet,
|
||||
(-a30*b03 + a31*b01 - a32*b00)*invDet,
|
||||
(a20*b03 - a21*b01 + a22*b00)*invDet };
|
||||
|
||||
// Create quaternion from source point
|
||||
raylib::Quaternion quat = { source.x, source.y, source.z, 1.0f };
|
||||
|
||||
// Multiply quat point by unprojecte matrix
|
||||
raylib::Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv)
|
||||
matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w,
|
||||
matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w,
|
||||
matViewProjInv.m2*quat.x + matViewProjInv.m6*quat.y + matViewProjInv.m10*quat.z + matViewProjInv.m14*quat.w,
|
||||
matViewProjInv.m3*quat.x + matViewProjInv.m7*quat.y + matViewProjInv.m11*quat.z + matViewProjInv.m15*quat.w };
|
||||
|
||||
// Normalized world points in vectors
|
||||
result.x = qtransformed.x/qtransformed.w;
|
||||
result.y = qtransformed.y/qtransformed.w;
|
||||
result.z = qtransformed.z/qtransformed.w;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn Matrix matrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane)
|
||||
{
|
||||
Matrix result = { 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 };
|
||||
|
||||
float rl = (float)(right - left);
|
||||
float tb = (float)(top - bottom);
|
||||
float far_near = (float)(farPlane - nearPlane);
|
||||
|
||||
result.m0 = 2.0f/rl;
|
||||
result.m1 = 0.0f;
|
||||
result.m2 = 0.0f;
|
||||
result.m3 = 0.0f;
|
||||
result.m4 = 0.0f;
|
||||
result.m5 = 2.0f/tb;
|
||||
result.m6 = 0.0f;
|
||||
result.m7 = 0.0f;
|
||||
result.m8 = 0.0f;
|
||||
result.m9 = 0.0f;
|
||||
result.m10 = -2.0f/far_near;
|
||||
result.m11 = 0.0f;
|
||||
result.m12 = -((float)left + (float)right)/rl;
|
||||
result.m13 = -((float)top + (float)bottom)/tb;
|
||||
result.m14 = -((float)farPlane + (float)nearPlane)/far_near;
|
||||
result.m15 = 1.0f;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn Vector3 vector3Normalize(Vector3 v)
|
||||
{
|
||||
Vector3 result = v;
|
||||
|
||||
float length = $$sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
|
||||
if (length != 0.0f)
|
||||
{
|
||||
float ilength = 1.0f/length;
|
||||
|
||||
result.x *= ilength;
|
||||
result.y *= ilength;
|
||||
result.z *= ilength;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn Vector3 vector3Subtract(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
fn Ray getScreenToWorldPointWithZDistance(Vector2 position, Camera camera, int screenWidth, int screenHeight, float zDistance)
|
||||
{
|
||||
Ray ray = { {0,0,0}, {0,0,0} };
|
||||
float x = (2.0f*position.x)/(float)screenWidth - 1.0f;
|
||||
float y = 1.0f - (2.0f*position.y)/(float)screenHeight;
|
||||
float z = 1.0f;
|
||||
|
||||
// Store values in a vector
|
||||
Vector3 deviceCoords = { x, y, z };
|
||||
|
||||
// Calculate view matrix from camera look at
|
||||
Matrix matView = raylib::getCameraMatrix(camera);
|
||||
|
||||
Matrix matProj = MATRIX_IDENTITY;
|
||||
|
||||
if (camera.projection == CameraProjection.PERSPECTIVE)
|
||||
{
|
||||
// Calculate projection matrix from perspective
|
||||
matProj = matrixPerspective((double)(camera.fovy*raylib::DEG2RAD), ((double)screenWidth/(double)screenHeight), 0.01f, zDistance);
|
||||
}
|
||||
else if (camera.projection == CameraProjection.ORTHOGRAPHIC)
|
||||
{
|
||||
double aspect = (double)screenWidth/(double)screenHeight;
|
||||
double top = camera.fovy/2.0;
|
||||
double right = top*aspect;
|
||||
|
||||
// Calculate projection matrix from orthographic
|
||||
matProj = matrixOrtho(-right, right, -top, top, 0.01, 1000.0);
|
||||
}
|
||||
|
||||
// Unproject far/near points
|
||||
Vector3 nearPoint = vector3Unproject({ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView);
|
||||
Vector3 farPoint = vector3Unproject({ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
|
||||
|
||||
// Calculate normalized direction vector
|
||||
Vector3 direction = vector3Normalize(vector3Subtract(farPoint, nearPoint));
|
||||
|
||||
ray.position = farPoint;
|
||||
|
||||
// Apply calculated vectors to ray
|
||||
ray.direction = direction;
|
||||
|
||||
return ray;
|
||||
}
|
||||
|
||||
fn Dimensions raylibMeasureText(ClayString *text, TextElementConfig *config)
|
||||
{
|
||||
// Measure string size for Font
|
||||
Dimensions textSize = { 0, 0 };
|
||||
|
||||
float maxTextWidth = 0.0f;
|
||||
float lineTextWidth = 0;
|
||||
|
||||
float textHeight = config.fontSize;
|
||||
Font fontToUse = raylibFonts[config.fontId].font;
|
||||
float scaleFactor = config.fontSize/(float)fontToUse.baseSize;
|
||||
|
||||
for (int i = 0; i < text.length; ++i)
|
||||
{
|
||||
if (text.chars[i] == '\n') {
|
||||
maxTextWidth = $$max(maxTextWidth, lineTextWidth);
|
||||
lineTextWidth = 0;
|
||||
continue;
|
||||
}
|
||||
int index = text.chars[i] - 32;
|
||||
if (fontToUse.glyphs[index].advanceX != 0) {lineTextWidth += fontToUse.glyphs[index].advanceX;}
|
||||
else {lineTextWidth += (fontToUse.recs[index].width + fontToUse.glyphs[index].offsetX);}
|
||||
}
|
||||
|
||||
maxTextWidth = $$max(maxTextWidth, lineTextWidth);
|
||||
|
||||
textSize.width = maxTextWidth * scaleFactor;
|
||||
textSize.height = textHeight;
|
||||
|
||||
return textSize;
|
||||
}
|
||||
|
||||
fn void raylibRender(RenderCommandArray renderCommands)
|
||||
{
|
||||
for (int j = 0; j < renderCommands.length; j++)
|
||||
{
|
||||
RenderCommand *renderCommand = renderCommands.get(j);
|
||||
ClayBoundingBox boundingBox = renderCommand.boundingBox;
|
||||
switch (renderCommand.commandType)
|
||||
{
|
||||
case RenderCommandType.TEXT: {
|
||||
// Raylib uses standard C strings so isn't compatible with cheap slices, we need to clone the string to append null terminator
|
||||
ClayString text = renderCommand.text;
|
||||
ZString cloned = (ZString)malloc((ulong)text.length + 1);
|
||||
$$memcpy(cloned, text.chars, (isz)text.length, false, (isz)0, (isz)0);
|
||||
cloned[text.length] = '\0';
|
||||
Font fontToUse = raylibFonts[renderCommand.config.textElementConfig.fontId].font;
|
||||
raylib::drawTextEx(fontToUse, cloned, {boundingBox.x, boundingBox.y}, (float)renderCommand.config.textElementConfig.fontSize, (float)renderCommand.config.textElementConfig.letterSpacing, clayToRaylibColor(renderCommand.config.textElementConfig.textColor));
|
||||
free(cloned);
|
||||
break;
|
||||
}
|
||||
case RenderCommandType.IMAGE: {
|
||||
Texture2D imageTexture = *(Texture2D *)renderCommand.config.imageElementConfig.imageData;
|
||||
raylib::drawTextureEx(
|
||||
imageTexture,
|
||||
{boundingBox.x, boundingBox.y},
|
||||
0,
|
||||
boundingBox.width / (float)imageTexture.width,
|
||||
raylib::WHITE);
|
||||
break;
|
||||
}
|
||||
case RenderCommandType.SCISSOR_START: {
|
||||
raylib::beginScissorMode((int)$$round(boundingBox.x), (int)$$round(boundingBox.y), (int)$$round(boundingBox.width), (int)$$round(boundingBox.height));
|
||||
break;
|
||||
}
|
||||
case RenderCommandType.SCISSOR_END: {
|
||||
raylib::endScissorMode();
|
||||
break;
|
||||
}
|
||||
case RenderCommandType.RECTANGLE: {
|
||||
RectangleElementConfig *config = renderCommand.config.rectangleElementConfig;
|
||||
if (config.cornerRadius.topLeft > 0) {
|
||||
float radius = (config.cornerRadius.topLeft * 2) / (float)(boundingBox.width > boundingBox.height ? boundingBox.height : boundingBox.width);
|
||||
raylib::drawRectangleRounded({ boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height }, radius, 8, clayToRaylibColor(config.color));
|
||||
} else {
|
||||
raylib::drawRectangle((int)$$round(boundingBox.x), (int)$$round(boundingBox.y), (int)$$round(boundingBox.width), (int)$$round(boundingBox.height), clayToRaylibColor(config.color));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RenderCommandType.BORDER: {
|
||||
BorderElementConfig *config = renderCommand.config.borderElementConfig;
|
||||
// Left border
|
||||
if (config.left.width > 0) {
|
||||
raylib::drawRectangle((int)$$round(boundingBox.x), (int)$$round(boundingBox.y + config.cornerRadius.topLeft), (int)config.left.width, (int)$$round(boundingBox.height - config.cornerRadius.topLeft - config.cornerRadius.bottomLeft), clayToRaylibColor(config.left.color));
|
||||
}
|
||||
// Right border
|
||||
if (config.right.width > 0) {
|
||||
raylib::drawRectangle((int)$$round(boundingBox.x + boundingBox.width - config.right.width), (int)$$round(boundingBox.y + config.cornerRadius.topRight), (int)config.right.width, (int)$$round(boundingBox.height - config.cornerRadius.topRight - config.cornerRadius.bottomRight), clayToRaylibColor(config.right.color));
|
||||
}
|
||||
// Top border
|
||||
if (config.top.width > 0) {
|
||||
raylib::drawRectangle((int)$$round(boundingBox.x + config.cornerRadius.topLeft), (int)$$round(boundingBox.y), (int)$$round(boundingBox.width - config.cornerRadius.topLeft - config.cornerRadius.topRight), (int)config.top.width, clayToRaylibColor(config.top.color));
|
||||
}
|
||||
// Bottom border
|
||||
if (config.bottom.width > 0) {
|
||||
raylib::drawRectangle((int)$$round(boundingBox.x + config.cornerRadius.bottomLeft), (int)$$round(boundingBox.y + boundingBox.height - config.bottom.width), (int)$$round(boundingBox.width - config.cornerRadius.bottomLeft - config.cornerRadius.bottomRight), (int)config.bottom.width, clayToRaylibColor(config.bottom.color));
|
||||
}
|
||||
if (config.cornerRadius.topLeft > 0) {
|
||||
raylib::drawRing({ $$round(boundingBox.x + config.cornerRadius.topLeft), $$round(boundingBox.y + config.cornerRadius.topLeft) }, $$round(config.cornerRadius.topLeft - config.top.width), config.cornerRadius.topLeft, 180, 270, 10, clayToRaylibColor(config.top.color));
|
||||
}
|
||||
if (config.cornerRadius.topRight > 0) {
|
||||
raylib::drawRing({ $$round(boundingBox.x + boundingBox.width - config.cornerRadius.topRight), $$round(boundingBox.y + config.cornerRadius.topRight) }, $$round(config.cornerRadius.topRight - config.top.width), config.cornerRadius.topRight, 270, 360, 10, clayToRaylibColor(config.top.color));
|
||||
}
|
||||
if (config.cornerRadius.bottomLeft > 0) {
|
||||
raylib::drawRing({ $$round(boundingBox.x + config.cornerRadius.bottomLeft), $$round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomLeft) }, $$round(config.cornerRadius.bottomLeft - config.top.width), config.cornerRadius.bottomLeft, 90, 180, 10, clayToRaylibColor(config.bottom.color));
|
||||
}
|
||||
if (config.cornerRadius.bottomRight > 0) {
|
||||
raylib::drawRing({ $$round(boundingBox.x + boundingBox.width - config.cornerRadius.bottomRight), $$round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomRight) }, $$round(config.cornerRadius.bottomRight - config.bottom.width), config.cornerRadius.bottomRight, 0.1, 90, 10, clayToRaylibColor(config.bottom.color));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RenderCommandType.CUSTOM: {
|
||||
CustomLayoutElement *customElement = (CustomLayoutElement *)renderCommand.config.customElementConfig.customData;
|
||||
if (!customElement) continue;
|
||||
switch (customElement.type) {
|
||||
case CustomLayoutElementType.MODEL_3D: {
|
||||
ClayBoundingBox rootBox = renderCommands.data[0].boundingBox;
|
||||
float scaleValue = $$min($$min(1f, 768f / rootBox.height) * $$max(1f, rootBox.width / 1024f), 1.5f);
|
||||
Ray positionRay = getScreenToWorldPointWithZDistance({ renderCommand.boundingBox.x + renderCommand.boundingBox.width / 2, renderCommand.boundingBox.y + (renderCommand.boundingBox.height / 2) + 20 }, raylibCamera, (int)$$round(rootBox.width), (int)$$round(rootBox.height), 140);
|
||||
raylib::beginMode3D(raylibCamera);
|
||||
raylib::drawModel(customElement.element.model.model, positionRay.position, customElement.element.model.scale * scaleValue, raylib::WHITE); // Draw 3d model with texture
|
||||
raylib::endMode3D();
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// std::io::printfn("ERROR: unhandled render command."); TODO: maybe make a workout for this
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
478
bindings/c3/source/clay.c3
Normal file
478
bindings/c3/source/clay.c3
Normal file
@ -0,0 +1,478 @@
|
||||
module clay;
|
||||
|
||||
import clay::carray;
|
||||
|
||||
macro @clay(...; @body()) @builtin
|
||||
{
|
||||
clay::openElement();
|
||||
$for (var $i = 0; $i < $vacount; $i++)
|
||||
$vaexpr[$i]; // If you get an error here consisder the @body[...]() macros
|
||||
$endfor
|
||||
clay::elementPostConfiguration();
|
||||
@body();
|
||||
clay::closeElement();
|
||||
}
|
||||
|
||||
macro text(String text, TextElementConfig *config) { clay::openTextElement({text.len, text}, config); }
|
||||
|
||||
<*Provides you conditional calls (eg #booleanCondition ? #doA : 0) within the condifuration of @clay(...)*>
|
||||
macro @bodyIf(#condition, #ifRes) { if (#condition) { #ifRes; } }
|
||||
|
||||
<*Provides you conditional calls (eg #booleanCondition ? #doA : #doB) within the condifuration of @clay(...)*>
|
||||
macro @bodyIfElse(#condition, #ifRes, #elseRes) { if (#condition) { #ifRes; } else { #elseRes; } }
|
||||
|
||||
<*attaches a RectangleElementConfig to the clay element when called within @clay(...)*>
|
||||
macro rectangle(RectangleElementConfig config) { clay::attachElementConfig({ .rectangleElementConfig = clay::storeRectangleElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_RECTANGLE ); }
|
||||
|
||||
<*attaches a LayoutConfig to the clay element when called within @clay(...)*>
|
||||
macro layout(LayoutConfig config) { clay::attachLayoutConfig( clay::storeLayoutConfig(config) ); }
|
||||
|
||||
<*attaches a LayoutConfig to the clay element when called within @clay(...)*>
|
||||
macro scroll(ScrollElementConfig config) { clay::attachElementConfig({ .scrollElementConfig = clay::storeScrollElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER ); }
|
||||
|
||||
<*attaches a FloatingElementConfig to the clay element when called within @clay(...)*>
|
||||
macro floating(FloatingElementConfig config) { clay::attachElementConfig({ .floatingElementConfig = clay::storeFloatingElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER ); }
|
||||
|
||||
<*attaches a BorderElementConfig to the clay element when called within @clay(...)*>
|
||||
macro @borderRadiusUni(uint #width, ClayColor #color, float #cornerRadius = 0) { clay::attachElementConfig({ .borderElementConfig = clay::storeBorderElementConfig({ .left = { #width, #color }, .right = { #width, #color }, .top = { #width, #color }, .bottom = { #width, #color }, .#cornerRadius = {#cornerRadius, #cornerRadius, #cornerRadius, #cornerRadius}})}, clay::ELEMENT_CONFIG_TYPE_BORDER_CONTAINER); }
|
||||
|
||||
macro id(String idString) { clay::attachId(clay::hashString({idString.len, idString}, 0, 0)); }
|
||||
|
||||
macro TextElementConfig* textConfig(TextElementConfig config) { return clay::storeTextElementConfig(config); }
|
||||
|
||||
macro SizingAxis sizingFit(float min = 0, float max = float.max) { return { .size.minMax = {min, max}, .type = SizingType.FIT }; }
|
||||
|
||||
macro SizingAxis sizingGrow() { return { .size.minMax = {0, 0}, .type = SizingType.GROW }; }
|
||||
|
||||
macro SizingAxis sizingFixed(float pixels) { return { .size.minMax = {pixels, pixels}, .type = SizingType.FIXED }; }
|
||||
|
||||
macro SizingAxis sizingPercent(float percent) { return { .size.percent = percent, .type = SizingType.PERCENT }; }
|
||||
|
||||
macro Padding paddingUni(ushort uniform) { return {uniform, uniform, uniform, uniform}; }
|
||||
|
||||
macro Padding padding(ushort horizontal, ushort vertical) { return {horizontal, horizontal, vertical, vertical}; }
|
||||
|
||||
macro CornerRadius cornerRadiusUni(float uniform) { return {uniform, uniform, uniform, uniform}; }
|
||||
|
||||
macro SizingAxis sizingFitCT(float $min = 0, float $max = float.max) { return { .size.minMax = {$min, $max}, .type = SizingType.FIT }; }
|
||||
|
||||
macro SizingAxis sizingFixedCT(float $pixels) { return { .size.minMax = {$pixels, $pixels}, .type = SizingType.FIXED }; }
|
||||
|
||||
macro SizingAxis sizingPercentCT(float $percent) { return { .size.percent = $percent, .type = SizingType.PERCENT }; }
|
||||
|
||||
macro Padding paddingCT(ushort $a, ushort $b, ushort $c, ushort $d) { return { $a, $b, $c, $d }; }
|
||||
|
||||
macro CornerRadius @cornerRadiusUniCT(float #uniform) { return {#uniform, #uniform, #uniform, #uniform}; }
|
||||
|
||||
struct ClayString
|
||||
{
|
||||
int length;
|
||||
char *chars;
|
||||
}
|
||||
def ClayStringArray = carray::Array(<ClayString>) @private;
|
||||
|
||||
struct Arena
|
||||
{
|
||||
uint128 nextAllocation;
|
||||
uint128 capacity;
|
||||
char *memory;
|
||||
}
|
||||
|
||||
struct Dimensions
|
||||
{
|
||||
float width, height;
|
||||
}
|
||||
|
||||
struct ClayVector2
|
||||
{
|
||||
float x, y;
|
||||
}
|
||||
|
||||
struct ClayColor
|
||||
{
|
||||
float r, g, b, a;
|
||||
}
|
||||
|
||||
|
||||
struct ElementId
|
||||
{
|
||||
uint id;
|
||||
uint offset;
|
||||
uint baseId;
|
||||
ClayString stringId;
|
||||
}
|
||||
|
||||
struct CornerRadius
|
||||
{
|
||||
float topLeft;
|
||||
float topRight;
|
||||
float bottomLeft;
|
||||
float bottomRight;
|
||||
}
|
||||
distinct ElementConfigType @private = char;
|
||||
const ElementConfigType ELEMENT_CONFIG_TYPE_NONE @private = 0;
|
||||
const ElementConfigType ELEMENT_CONFIG_TYPE_RECTANGLE @private = 1;
|
||||
const ElementConfigType ELEMENT_CONFIG_TYPE_BORDER_CONTAINER @private = 2;
|
||||
const ElementConfigType ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER @private = 4;
|
||||
const ElementConfigType ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER @private = 8;
|
||||
const ElementConfigType ELEMENT_CONFIG_TYPE_IMAGE @private = 16;
|
||||
const ElementConfigType ELEMENT_CONFIG_TYPE_TEXT @private = 32;
|
||||
const ElementConfigType ELEMENT_CONFIG_TYPE_CUSTOM @private = 64;
|
||||
|
||||
enum LayoutDirection : char @export
|
||||
{
|
||||
LEFT_TO_RIGHT,
|
||||
TOP_TO_BOTTOM,
|
||||
}
|
||||
|
||||
enum AlignX : char @export
|
||||
{
|
||||
LEFT,
|
||||
RIGHT,
|
||||
CENTER,
|
||||
}
|
||||
|
||||
enum AlignY : char @export
|
||||
{
|
||||
TOP,
|
||||
BOTTOM,
|
||||
CENTER,
|
||||
}
|
||||
|
||||
enum SizingType : char @export
|
||||
{
|
||||
FIT,
|
||||
GROW,
|
||||
PERCENT,
|
||||
FIXED,
|
||||
}
|
||||
|
||||
struct ChildAlignment
|
||||
{
|
||||
AlignX x;
|
||||
AlignY y;
|
||||
}
|
||||
|
||||
struct SizingMinMax
|
||||
{
|
||||
float min;
|
||||
float max;
|
||||
}
|
||||
|
||||
struct SizingAxis
|
||||
{
|
||||
union size
|
||||
{
|
||||
SizingMinMax minMax;
|
||||
float percent;
|
||||
}
|
||||
SizingType type;
|
||||
}
|
||||
|
||||
struct Sizing
|
||||
{
|
||||
SizingAxis width;
|
||||
SizingAxis height;
|
||||
}
|
||||
|
||||
struct Padding
|
||||
{
|
||||
ushort left;
|
||||
ushort right;
|
||||
ushort top;
|
||||
ushort bottom;
|
||||
}
|
||||
|
||||
struct LayoutConfig
|
||||
{
|
||||
Sizing sizing;
|
||||
Padding padding;
|
||||
ushort childGap;
|
||||
ChildAlignment childAlignment;
|
||||
LayoutDirection layoutDirection;
|
||||
}
|
||||
|
||||
struct RectangleElementConfig
|
||||
{
|
||||
ClayColor color;
|
||||
CornerRadius cornerRadius;
|
||||
// #ifdef CLAY_EXTEND_CONFIG_RECTANGLE
|
||||
// CLAY_EXTEND_CONFIG_RECTANGLE
|
||||
// #endif
|
||||
}
|
||||
|
||||
enum WrapMode @export
|
||||
{
|
||||
WORDS,
|
||||
NEWLINES,
|
||||
NONE,
|
||||
}
|
||||
|
||||
struct TextElementConfig
|
||||
{
|
||||
ClayColor textColor;
|
||||
ushort fontId;
|
||||
ushort fontSize;
|
||||
ushort letterSpacing;
|
||||
ushort lineHeight;
|
||||
WrapMode wrapMode;
|
||||
// #ifdef CLAY_EXTEND_CONFIG_TEXT
|
||||
// CLAY_EXTEND_CONFIG_TEXT
|
||||
// #endif
|
||||
}
|
||||
|
||||
struct ImageElementConfig
|
||||
{
|
||||
void *imageData;
|
||||
Dimensions sourceDimensions;
|
||||
// #ifdef CLAY_EXTEND_CONFIG_IMAGE
|
||||
// CLAY_EXTEND_CONFIG_IMAGE
|
||||
// #endif
|
||||
}
|
||||
|
||||
enum AttachPoint : char @export
|
||||
{
|
||||
LEFT_TOP,
|
||||
LEFT_CENTER,
|
||||
LEFT_BOTTOM,
|
||||
CENTER_TOP,
|
||||
CENTER_CENTER,
|
||||
CENTER_BOTTOM,
|
||||
RIGHT_TOP,
|
||||
RIGHT_CENTER,
|
||||
RIGHT_BOTTOM,
|
||||
}
|
||||
|
||||
struct FloatingAttachPoints
|
||||
{
|
||||
AttachPoint element;
|
||||
AttachPoint parent;
|
||||
}
|
||||
|
||||
enum PointerCaptureMode @export
|
||||
{
|
||||
CAPTURE,
|
||||
// MODE_PASSTHROUGH,
|
||||
PARENT,
|
||||
}
|
||||
|
||||
struct FloatingElementConfig
|
||||
{
|
||||
ClayVector2 offset;
|
||||
Dimensions expand;
|
||||
ushort zIndex;
|
||||
uint parentId;
|
||||
FloatingAttachPoints attachment;
|
||||
PointerCaptureMode pointerCaptureMode;
|
||||
}
|
||||
|
||||
|
||||
struct CustomElementConfig
|
||||
{
|
||||
void *customData;
|
||||
}
|
||||
|
||||
struct ScrollElementConfig
|
||||
{
|
||||
bool horizontal;
|
||||
bool vertical;
|
||||
}
|
||||
|
||||
// Border
|
||||
struct Border
|
||||
{
|
||||
uint width;
|
||||
ClayColor color;
|
||||
}
|
||||
|
||||
struct BorderElementConfig
|
||||
{
|
||||
Border left;
|
||||
Border right;
|
||||
Border top;
|
||||
Border bottom;
|
||||
Border betweenChildren;
|
||||
CornerRadius cornerRadius;
|
||||
}
|
||||
|
||||
union ElementConfigUnion
|
||||
{
|
||||
RectangleElementConfig *rectangleElementConfig;
|
||||
TextElementConfig *textElementConfig;
|
||||
ImageElementConfig *imageElementConfig;
|
||||
FloatingElementConfig *floatingElementConfig;
|
||||
CustomElementConfig *customElementConfig;
|
||||
ScrollElementConfig *scrollElementConfig;
|
||||
BorderElementConfig *borderElementConfig;
|
||||
}
|
||||
|
||||
struct ElementConfig
|
||||
{
|
||||
ElementConfigType type;
|
||||
ElementConfigUnion config;
|
||||
}
|
||||
|
||||
struct ClayBoundingBox
|
||||
{
|
||||
float x, y, width, height;
|
||||
}
|
||||
|
||||
enum RenderCommandType : char @export
|
||||
{
|
||||
NONE,
|
||||
RECTANGLE,
|
||||
BORDER,
|
||||
TEXT,
|
||||
IMAGE,
|
||||
SCISSOR_START,
|
||||
SCISSOR_END,
|
||||
CUSTOM,
|
||||
}
|
||||
|
||||
struct RenderCommand
|
||||
{
|
||||
ClayBoundingBox boundingBox;
|
||||
ElementConfigUnion config;
|
||||
ClayString text;
|
||||
uint id;
|
||||
RenderCommandType commandType;
|
||||
}
|
||||
def RenderCommandArray = carray::Array(<RenderCommand>);
|
||||
|
||||
struct ScrollContainerData
|
||||
{
|
||||
// Note: This is a pointer to the real internal scroll position, mutating it may cause a change in final layout.
|
||||
// Intended for use with external functionality that modifies scroll position, such as scroll bars or auto scrolling.
|
||||
ClayVector2 *scrollPosition;
|
||||
Dimensions scrollContainerDimensions;
|
||||
Dimensions contentDimensions;
|
||||
ScrollElementConfig config;
|
||||
// Indicates whether an actual scroll container matched the provided ID or if the default struct was returned.
|
||||
bool found;
|
||||
}
|
||||
|
||||
struct ElementData
|
||||
{
|
||||
ClayBoundingBox boundingBox;
|
||||
// Indicates whether an actual Element matched the provided ID or if the default struct was returned.
|
||||
bool found;
|
||||
}
|
||||
|
||||
enum PointerState @export
|
||||
{
|
||||
PRESSED_THIS_FRAME,
|
||||
PRESSED,
|
||||
RELEASED_THIS_FRAME,
|
||||
RELEASED,
|
||||
}
|
||||
|
||||
struct PointerData
|
||||
{
|
||||
ClayVector2 position;
|
||||
PointerState state;
|
||||
}
|
||||
|
||||
def OnHoverEvent = fn void(ElementId elementId, PointerData pointerData, iptr userData);
|
||||
def MeasureTextFunc = fn Dimensions(ClayString *text, TextElementConfig *config);
|
||||
def QueryScrollOffsetFunc = fn ClayVector2(uint elementId);
|
||||
|
||||
enum ErrorType @export
|
||||
{
|
||||
TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED,
|
||||
ARENA_CAPACITY_EXCEEDED,
|
||||
ELEMENTS_CAPACITY_EXCEEDED,
|
||||
TEXT_MEASUREMENT_CAPACITY_EXCEEDED,
|
||||
DUPLICATE_ID,
|
||||
FLOATING_CONTAINER_PARENT_NOT_FOUND,
|
||||
INTERNAL_ERROR,
|
||||
}
|
||||
|
||||
struct ErrorData
|
||||
{
|
||||
ErrorType errorType;
|
||||
ClayString errorText;
|
||||
uint128 userData;
|
||||
}
|
||||
|
||||
def ErrorHandleFunc = fn void(ErrorData errorText);
|
||||
|
||||
struct ErrorHandler
|
||||
{
|
||||
ErrorHandleFunc errorHandler;
|
||||
uint128 userData;
|
||||
}
|
||||
|
||||
distinct Context = void; // I'm not doing all that again
|
||||
|
||||
// =====================
|
||||
// ===== FUNCTIONS =====
|
||||
// =====================
|
||||
|
||||
// ===== Public Clay API C3 Functions (String replacement) ===== // TODO @export and @wasm can be ignored rn
|
||||
// I haven't been able to get c3c and c compilations to work together for wasm32 or a c3 library
|
||||
fn ElementId getElementIdWithIndex(String idString, uint index) @export @inline
|
||||
{ return __getElementIdWithIndex({idString.len, idString}, (uint)index); }
|
||||
fn ElementId getElementId(String idString) @export @inline
|
||||
{ return __getElementId({idString.len, idString}); }
|
||||
|
||||
// ===== Public Clay API Functions =====
|
||||
extern fn uint minMemorySize() @extern("Clay_MinMemorySize") @wasm @export;
|
||||
extern fn Arena createArena(uint capacity, void* offset) @extern("Clay_CreateArenaWithCapacityAndMemory") @wasm @export;
|
||||
extern fn void setPointerState(ClayVector2 position, bool pointerDown) @extern("Clay_SetPointerState") @export;
|
||||
extern fn Context* initialize(Arena arena, Dimensions layoutDimensions, ErrorHandler errorHandler) @extern("Clay_Initialize") @wasm @export;
|
||||
extern fn Context* getCurrentContext() @extern("Clay_GetCurrentContext") @export;
|
||||
extern fn void setCurrentContext(Context* context) @extern("Clay_SetCurrentContext") @export;
|
||||
extern fn void updateScrollContainer(bool enableDragScrolling, ClayVector2 scrollDelta, float deltaTime) @extern("Clay_UpdateScrollContainers") @export;
|
||||
extern fn void setLayoutDimensions (Dimensions dimensions) @extern("Clay_SetLayoutDimensions") @export;
|
||||
extern fn ElementData getElementData(ElementId id) @extern("Clay_GetElementData") @export;
|
||||
extern fn bool hovered() @extern("Clay_Hovered") @export;
|
||||
extern fn void onHover(OnHoverEvent onHover, iptr userData) @extern("Clay_OnHover") @export;
|
||||
extern fn bool pointerOver(ElementId elementId) @extern("Clay_PointerOver") @wasm @export;
|
||||
extern fn ScrollContainerData getScrollContainerData(ElementId id) @extern("Clay_GetScrollContainerData") @export;
|
||||
extern fn void setMeasureTextFunction(MeasureTextFunc measureText) @extern("Clay_SetMeasureTextFunction") @export;
|
||||
extern fn void setQueryScrollOffsetFunction(QueryScrollOffsetFunc queryScrollOffset) @extern("Clay_SetQueryScrollOffsetFunction") @export;
|
||||
extern fn RenderCommand * RenderCommandArray.get(RenderCommandArray* array, int index) @extern("Clay_RenderCommandArray_Get") @export;
|
||||
extern fn void setDebugModeEnabled(bool enabled) @extern("Clay_SetDebugModeEnabled") @export;
|
||||
extern fn bool isDebugModeEnabled() @extern("Clay_IsDebugModeEnabled") @export;
|
||||
extern fn void setCullingEnabled(bool enabled) @extern("Clay_SetCullingEnabled") @export;
|
||||
extern fn int getMaxMeasuredTextCachedWordCount() @extern("Clay_GetMaxElementCount") @export;
|
||||
extern fn void setMaxElementCount(int maxElementCount) @extern("Clay_SetMaxElementCount") @export;
|
||||
extern fn int getMaxElementCount() @extern("Clay_GetMaxMeasureTextCacheWordCount") @export;
|
||||
extern fn void setMaxMeasureTextCacheWordCount(int maxMeasureTextCacheWordCount) @extern("Clay_SetMaxMeasureTextCacheWordCount") @export;
|
||||
extern fn void resetMeasureTextCache() @extern("Clay_ResetMeasureTextCache") @export;
|
||||
extern fn void beginLayout() @extern("Clay_BeginLayout") @export;
|
||||
extern fn RenderCommandArray endLayout() @extern("Clay_EndLayout") @export;
|
||||
|
||||
// ===== (NEW) Internal Clay API Functions (String replacement) =====
|
||||
extern fn ElementId __getElementIdWithIndex(ClayString idString, uint index) @extern("Clay_GetElementIdWithIndex") @export @private;
|
||||
extern fn ElementId __getElementId(ClayString idString) @extern("Clay_GetElementId") @export @private;
|
||||
|
||||
// ===== Internal Clay API Functions =====
|
||||
extern fn void openElement() @extern ("Clay__OpenElement") @export @private;
|
||||
extern fn void closeElement() @extern("Clay__CloseElement") @export @private;
|
||||
extern fn void openTextElement(ClayString text, TextElementConfig *textConfig) @extern("Clay__OpenTextElement") @export @private;
|
||||
extern fn void elementPostConfiguration() @extern("Clay__ElementPostConfiguration") @export @private;
|
||||
extern fn LayoutConfig * storeLayoutConfig(LayoutConfig config) @extern("Clay__StoreLayoutConfig") @export @private;
|
||||
extern fn void attachId(ElementId id) @extern("Clay__AttachId") @export @private;
|
||||
extern fn void attachLayoutConfig(LayoutConfig *config) @extern("Clay__AttachLayoutConfig") @export @private;
|
||||
extern fn void attachElementConfig(ElementConfigUnion config, ElementConfigType type) @extern("Clay__AttachElementConfig") @export @private;
|
||||
extern fn RectangleElementConfig * storeRectangleElementConfig(RectangleElementConfig config) @extern("Clay__StoreRectangleElementConfig") @export @private;
|
||||
extern fn TextElementConfig * storeTextElementConfig(TextElementConfig config) @extern("Clay__StoreTextElementConfig") @export @private;
|
||||
extern fn ImageElementConfig * storeImageElementConfig(ImageElementConfig config) @extern("Clay__StoreImageElementConfig") @export @private;
|
||||
extern fn FloatingElementConfig * storeFloatingElementConfig(FloatingElementConfig config) @extern("Clay__StoreFloatingElementConfig") @export @private;
|
||||
extern fn CustomElementConfig * storeCustomElementConfig(CustomElementConfig config) @extern("Clay__StoreCustomElementConfig") @export @private;
|
||||
extern fn ScrollElementConfig * storeScrollElementConfig(ScrollElementConfig config) @extern("Clay__StoreScrollElementConfig") @export @private;
|
||||
extern fn BorderElementConfig * storeBorderElementConfig(BorderElementConfig config) @extern("Clay__StoreBorderElementConfig") @export @private;
|
||||
extern fn ElementId hashString(ClayString key, uint offset, uint seed) @extern("Clay__HashString") @export @private;
|
||||
extern fn uint getParentElementId() @extern("Clay__GetParentElementId") @export @private;
|
||||
|
||||
// ==========================================================================
|
||||
// ===== An internal module for wrapping Struct Array's defined in Clay =====
|
||||
// ==========================================================================
|
||||
module clay::carray(<ElementType>);
|
||||
|
||||
struct Array {
|
||||
int capacity;
|
||||
int length;
|
||||
ElementType *data;
|
||||
}
|
Loading…
Reference in New Issue
Block a user