Compare commits

..

21 Commits

Author SHA1 Message Date
Stowy
4d3a13dc37 Added readme and documentation in module.jai 2025-01-03 13:26:43 +01:00
Stowy
b9f4bd3b9c Fixed paths 2025-01-03 12:24:17 +01:00
Stowy
0a3b43027e Updated to latest clay and moved files to be like in the odin bindings 2025-01-03 12:21:43 +01:00
Stowy
e542322cfc Merge branch 'main' into jai-bindings 2025-01-03 12:13:13 +01:00
Stowy
260bb79bab Added missing procedures 2025-01-02 23:36:49 +01:00
Stowy
d1538398dc Finished first version of the bindings with working demo !! 2025-01-02 23:19:31 +01:00
Stowy
c1caf0d3ef Continuing example and still working on adaption the CLAY macro 2025-01-01 19:28:22 +01:00
Stowy
0e5848e6f6 Changed the UI proc to be like the one in the Odin bindings 2025-01-01 16:19:52 +01:00
Stowy
3cab35efc2 Merge branch 'main' into jai-bindings 2024-12-31 14:36:50 +01:00
Stowy
1ec615d5c1 Continued clay bindings 2024-12-31 14:35:03 +01:00
Stowy
129bf62a81 Finished Raylib renderer and continued demo 2024-12-30 20:00:26 +01:00
Stowy
a04bd04e3a Removed private elements from bindings 2024-12-30 18:04:16 +01:00
Stowy
06c5618829 Fixed wrong command when building in debug 2024-12-30 17:49:49 +01:00
Stowy
46ef24ee5a
Merge branch 'nicbarker:main' into main 2024-12-30 17:20:38 +01:00
Stowy
60b4b5c2fc Updated Raylib jai bindings and switch example project to clay video demo 2024-12-29 10:32:49 +01:00
Stowy
b6a6e9ef2d
Merge branch 'nicbarker:main' into main 2024-12-29 10:12:52 +01:00
Stowy
38db2dd27c Replaced raylib bindings with custom ones 2024-12-24 01:30:10 +01:00
Stowy
696e266fc8 Start of clay website example 2024-12-22 18:20:51 +01:00
Stowy
f2101b8f51 Simplified bindings generation 2024-12-22 18:20:31 +01:00
Stowy
e4e118db2a
Merge branch 'nicbarker:main' into main 2024-12-22 16:40:01 +01:00
Stowy
9e5802000a Added first version of Jai bindings 2024-12-22 11:49:53 +01:00
46 changed files with 1006 additions and 9299 deletions

1
.gitignore vendored
View File

@ -2,5 +2,6 @@ cmake-build-debug/
cmake-build-release/
.DS_Store
.idea/
build/
node_modules/
*.dSYM

View File

@ -8,8 +8,7 @@ add_subdirectory("examples/cpp-project-example")
# Don't try to compile C99 projects using MSVC
if(NOT MSVC)
add_subdirectory("examples/raylib-sidebar-scrolling-container")
add_subdirectory("examples/raylib-multi-context")
# add_subdirectory("examples/cairo-pdf-rendering") Some issue with github actions populating cairo, disable for now
add_subdirectory("examples/cairo-pdf-rendering")
add_subdirectory("examples/clay-official-website")
add_subdirectory("examples/introducing-clay-video-demo")
add_subdirectory("examples/SDL2-video-demo")

View File

@ -100,7 +100,7 @@ Clay_RenderCommandArray CreateLayout() {
CLAY_RECTANGLE({ .color = COLOR_LIGHT })
) {
CLAY(CLAY_ID("ProfilePictureOuter"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW() }, .padding = {16, 16}, .childGap = 16, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER }), CLAY_RECTANGLE({ .color = COLOR_RED })) {
CLAY(CLAY_ID("ProfilePicture"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }}), CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {60, 60} })) {}
CLAY(CLAY_ID("ProfilePicture"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_FIXED(60), .height = CLAY_SIZING_FIXED(60) }}), CLAY_IMAGE({ .imageData = &profilePicture, .height = 60, .width = 60 })) {}
CLAY_TEXT(CLAY_STRING("Clay - UI Library"), CLAY_TEXT_CONFIG({ .fontSize = 24, .textColor = {255, 255, 255, 255} }));
}
@ -245,7 +245,7 @@ This ID (or, if not provided, an auto generated ID) will be forwarded to the fin
Clay provides several functions for handling mouse and pointer interactions.
All pointer interactions depend on the function `void Clay_SetPointerState(Clay_Vector2 position, bool isPointerDown)` being called after each mouse position update and before any other clay functions.
All pointer interactions depend on the function `void Clay_SetPointerState(Clay_Vector2 position)` being called after each mouse position update and before any other clay functions.
**During UI declaration**
@ -442,36 +442,6 @@ The debug tooling by default will render as a panel to the right side of the scr
_The official Clay website with debug tooling visible_
### Running more than one Clay instance
Clay allows you to run more than one instance in a program. To do this, [Clay_Initialize](#clay_initialize) returns a [Clay_Context*](#clay_context) reference. You can activate a specific instance using [Clay_SetCurrentContext](#clay_setcurrentcontext). If [Clay_SetCurrentContext](#clay_setcurrentcontext) is not called, then Clay will default to using the context from the most recently called [Clay_Initialize](#clay_initialize).
**⚠ Important: Do not render instances across different threads simultaneously, as Clay does not currently support proper multi-threading.**
```c++
// Define separate arenas for the instances.
Clay_Arena arena1, arena2;
// ... allocate arenas
// Initialize both instances, storing the context for each one.
Clay_Context* instance1 = Clay_Initialize(arena1, layoutDimensions, errorHandler);
Clay_Context* instance2 = Clay_Initialize(arena2, layoutDimensions, errorHandler);
// In the program's render function, activate each instance before executing clay commands and macros.
Clay_SetCurrentContext(instance1);
Clay_BeginLayout();
// ... declare layout for instance1
Clay_RenderCommandArray renderCommands1 = Clay_EndLayout();
render(renderCommands1);
// Switch to the second instance
Clay_SetCurrentContext(instance2);
Clay_BeginLayout();
// ... declare layout for instance2
Clay_RenderCommandArray renderCommands2 = Clay_EndLayout();
render(renderCommands2);
```
# API
### Naming Conventions
@ -516,7 +486,7 @@ Takes a pointer to a function that can be used to measure the `width, height` di
`void Clay_SetMaxElementCount(uint32_t maxElementCount)`
Sets the internal maximum element count that will be used in subsequent [Clay_Initialize()](#clay_initialize) and [Clay_MinMemorySize()](#clay_minmemorysize) calls, allowing clay to allocate larger UI hierarchies.
Updates the internal maximum element count, allowing clay to allocate larger UI hierarchies.
**Note: You will need to reinitialize clay, after calling [Clay_MinMemorySize()](#clay_minmemorysize) to calculate updated memory requirements.**
@ -524,29 +494,17 @@ Sets the internal maximum element count that will be used in subsequent [Clay_In
`void Clay_SetMaxMeasureTextCacheWordCount(uint32_t maxMeasureTextCacheWordCount)`
Sets the internal text measurement cache size that will be used in subsequent [Clay_Initialize()](#clay_initialize) and [Clay_MinMemorySize()](#clay_minmemorysize) calls, allowing clay to allocate more text. The value represents how many separate words can be stored in the text measurement cache.
Updates the internal text measurement cache size, allowing clay to allocate more text. The value represents how many seperate words can be stored in the text measurement cache.
**Note: You will need to reinitialize clay, after calling [Clay_MinMemorySize()](#clay_minmemorysize) to calculate updated memory requirements.**
### Clay_Initialize
`Clay_Context* Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler)`
`void Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler)`
Initializes the internal memory mapping, sets the internal dimensions for layout, and binds an error handler for clay to use when something goes wrong. Returns a [Clay_Context*](#clay_context) that can optionally be given to [Clay_SetCurrentContext](#clay_setcurrentcontext) to allow running multiple instances of clay in the same program, and sets it as the current context. See [Running more than one Clay instance](#running-more-than-one-clay-instance).
Initializes the internal memory mapping, sets the internal dimensions for layout, and binds an error handler for clay to use when something goes wrong.
Reference: [Clay_Arena](#clay_createarenawithcapacityandmemory), [Clay_ErrorHandler](#clay_errorhandler), [Clay_SetCurrentContext](#clay_setcurrentcontext)
### Clay_SetCurrentContext
`void Clay_SetCurrentContext(Clay_Context* context)`
Sets the context that subsequent clay commands will operate on. You can get this reference from [Clay_Initialize](#clay_initialize) or [Clay_GetCurrentContext](#clay_getcurrentcontext). See [Running more than one Clay instance](#running-more-than-one-clay-instance).
### Clay_GetCurrentContext
`Clay_Context* Clay_GetCurrentContext()`
Returns the context that clay commands are currently operating on, or null if no context has been set. See [Running more than one Clay instance](#running-more-than-one-clay-instance).
Reference: [Clay_Arena](#clay_createarenawithcapacityandmemory), [Clay_ErrorHandler](#clay_errorhandler)
### Clay_SetLayoutDimensions
@ -1101,11 +1059,11 @@ CLAY(CLAY_IMAGE({ .image = { .format = IMAGE_FORMAT_RGBA, .internalData = &image
// Load an image somewhere in your code
Image profilePicture = LoadImage("profilePicture.png");
// Declare a reusable image config
Clay_ImageElementConfig imageConfig = (Clay_ImageElementConfig) { .imageData = &profilePicture, .sourceDimensions = {60, 60} };
Clay_ImageElementConfig imageConfig = (Clay_ImageElementConfig) { .imageData = &profilePicture, .height = 60, .width = 60 };
// Declare an image element using a reusable config
CLAY(CLAY_IMAGE(imageConfig)) {}
// Declare an image element using an inline config
CLAY(CLAY_IMAGE({ .imageData = &profilePicture, .sourceDimensions = {60, 60} })) {}
CLAY(CLAY_IMAGE({ .imageData = &profilePicture, .height = 60, .width = 60 })) {}
// Rendering example
Image *imageToRender = renderCommand->elementConfig.imageElementConfig->imageData;
```

View File

@ -2,4 +2,3 @@
main.exe
main.pdb
main.rdi
main

View File

@ -18,14 +18,12 @@ DECLARATIONS_TO_OMIT :: string.[
];
#if AT_COMPILE_TIME {
#if !#exists(JAILS_DIAGNOSTICS_BUILD) {
#run,stallable {
Compiler.set_build_options_dc(.{do_output=false});
options := Compiler.get_build_options();
args := options.compile_time_command_line;
if !generate_bindings(args, options.minimum_os_version) {
Compiler.compiler_set_workspace_status(.FAILED);
}
#run,stallable {
Compiler.set_build_options_dc(.{do_output=false});
options := Compiler.get_build_options();
args := options.compile_time_command_line;
if !generate_bindings(args, options.minimum_os_version) {
Compiler.compiler_set_workspace_status(.FAILED);
}
}
} else {
@ -52,7 +50,6 @@ generate_bindings :: (args: [] string, minimum_os_version: type_of(Compiler.Buil
success := true;
#if OS == .WINDOWS {
// TODO try to use BuildCpp module again
File.make_directory_if_it_does_not_exist("windows", true);
command := ifx compile_debug {
@ -70,15 +67,9 @@ generate_bindings :: (args: [] string, minimum_os_version: type_of(Compiler.Buil
command = Process.break_command_into_strings("llvm-ar -rcs windows/clay.lib clay.o");
result = Process.run_command(..command, capture_and_return_output=true, print_captured_output=true);
if result.exit_code != 0 then return false;
} else #if OS == .LINUX {
File.make_directory_if_it_does_not_exist("linux", true);
could_build := BuildCpp.build_cpp_static_lib("linux/clay", "source/clay.c",
debug = compile_debug,
);
assert(could_build);
} else {
// TODO MacOS
// TODO Linux
assert(false);
}
@ -89,16 +80,11 @@ generate_bindings :: (args: [] string, minimum_os_version: type_of(Compiler.Buil
output_filename: string;
options: Generator.Generate_Bindings_Options;
{
write_string("Generating bindings...\n");
using options;
#if OS == .WINDOWS {
array_add(*libpaths, "windows");
output_filename = "windows.jai";
} else #if OS == .LINUX {
array_add(*libpaths, "linux");
output_filename = "linux.jai";
} else {
assert(false);
}
@ -127,15 +113,7 @@ clay_visitor :: (decl: *Generator.Declaration, parent_decl: *Generator.Declarati
return .STOP;
}
// We don't want the align and wrapper strucs
if String.begins_with(decl.name, "Clay__Align") || String.ends_with(decl.name, "Wrapper") {
decl.decl_flags |= .OMIT_FROM_OUTPUT;
return .STOP;
}
if String.begins_with(decl.name, "Clay__") {
// The way bindings generator strip prefixes mean that something like `Clay__Foo` will be turned to `Foo`
// but what we want is `_Foo`
decl.output_name = String.slice(decl.name, 5, decl.name.count - 5);
}
}
@ -153,10 +131,10 @@ FileUtils :: #import "File_Utilities";
BuildCpp :: #import "BuildCpp";
Process :: #import "Process";
String :: #import "String";
WindowsResources :: #import "Windows_Resources";
#if OS == .WINDOWS {
Windows :: #import "Windows";
WindowsResources :: #import "Windows_Resources";
getenv :: Windows.getenv;
} else {
Posix :: #import "POSIX";

View File

@ -1,711 +0,0 @@
//
// This file was auto-generated using the following command:
//
// jai generate.jai - -compile
//
// Utility Structs -------------------------
// Note: Clay_String is not guaranteed to be null terminated. It may be if created from a literal C string,
// but it is also used to represent slices.
String :: struct {
length: s32;
chars: *u8;
}
_StringArray :: struct {
capacity: s32;
length: s32;
internalArray: *String;
}
Context :: struct {}
Arena :: struct {
nextAllocation: u64;
capacity: u64;
memory: *u8;
}
Dimensions :: struct {
width: float;
height: float;
}
Color :: struct {
r: float;
g: float;
b: float;
a: float;
}
BoundingBox :: struct {
x: float;
y: float;
width: float;
height: float;
}
// baseId + offset = id
ElementId :: struct {
id: u32;
offset: u32;
baseId: u32;
stringId: String;
}
CornerRadius :: struct {
topLeft: float;
topRight: float;
bottomLeft: float;
bottomRight: float;
}
LayoutDirection :: enum u8 {
LEFT_TO_RIGHT :: 0;
TOP_TO_BOTTOM :: 1;
CLAY_LEFT_TO_RIGHT :: LEFT_TO_RIGHT;
CLAY_TOP_TO_BOTTOM :: TOP_TO_BOTTOM;
}
LayoutAlignmentX :: enum u8 {
LEFT :: 0;
RIGHT :: 1;
CENTER :: 2;
CLAY_ALIGN_X_LEFT :: LEFT;
CLAY_ALIGN_X_RIGHT :: RIGHT;
CLAY_ALIGN_X_CENTER :: CENTER;
}
LayoutAlignmentY :: enum u8 {
TOP :: 0;
BOTTOM :: 1;
CENTER :: 2;
CLAY_ALIGN_Y_TOP :: TOP;
CLAY_ALIGN_Y_BOTTOM :: BOTTOM;
CLAY_ALIGN_Y_CENTER :: CENTER;
}
_SizingType :: enum u8 {
FIT :: 0;
GROW :: 1;
PERCENT :: 2;
FIXED :: 3;
CLAY__SIZING_TYPE_FIT :: FIT;
CLAY__SIZING_TYPE_GROW :: GROW;
CLAY__SIZING_TYPE_PERCENT :: PERCENT;
CLAY__SIZING_TYPE_FIXED :: FIXED;
}
ChildAlignment :: struct {
x: LayoutAlignmentX;
y: LayoutAlignmentY;
}
SizingMinMax :: struct {
min: float;
max: float;
}
SizingAxis :: struct {
size: union {
minMax: SizingMinMax;
percent: float;
};
type: _SizingType;
}
Sizing :: struct {
width: SizingAxis;
height: SizingAxis;
}
Padding :: struct {
x: u16;
y: u16;
}
LayoutConfig :: struct {
sizing: Sizing;
padding: Padding;
childGap: u16;
childAlignment: ChildAlignment;
layoutDirection: LayoutDirection;
}
CLAY_LAYOUT_DEFAULT: LayoutConfig #elsewhere clay;
// Rectangle
// NOTE: Not declared in the typedef as an ifdef inside macro arguments is UB
RectangleElementConfig :: struct {
color: Color;
cornerRadius: CornerRadius;
}
// Text
TextElementConfigWrapMode :: enum u32 {
WORDS :: 0;
NEWLINES :: 1;
NONE :: 2;
CLAY_TEXT_WRAP_WORDS :: WORDS;
CLAY_TEXT_WRAP_NEWLINES :: NEWLINES;
CLAY_TEXT_WRAP_NONE :: NONE;
}
TextElementConfig :: struct {
textColor: Color;
fontId: u16;
fontSize: u16;
letterSpacing: u16;
lineHeight: u16;
wrapMode: TextElementConfigWrapMode;
}
// Image
ImageElementConfig :: struct {
imageData: *void;
sourceDimensions: Dimensions;
}
FloatingAttachPointType :: enum u8 {
LEFT_TOP :: 0;
LEFT_CENTER :: 1;
LEFT_BOTTOM :: 2;
CENTER_TOP :: 3;
CENTER_CENTER :: 4;
CENTER_BOTTOM :: 5;
RIGHT_TOP :: 6;
RIGHT_CENTER :: 7;
RIGHT_BOTTOM :: 8;
CLAY_ATTACH_POINT_LEFT_TOP :: LEFT_TOP;
CLAY_ATTACH_POINT_LEFT_CENTER :: LEFT_CENTER;
CLAY_ATTACH_POINT_LEFT_BOTTOM :: LEFT_BOTTOM;
CLAY_ATTACH_POINT_CENTER_TOP :: CENTER_TOP;
CLAY_ATTACH_POINT_CENTER_CENTER :: CENTER_CENTER;
CLAY_ATTACH_POINT_CENTER_BOTTOM :: CENTER_BOTTOM;
CLAY_ATTACH_POINT_RIGHT_TOP :: RIGHT_TOP;
CLAY_ATTACH_POINT_RIGHT_CENTER :: RIGHT_CENTER;
CLAY_ATTACH_POINT_RIGHT_BOTTOM :: RIGHT_BOTTOM;
}
FloatingAttachPoints :: struct {
element: FloatingAttachPointType;
parent: FloatingAttachPointType;
}
PointerCaptureMode :: enum u32 {
CAPTURE :: 0;
PASSTHROUGH :: 1;
CLAY_POINTER_CAPTURE_MODE_CAPTURE :: CAPTURE;
CLAY_POINTER_CAPTURE_MODE_PASSTHROUGH :: PASSTHROUGH;
}
FloatingElementConfig :: struct {
offset: Vector2;
expand: Dimensions;
zIndex: u16;
parentId: u32;
attachment: FloatingAttachPoints;
pointerCaptureMode: PointerCaptureMode;
}
// Custom
CustomElementConfig :: struct {
customData: *void;
}
// Scroll
ScrollElementConfig :: struct {
horizontal: bool;
vertical: bool;
}
ElementConfigUnion :: union {
rectangleElementConfig: *RectangleElementConfig;
textElementConfig: *TextElementConfig;
imageElementConfig: *ImageElementConfig;
floatingElementConfig: *FloatingElementConfig;
customElementConfig: *CustomElementConfig;
scrollElementConfig: *ScrollElementConfig;
borderElementConfig: *BorderElementConfig;
}
ElementConfig :: struct {
type: ElementConfigType;
config: ElementConfigUnion;
}
// Miscellaneous Structs & Enums ---------------------------------
ScrollContainerData :: struct {
// 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.
scrollPosition: *Vector2;
scrollContainerDimensions: Dimensions;
contentDimensions: Dimensions;
config: ScrollElementConfig;
found: bool;
}
RenderCommandType :: enum u8 {
NONE :: 0;
RECTANGLE :: 1;
BORDER :: 2;
TEXT :: 3;
IMAGE :: 4;
SCISSOR_START :: 5;
SCISSOR_END :: 6;
CUSTOM :: 7;
CLAY_RENDER_COMMAND_TYPE_NONE :: NONE;
CLAY_RENDER_COMMAND_TYPE_RECTANGLE :: RECTANGLE;
CLAY_RENDER_COMMAND_TYPE_BORDER :: BORDER;
CLAY_RENDER_COMMAND_TYPE_TEXT :: TEXT;
CLAY_RENDER_COMMAND_TYPE_IMAGE :: IMAGE;
CLAY_RENDER_COMMAND_TYPE_SCISSOR_START :: SCISSOR_START;
CLAY_RENDER_COMMAND_TYPE_SCISSOR_END :: SCISSOR_END;
CLAY_RENDER_COMMAND_TYPE_CUSTOM :: CUSTOM;
}
RenderCommand :: struct {
boundingBox: BoundingBox;
config: ElementConfigUnion;
text: String; // TODO I wish there was a way to avoid having to have this on every render command
id: u32;
commandType: RenderCommandType;
}
RenderCommandArray :: struct {
capacity: s32;
length: s32;
internalArray: *RenderCommand;
}
PointerDataInteractionState :: enum u32 {
PRESSED_THIS_FRAME :: 0;
PRESSED :: 1;
RELEASED_THIS_FRAME :: 2;
RELEASED :: 3;
CLAY_POINTER_DATA_PRESSED_THIS_FRAME :: PRESSED_THIS_FRAME;
CLAY_POINTER_DATA_PRESSED :: PRESSED;
CLAY_POINTER_DATA_RELEASED_THIS_FRAME :: RELEASED_THIS_FRAME;
CLAY_POINTER_DATA_RELEASED :: RELEASED;
}
PointerData :: struct {
position: Vector2;
state: PointerDataInteractionState;
}
ErrorType :: enum u32 {
TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED :: 0;
ARENA_CAPACITY_EXCEEDED :: 1;
ELEMENTS_CAPACITY_EXCEEDED :: 2;
TEXT_MEASUREMENT_CAPACITY_EXCEEDED :: 3;
DUPLICATE_ID :: 4;
FLOATING_CONTAINER_PARENT_NOT_FOUND :: 5;
INTERNAL_ERROR :: 6;
CLAY_ERROR_TYPE_TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED :: TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED;
CLAY_ERROR_TYPE_ARENA_CAPACITY_EXCEEDED :: ARENA_CAPACITY_EXCEEDED;
CLAY_ERROR_TYPE_ELEMENTS_CAPACITY_EXCEEDED :: ELEMENTS_CAPACITY_EXCEEDED;
CLAY_ERROR_TYPE_TEXT_MEASUREMENT_CAPACITY_EXCEEDED :: TEXT_MEASUREMENT_CAPACITY_EXCEEDED;
CLAY_ERROR_TYPE_DUPLICATE_ID :: DUPLICATE_ID;
CLAY_ERROR_TYPE_FLOATING_CONTAINER_PARENT_NOT_FOUND :: FLOATING_CONTAINER_PARENT_NOT_FOUND;
CLAY_ERROR_TYPE_INTERNAL_ERROR :: INTERNAL_ERROR;
}
ErrorData :: struct {
errorType: ErrorType;
errorText: String;
userData: u64;
}
ErrorHandler :: struct {
errorHandlerFunction: #type (errorText: ErrorData) -> void #c_call;
userData: u64;
}
// Function Forward Declarations ---------------------------------
// Public API functions ---
MinMemorySize :: () -> u32 #foreign clay "Clay_MinMemorySize";
CreateArenaWithCapacityAndMemory :: (capacity: u32, offset: *void) -> Arena #foreign clay "Clay_CreateArenaWithCapacityAndMemory";
SetPointerState :: (position: Vector2, pointerDown: bool) -> void #foreign clay "Clay_SetPointerState";
Initialize :: (arena: Arena, layoutDimensions: Dimensions, errorHandler: ErrorHandler) -> *Context #foreign clay "Clay_Initialize";
GetCurrentContext :: () -> *Context #foreign clay "Clay_GetCurrentContext";
SetCurrentContext :: (_context: *Context) -> void #foreign clay "Clay_SetCurrentContext";
UpdateScrollContainers :: (enableDragScrolling: bool, scrollDelta: Vector2, deltaTime: float) -> void #foreign clay "Clay_UpdateScrollContainers";
SetLayoutDimensions :: (dimensions: Dimensions) -> void #foreign clay "Clay_SetLayoutDimensions";
BeginLayout :: () -> void #foreign clay "Clay_BeginLayout";
EndLayout :: () -> RenderCommandArray #foreign clay "Clay_EndLayout";
GetElementId :: (idString: String) -> ElementId #foreign clay "Clay_GetElementId";
GetElementIdWithIndex :: (idString: String, index: u32) -> ElementId #foreign clay "Clay_GetElementIdWithIndex";
PointerOver :: (elementId: ElementId) -> bool #foreign clay "Clay_PointerOver";
GetScrollContainerData :: (id: ElementId) -> ScrollContainerData #foreign clay "Clay_GetScrollContainerData";
SetMeasureTextFunction :: (measureTextFunction: #type (text: *String, config: *TextElementConfig) -> Dimensions #c_call) -> void #foreign clay "Clay_SetMeasureTextFunction";
SetQueryScrollOffsetFunction :: (queryScrollOffsetFunction: #type (elementId: u32) -> Vector2 #c_call) -> void #foreign clay "Clay_SetQueryScrollOffsetFunction";
RenderCommandArray_Get :: (array: *RenderCommandArray, index: s32) -> *RenderCommand #foreign clay "Clay_RenderCommandArray_Get";
SetDebugModeEnabled :: (enabled: bool) -> void #foreign clay "Clay_SetDebugModeEnabled";
IsDebugModeEnabled :: () -> bool #foreign clay "Clay_IsDebugModeEnabled";
SetCullingEnabled :: (enabled: bool) -> void #foreign clay "Clay_SetCullingEnabled";
GetMaxElementCount :: () -> s32 #foreign clay "Clay_GetMaxElementCount";
SetMaxElementCount :: (maxElementCount: s32) -> void #foreign clay "Clay_SetMaxElementCount";
GetMaxMeasureTextCacheWordCount :: () -> s32 #foreign clay "Clay_GetMaxMeasureTextCacheWordCount";
SetMaxMeasureTextCacheWordCount :: (maxMeasureTextCacheWordCount: s32) -> void #foreign clay "Clay_SetMaxMeasureTextCacheWordCount";
// Internal API functions required by macros
_OpenElement :: () -> void #foreign clay "Clay__OpenElement";
_CloseElement :: () -> void #foreign clay "Clay__CloseElement";
_StoreLayoutConfig :: (config: LayoutConfig) -> *LayoutConfig #foreign clay "Clay__StoreLayoutConfig";
_ElementPostConfiguration :: () -> void #foreign clay "Clay__ElementPostConfiguration";
_AttachId :: (id: ElementId) -> void #foreign clay "Clay__AttachId";
_AttachLayoutConfig :: (config: *LayoutConfig) -> void #foreign clay "Clay__AttachLayoutConfig";
_AttachElementConfig :: (config: ElementConfigUnion, type: ElementConfigType) -> void #foreign clay "Clay__AttachElementConfig";
_StoreRectangleElementConfig :: (config: RectangleElementConfig) -> *RectangleElementConfig #foreign clay "Clay__StoreRectangleElementConfig";
_StoreTextElementConfig :: (config: TextElementConfig) -> *TextElementConfig #foreign clay "Clay__StoreTextElementConfig";
_StoreImageElementConfig :: (config: ImageElementConfig) -> *ImageElementConfig #foreign clay "Clay__StoreImageElementConfig";
_StoreFloatingElementConfig :: (config: FloatingElementConfig) -> *FloatingElementConfig #foreign clay "Clay__StoreFloatingElementConfig";
_StoreCustomElementConfig :: (config: CustomElementConfig) -> *CustomElementConfig #foreign clay "Clay__StoreCustomElementConfig";
_StoreScrollElementConfig :: (config: ScrollElementConfig) -> *ScrollElementConfig #foreign clay "Clay__StoreScrollElementConfig";
_StoreBorderElementConfig :: (config: BorderElementConfig) -> *BorderElementConfig #foreign clay "Clay__StoreBorderElementConfig";
_HashString :: (key: String, offset: u32, seed: u32) -> ElementId #foreign clay "Clay__HashString";
_OpenTextElement :: (text: String, textConfig: *TextElementConfig) -> void #foreign clay "Clay__OpenTextElement";
_GetParentElementId :: () -> u32 #foreign clay "Clay__GetParentElementId";
_debugViewHighlightColor: Color #elsewhere clay "Clay__debugViewHighlightColor";
_debugViewWidth: u32 #elsewhere clay "Clay__debugViewWidth";
#scope_file
#import "Basic"; // For assert
clay :: #library,no_dll "linux/clay";
#run {
{
instance: String;
assert(((cast(*void)(*instance.length)) - cast(*void)(*instance)) == 0, "String.length has unexpected offset % instead of 0", ((cast(*void)(*instance.length)) - cast(*void)(*instance)));
assert(size_of(type_of(String.length)) == 4, "String.length has unexpected size % instead of 4", size_of(type_of(String.length)));
assert(((cast(*void)(*instance.chars)) - cast(*void)(*instance)) == 8, "String.chars has unexpected offset % instead of 8", ((cast(*void)(*instance.chars)) - cast(*void)(*instance)));
assert(size_of(type_of(String.chars)) == 8, "String.chars has unexpected size % instead of 8", size_of(type_of(String.chars)));
assert(size_of(String) == 16, "String has size % instead of 16", size_of(String));
}
{
instance: _StringArray;
assert(((cast(*void)(*instance.capacity)) - cast(*void)(*instance)) == 0, "_StringArray.capacity has unexpected offset % instead of 0", ((cast(*void)(*instance.capacity)) - cast(*void)(*instance)));
assert(size_of(type_of(_StringArray.capacity)) == 4, "_StringArray.capacity has unexpected size % instead of 4", size_of(type_of(_StringArray.capacity)));
assert(((cast(*void)(*instance.length)) - cast(*void)(*instance)) == 4, "_StringArray.length has unexpected offset % instead of 4", ((cast(*void)(*instance.length)) - cast(*void)(*instance)));
assert(size_of(type_of(_StringArray.length)) == 4, "_StringArray.length has unexpected size % instead of 4", size_of(type_of(_StringArray.length)));
assert(((cast(*void)(*instance.internalArray)) - cast(*void)(*instance)) == 8, "_StringArray.internalArray has unexpected offset % instead of 8", ((cast(*void)(*instance.internalArray)) - cast(*void)(*instance)));
assert(size_of(type_of(_StringArray.internalArray)) == 8, "_StringArray.internalArray has unexpected size % instead of 8", size_of(type_of(_StringArray.internalArray)));
assert(size_of(_StringArray) == 16, "_StringArray has size % instead of 16", size_of(_StringArray));
}
{
instance: Arena;
assert(((cast(*void)(*instance.nextAllocation)) - cast(*void)(*instance)) == 0, "Arena.nextAllocation has unexpected offset % instead of 0", ((cast(*void)(*instance.nextAllocation)) - cast(*void)(*instance)));
assert(size_of(type_of(Arena.nextAllocation)) == 8, "Arena.nextAllocation has unexpected size % instead of 8", size_of(type_of(Arena.nextAllocation)));
assert(((cast(*void)(*instance.capacity)) - cast(*void)(*instance)) == 8, "Arena.capacity has unexpected offset % instead of 8", ((cast(*void)(*instance.capacity)) - cast(*void)(*instance)));
assert(size_of(type_of(Arena.capacity)) == 8, "Arena.capacity has unexpected size % instead of 8", size_of(type_of(Arena.capacity)));
assert(((cast(*void)(*instance.memory)) - cast(*void)(*instance)) == 16, "Arena.memory has unexpected offset % instead of 16", ((cast(*void)(*instance.memory)) - cast(*void)(*instance)));
assert(size_of(type_of(Arena.memory)) == 8, "Arena.memory has unexpected size % instead of 8", size_of(type_of(Arena.memory)));
assert(size_of(Arena) == 24, "Arena has size % instead of 24", size_of(Arena));
}
{
instance: Dimensions;
assert(((cast(*void)(*instance.width)) - cast(*void)(*instance)) == 0, "Dimensions.width has unexpected offset % instead of 0", ((cast(*void)(*instance.width)) - cast(*void)(*instance)));
assert(size_of(type_of(Dimensions.width)) == 4, "Dimensions.width has unexpected size % instead of 4", size_of(type_of(Dimensions.width)));
assert(((cast(*void)(*instance.height)) - cast(*void)(*instance)) == 4, "Dimensions.height has unexpected offset % instead of 4", ((cast(*void)(*instance.height)) - cast(*void)(*instance)));
assert(size_of(type_of(Dimensions.height)) == 4, "Dimensions.height has unexpected size % instead of 4", size_of(type_of(Dimensions.height)));
assert(size_of(Dimensions) == 8, "Dimensions has size % instead of 8", size_of(Dimensions));
}
{
instance: Color;
assert(((cast(*void)(*instance.r)) - cast(*void)(*instance)) == 0, "Color.r has unexpected offset % instead of 0", ((cast(*void)(*instance.r)) - cast(*void)(*instance)));
assert(size_of(type_of(Color.r)) == 4, "Color.r has unexpected size % instead of 4", size_of(type_of(Color.r)));
assert(((cast(*void)(*instance.g)) - cast(*void)(*instance)) == 4, "Color.g has unexpected offset % instead of 4", ((cast(*void)(*instance.g)) - cast(*void)(*instance)));
assert(size_of(type_of(Color.g)) == 4, "Color.g has unexpected size % instead of 4", size_of(type_of(Color.g)));
assert(((cast(*void)(*instance.b)) - cast(*void)(*instance)) == 8, "Color.b has unexpected offset % instead of 8", ((cast(*void)(*instance.b)) - cast(*void)(*instance)));
assert(size_of(type_of(Color.b)) == 4, "Color.b has unexpected size % instead of 4", size_of(type_of(Color.b)));
assert(((cast(*void)(*instance.a)) - cast(*void)(*instance)) == 12, "Color.a has unexpected offset % instead of 12", ((cast(*void)(*instance.a)) - cast(*void)(*instance)));
assert(size_of(type_of(Color.a)) == 4, "Color.a has unexpected size % instead of 4", size_of(type_of(Color.a)));
assert(size_of(Color) == 16, "Color has size % instead of 16", size_of(Color));
}
{
instance: BoundingBox;
assert(((cast(*void)(*instance.x)) - cast(*void)(*instance)) == 0, "BoundingBox.x has unexpected offset % instead of 0", ((cast(*void)(*instance.x)) - cast(*void)(*instance)));
assert(size_of(type_of(BoundingBox.x)) == 4, "BoundingBox.x has unexpected size % instead of 4", size_of(type_of(BoundingBox.x)));
assert(((cast(*void)(*instance.y)) - cast(*void)(*instance)) == 4, "BoundingBox.y has unexpected offset % instead of 4", ((cast(*void)(*instance.y)) - cast(*void)(*instance)));
assert(size_of(type_of(BoundingBox.y)) == 4, "BoundingBox.y has unexpected size % instead of 4", size_of(type_of(BoundingBox.y)));
assert(((cast(*void)(*instance.width)) - cast(*void)(*instance)) == 8, "BoundingBox.width has unexpected offset % instead of 8", ((cast(*void)(*instance.width)) - cast(*void)(*instance)));
assert(size_of(type_of(BoundingBox.width)) == 4, "BoundingBox.width has unexpected size % instead of 4", size_of(type_of(BoundingBox.width)));
assert(((cast(*void)(*instance.height)) - cast(*void)(*instance)) == 12, "BoundingBox.height has unexpected offset % instead of 12", ((cast(*void)(*instance.height)) - cast(*void)(*instance)));
assert(size_of(type_of(BoundingBox.height)) == 4, "BoundingBox.height has unexpected size % instead of 4", size_of(type_of(BoundingBox.height)));
assert(size_of(BoundingBox) == 16, "BoundingBox has size % instead of 16", size_of(BoundingBox));
}
{
instance: ElementId;
assert(((cast(*void)(*instance.id)) - cast(*void)(*instance)) == 0, "ElementId.id has unexpected offset % instead of 0", ((cast(*void)(*instance.id)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementId.id)) == 4, "ElementId.id has unexpected size % instead of 4", size_of(type_of(ElementId.id)));
assert(((cast(*void)(*instance.offset)) - cast(*void)(*instance)) == 4, "ElementId.offset has unexpected offset % instead of 4", ((cast(*void)(*instance.offset)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementId.offset)) == 4, "ElementId.offset has unexpected size % instead of 4", size_of(type_of(ElementId.offset)));
assert(((cast(*void)(*instance.baseId)) - cast(*void)(*instance)) == 8, "ElementId.baseId has unexpected offset % instead of 8", ((cast(*void)(*instance.baseId)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementId.baseId)) == 4, "ElementId.baseId has unexpected size % instead of 4", size_of(type_of(ElementId.baseId)));
assert(((cast(*void)(*instance.stringId)) - cast(*void)(*instance)) == 16, "ElementId.stringId has unexpected offset % instead of 16", ((cast(*void)(*instance.stringId)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementId.stringId)) == 16, "ElementId.stringId has unexpected size % instead of 16", size_of(type_of(ElementId.stringId)));
assert(size_of(ElementId) == 32, "ElementId has size % instead of 32", size_of(ElementId));
}
{
instance: CornerRadius;
assert(((cast(*void)(*instance.topLeft)) - cast(*void)(*instance)) == 0, "CornerRadius.topLeft has unexpected offset % instead of 0", ((cast(*void)(*instance.topLeft)) - cast(*void)(*instance)));
assert(size_of(type_of(CornerRadius.topLeft)) == 4, "CornerRadius.topLeft has unexpected size % instead of 4", size_of(type_of(CornerRadius.topLeft)));
assert(((cast(*void)(*instance.topRight)) - cast(*void)(*instance)) == 4, "CornerRadius.topRight has unexpected offset % instead of 4", ((cast(*void)(*instance.topRight)) - cast(*void)(*instance)));
assert(size_of(type_of(CornerRadius.topRight)) == 4, "CornerRadius.topRight has unexpected size % instead of 4", size_of(type_of(CornerRadius.topRight)));
assert(((cast(*void)(*instance.bottomLeft)) - cast(*void)(*instance)) == 8, "CornerRadius.bottomLeft has unexpected offset % instead of 8", ((cast(*void)(*instance.bottomLeft)) - cast(*void)(*instance)));
assert(size_of(type_of(CornerRadius.bottomLeft)) == 4, "CornerRadius.bottomLeft has unexpected size % instead of 4", size_of(type_of(CornerRadius.bottomLeft)));
assert(((cast(*void)(*instance.bottomRight)) - cast(*void)(*instance)) == 12, "CornerRadius.bottomRight has unexpected offset % instead of 12", ((cast(*void)(*instance.bottomRight)) - cast(*void)(*instance)));
assert(size_of(type_of(CornerRadius.bottomRight)) == 4, "CornerRadius.bottomRight has unexpected size % instead of 4", size_of(type_of(CornerRadius.bottomRight)));
assert(size_of(CornerRadius) == 16, "CornerRadius has size % instead of 16", size_of(CornerRadius));
}
{
instance: ChildAlignment;
assert(((cast(*void)(*instance.x)) - cast(*void)(*instance)) == 0, "ChildAlignment.x has unexpected offset % instead of 0", ((cast(*void)(*instance.x)) - cast(*void)(*instance)));
assert(size_of(type_of(ChildAlignment.x)) == 1, "ChildAlignment.x has unexpected size % instead of 1", size_of(type_of(ChildAlignment.x)));
assert(((cast(*void)(*instance.y)) - cast(*void)(*instance)) == 1, "ChildAlignment.y has unexpected offset % instead of 1", ((cast(*void)(*instance.y)) - cast(*void)(*instance)));
assert(size_of(type_of(ChildAlignment.y)) == 1, "ChildAlignment.y has unexpected size % instead of 1", size_of(type_of(ChildAlignment.y)));
assert(size_of(ChildAlignment) == 2, "ChildAlignment has size % instead of 2", size_of(ChildAlignment));
}
{
instance: SizingMinMax;
assert(((cast(*void)(*instance.min)) - cast(*void)(*instance)) == 0, "SizingMinMax.min has unexpected offset % instead of 0", ((cast(*void)(*instance.min)) - cast(*void)(*instance)));
assert(size_of(type_of(SizingMinMax.min)) == 4, "SizingMinMax.min has unexpected size % instead of 4", size_of(type_of(SizingMinMax.min)));
assert(((cast(*void)(*instance.max)) - cast(*void)(*instance)) == 4, "SizingMinMax.max has unexpected offset % instead of 4", ((cast(*void)(*instance.max)) - cast(*void)(*instance)));
assert(size_of(type_of(SizingMinMax.max)) == 4, "SizingMinMax.max has unexpected size % instead of 4", size_of(type_of(SizingMinMax.max)));
assert(size_of(SizingMinMax) == 8, "SizingMinMax has size % instead of 8", size_of(SizingMinMax));
}
{
instance: SizingAxis;
assert(((cast(*void)(*instance.size)) - cast(*void)(*instance)) == 0, "SizingAxis.size has unexpected offset % instead of 0", ((cast(*void)(*instance.size)) - cast(*void)(*instance)));
assert(size_of(type_of(SizingAxis.size)) == 8, "SizingAxis.size has unexpected size % instead of 8", size_of(type_of(SizingAxis.size)));
assert(((cast(*void)(*instance.type)) - cast(*void)(*instance)) == 8, "SizingAxis.type has unexpected offset % instead of 8", ((cast(*void)(*instance.type)) - cast(*void)(*instance)));
assert(size_of(type_of(SizingAxis.type)) == 1, "SizingAxis.type has unexpected size % instead of 1", size_of(type_of(SizingAxis.type)));
assert(size_of(SizingAxis) == 12, "SizingAxis has size % instead of 12", size_of(SizingAxis));
}
{
instance: Sizing;
assert(((cast(*void)(*instance.width)) - cast(*void)(*instance)) == 0, "Sizing.width has unexpected offset % instead of 0", ((cast(*void)(*instance.width)) - cast(*void)(*instance)));
assert(size_of(type_of(Sizing.width)) == 12, "Sizing.width has unexpected size % instead of 12", size_of(type_of(Sizing.width)));
assert(((cast(*void)(*instance.height)) - cast(*void)(*instance)) == 12, "Sizing.height has unexpected offset % instead of 12", ((cast(*void)(*instance.height)) - cast(*void)(*instance)));
assert(size_of(type_of(Sizing.height)) == 12, "Sizing.height has unexpected size % instead of 12", size_of(type_of(Sizing.height)));
assert(size_of(Sizing) == 24, "Sizing has size % instead of 24", size_of(Sizing));
}
{
instance: Padding;
assert(((cast(*void)(*instance.x)) - cast(*void)(*instance)) == 0, "Padding.x has unexpected offset % instead of 0", ((cast(*void)(*instance.x)) - cast(*void)(*instance)));
assert(size_of(type_of(Padding.x)) == 2, "Padding.x has unexpected size % instead of 2", size_of(type_of(Padding.x)));
assert(((cast(*void)(*instance.y)) - cast(*void)(*instance)) == 2, "Padding.y has unexpected offset % instead of 2", ((cast(*void)(*instance.y)) - cast(*void)(*instance)));
assert(size_of(type_of(Padding.y)) == 2, "Padding.y has unexpected size % instead of 2", size_of(type_of(Padding.y)));
assert(size_of(Padding) == 4, "Padding has size % instead of 4", size_of(Padding));
}
{
instance: LayoutConfig;
assert(((cast(*void)(*instance.sizing)) - cast(*void)(*instance)) == 0, "LayoutConfig.sizing has unexpected offset % instead of 0", ((cast(*void)(*instance.sizing)) - cast(*void)(*instance)));
assert(size_of(type_of(LayoutConfig.sizing)) == 24, "LayoutConfig.sizing has unexpected size % instead of 24", size_of(type_of(LayoutConfig.sizing)));
assert(((cast(*void)(*instance.padding)) - cast(*void)(*instance)) == 24, "LayoutConfig.padding has unexpected offset % instead of 24", ((cast(*void)(*instance.padding)) - cast(*void)(*instance)));
assert(size_of(type_of(LayoutConfig.padding)) == 4, "LayoutConfig.padding has unexpected size % instead of 4", size_of(type_of(LayoutConfig.padding)));
assert(((cast(*void)(*instance.childGap)) - cast(*void)(*instance)) == 28, "LayoutConfig.childGap has unexpected offset % instead of 28", ((cast(*void)(*instance.childGap)) - cast(*void)(*instance)));
assert(size_of(type_of(LayoutConfig.childGap)) == 2, "LayoutConfig.childGap has unexpected size % instead of 2", size_of(type_of(LayoutConfig.childGap)));
assert(((cast(*void)(*instance.childAlignment)) - cast(*void)(*instance)) == 30, "LayoutConfig.childAlignment has unexpected offset % instead of 30", ((cast(*void)(*instance.childAlignment)) - cast(*void)(*instance)));
assert(size_of(type_of(LayoutConfig.childAlignment)) == 2, "LayoutConfig.childAlignment has unexpected size % instead of 2", size_of(type_of(LayoutConfig.childAlignment)));
assert(((cast(*void)(*instance.layoutDirection)) - cast(*void)(*instance)) == 32, "LayoutConfig.layoutDirection has unexpected offset % instead of 32", ((cast(*void)(*instance.layoutDirection)) - cast(*void)(*instance)));
assert(size_of(type_of(LayoutConfig.layoutDirection)) == 1, "LayoutConfig.layoutDirection has unexpected size % instead of 1", size_of(type_of(LayoutConfig.layoutDirection)));
assert(size_of(LayoutConfig) == 36, "LayoutConfig has size % instead of 36", size_of(LayoutConfig));
}
{
instance: RectangleElementConfig;
assert(((cast(*void)(*instance.color)) - cast(*void)(*instance)) == 0, "RectangleElementConfig.color has unexpected offset % instead of 0", ((cast(*void)(*instance.color)) - cast(*void)(*instance)));
assert(size_of(type_of(RectangleElementConfig.color)) == 16, "RectangleElementConfig.color has unexpected size % instead of 16", size_of(type_of(RectangleElementConfig.color)));
assert(((cast(*void)(*instance.cornerRadius)) - cast(*void)(*instance)) == 16, "RectangleElementConfig.cornerRadius has unexpected offset % instead of 16", ((cast(*void)(*instance.cornerRadius)) - cast(*void)(*instance)));
assert(size_of(type_of(RectangleElementConfig.cornerRadius)) == 16, "RectangleElementConfig.cornerRadius has unexpected size % instead of 16", size_of(type_of(RectangleElementConfig.cornerRadius)));
assert(size_of(RectangleElementConfig) == 32, "RectangleElementConfig has size % instead of 32", size_of(RectangleElementConfig));
}
{
instance: TextElementConfig;
assert(((cast(*void)(*instance.textColor)) - cast(*void)(*instance)) == 0, "TextElementConfig.textColor has unexpected offset % instead of 0", ((cast(*void)(*instance.textColor)) - cast(*void)(*instance)));
assert(size_of(type_of(TextElementConfig.textColor)) == 16, "TextElementConfig.textColor has unexpected size % instead of 16", size_of(type_of(TextElementConfig.textColor)));
assert(((cast(*void)(*instance.fontId)) - cast(*void)(*instance)) == 16, "TextElementConfig.fontId has unexpected offset % instead of 16", ((cast(*void)(*instance.fontId)) - cast(*void)(*instance)));
assert(size_of(type_of(TextElementConfig.fontId)) == 2, "TextElementConfig.fontId has unexpected size % instead of 2", size_of(type_of(TextElementConfig.fontId)));
assert(((cast(*void)(*instance.fontSize)) - cast(*void)(*instance)) == 18, "TextElementConfig.fontSize has unexpected offset % instead of 18", ((cast(*void)(*instance.fontSize)) - cast(*void)(*instance)));
assert(size_of(type_of(TextElementConfig.fontSize)) == 2, "TextElementConfig.fontSize has unexpected size % instead of 2", size_of(type_of(TextElementConfig.fontSize)));
assert(((cast(*void)(*instance.letterSpacing)) - cast(*void)(*instance)) == 20, "TextElementConfig.letterSpacing has unexpected offset % instead of 20", ((cast(*void)(*instance.letterSpacing)) - cast(*void)(*instance)));
assert(size_of(type_of(TextElementConfig.letterSpacing)) == 2, "TextElementConfig.letterSpacing has unexpected size % instead of 2", size_of(type_of(TextElementConfig.letterSpacing)));
assert(((cast(*void)(*instance.lineHeight)) - cast(*void)(*instance)) == 22, "TextElementConfig.lineHeight has unexpected offset % instead of 22", ((cast(*void)(*instance.lineHeight)) - cast(*void)(*instance)));
assert(size_of(type_of(TextElementConfig.lineHeight)) == 2, "TextElementConfig.lineHeight has unexpected size % instead of 2", size_of(type_of(TextElementConfig.lineHeight)));
assert(((cast(*void)(*instance.wrapMode)) - cast(*void)(*instance)) == 24, "TextElementConfig.wrapMode has unexpected offset % instead of 24", ((cast(*void)(*instance.wrapMode)) - cast(*void)(*instance)));
assert(size_of(type_of(TextElementConfig.wrapMode)) == 4, "TextElementConfig.wrapMode has unexpected size % instead of 4", size_of(type_of(TextElementConfig.wrapMode)));
assert(size_of(TextElementConfig) == 28, "TextElementConfig has size % instead of 28", size_of(TextElementConfig));
}
{
instance: ImageElementConfig;
assert(((cast(*void)(*instance.imageData)) - cast(*void)(*instance)) == 0, "ImageElementConfig.imageData has unexpected offset % instead of 0", ((cast(*void)(*instance.imageData)) - cast(*void)(*instance)));
assert(size_of(type_of(ImageElementConfig.imageData)) == 8, "ImageElementConfig.imageData has unexpected size % instead of 8", size_of(type_of(ImageElementConfig.imageData)));
assert(((cast(*void)(*instance.sourceDimensions)) - cast(*void)(*instance)) == 8, "ImageElementConfig.sourceDimensions has unexpected offset % instead of 8", ((cast(*void)(*instance.sourceDimensions)) - cast(*void)(*instance)));
assert(size_of(type_of(ImageElementConfig.sourceDimensions)) == 8, "ImageElementConfig.sourceDimensions has unexpected size % instead of 8", size_of(type_of(ImageElementConfig.sourceDimensions)));
assert(size_of(ImageElementConfig) == 16, "ImageElementConfig has size % instead of 16", size_of(ImageElementConfig));
}
{
instance: FloatingAttachPoints;
assert(((cast(*void)(*instance.element)) - cast(*void)(*instance)) == 0, "FloatingAttachPoints.element has unexpected offset % instead of 0", ((cast(*void)(*instance.element)) - cast(*void)(*instance)));
assert(size_of(type_of(FloatingAttachPoints.element)) == 1, "FloatingAttachPoints.element has unexpected size % instead of 1", size_of(type_of(FloatingAttachPoints.element)));
assert(((cast(*void)(*instance.parent)) - cast(*void)(*instance)) == 1, "FloatingAttachPoints.parent has unexpected offset % instead of 1", ((cast(*void)(*instance.parent)) - cast(*void)(*instance)));
assert(size_of(type_of(FloatingAttachPoints.parent)) == 1, "FloatingAttachPoints.parent has unexpected size % instead of 1", size_of(type_of(FloatingAttachPoints.parent)));
assert(size_of(FloatingAttachPoints) == 2, "FloatingAttachPoints has size % instead of 2", size_of(FloatingAttachPoints));
}
{
instance: FloatingElementConfig;
assert(((cast(*void)(*instance.offset)) - cast(*void)(*instance)) == 0, "FloatingElementConfig.offset has unexpected offset % instead of 0", ((cast(*void)(*instance.offset)) - cast(*void)(*instance)));
assert(size_of(type_of(FloatingElementConfig.offset)) == 8, "FloatingElementConfig.offset has unexpected size % instead of 8", size_of(type_of(FloatingElementConfig.offset)));
assert(((cast(*void)(*instance.expand)) - cast(*void)(*instance)) == 8, "FloatingElementConfig.expand has unexpected offset % instead of 8", ((cast(*void)(*instance.expand)) - cast(*void)(*instance)));
assert(size_of(type_of(FloatingElementConfig.expand)) == 8, "FloatingElementConfig.expand has unexpected size % instead of 8", size_of(type_of(FloatingElementConfig.expand)));
assert(((cast(*void)(*instance.zIndex)) - cast(*void)(*instance)) == 16, "FloatingElementConfig.zIndex has unexpected offset % instead of 16", ((cast(*void)(*instance.zIndex)) - cast(*void)(*instance)));
assert(size_of(type_of(FloatingElementConfig.zIndex)) == 2, "FloatingElementConfig.zIndex has unexpected size % instead of 2", size_of(type_of(FloatingElementConfig.zIndex)));
assert(((cast(*void)(*instance.parentId)) - cast(*void)(*instance)) == 20, "FloatingElementConfig.parentId has unexpected offset % instead of 20", ((cast(*void)(*instance.parentId)) - cast(*void)(*instance)));
assert(size_of(type_of(FloatingElementConfig.parentId)) == 4, "FloatingElementConfig.parentId has unexpected size % instead of 4", size_of(type_of(FloatingElementConfig.parentId)));
assert(((cast(*void)(*instance.attachment)) - cast(*void)(*instance)) == 24, "FloatingElementConfig.attachment has unexpected offset % instead of 24", ((cast(*void)(*instance.attachment)) - cast(*void)(*instance)));
assert(size_of(type_of(FloatingElementConfig.attachment)) == 2, "FloatingElementConfig.attachment has unexpected size % instead of 2", size_of(type_of(FloatingElementConfig.attachment)));
assert(((cast(*void)(*instance.pointerCaptureMode)) - cast(*void)(*instance)) == 28, "FloatingElementConfig.pointerCaptureMode has unexpected offset % instead of 28", ((cast(*void)(*instance.pointerCaptureMode)) - cast(*void)(*instance)));
assert(size_of(type_of(FloatingElementConfig.pointerCaptureMode)) == 4, "FloatingElementConfig.pointerCaptureMode has unexpected size % instead of 4", size_of(type_of(FloatingElementConfig.pointerCaptureMode)));
assert(size_of(FloatingElementConfig) == 32, "FloatingElementConfig has size % instead of 32", size_of(FloatingElementConfig));
}
{
instance: CustomElementConfig;
assert(((cast(*void)(*instance.customData)) - cast(*void)(*instance)) == 0, "CustomElementConfig.customData has unexpected offset % instead of 0", ((cast(*void)(*instance.customData)) - cast(*void)(*instance)));
assert(size_of(type_of(CustomElementConfig.customData)) == 8, "CustomElementConfig.customData has unexpected size % instead of 8", size_of(type_of(CustomElementConfig.customData)));
assert(size_of(CustomElementConfig) == 8, "CustomElementConfig has size % instead of 8", size_of(CustomElementConfig));
}
{
instance: ScrollElementConfig;
assert(((cast(*void)(*instance.horizontal)) - cast(*void)(*instance)) == 0, "ScrollElementConfig.horizontal has unexpected offset % instead of 0", ((cast(*void)(*instance.horizontal)) - cast(*void)(*instance)));
assert(size_of(type_of(ScrollElementConfig.horizontal)) == 1, "ScrollElementConfig.horizontal has unexpected size % instead of 1", size_of(type_of(ScrollElementConfig.horizontal)));
assert(((cast(*void)(*instance.vertical)) - cast(*void)(*instance)) == 1, "ScrollElementConfig.vertical has unexpected offset % instead of 1", ((cast(*void)(*instance.vertical)) - cast(*void)(*instance)));
assert(size_of(type_of(ScrollElementConfig.vertical)) == 1, "ScrollElementConfig.vertical has unexpected size % instead of 1", size_of(type_of(ScrollElementConfig.vertical)));
assert(size_of(ScrollElementConfig) == 2, "ScrollElementConfig has size % instead of 2", size_of(ScrollElementConfig));
}
{
instance: ElementConfigUnion;
assert(((cast(*void)(*instance.rectangleElementConfig)) - cast(*void)(*instance)) == 0, "ElementConfigUnion.rectangleElementConfig has unexpected offset % instead of 0", ((cast(*void)(*instance.rectangleElementConfig)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfigUnion.rectangleElementConfig)) == 8, "ElementConfigUnion.rectangleElementConfig has unexpected size % instead of 8", size_of(type_of(ElementConfigUnion.rectangleElementConfig)));
assert(((cast(*void)(*instance.textElementConfig)) - cast(*void)(*instance)) == 0, "ElementConfigUnion.textElementConfig has unexpected offset % instead of 0", ((cast(*void)(*instance.textElementConfig)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfigUnion.textElementConfig)) == 8, "ElementConfigUnion.textElementConfig has unexpected size % instead of 8", size_of(type_of(ElementConfigUnion.textElementConfig)));
assert(((cast(*void)(*instance.imageElementConfig)) - cast(*void)(*instance)) == 0, "ElementConfigUnion.imageElementConfig has unexpected offset % instead of 0", ((cast(*void)(*instance.imageElementConfig)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfigUnion.imageElementConfig)) == 8, "ElementConfigUnion.imageElementConfig has unexpected size % instead of 8", size_of(type_of(ElementConfigUnion.imageElementConfig)));
assert(((cast(*void)(*instance.floatingElementConfig)) - cast(*void)(*instance)) == 0, "ElementConfigUnion.floatingElementConfig has unexpected offset % instead of 0", ((cast(*void)(*instance.floatingElementConfig)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfigUnion.floatingElementConfig)) == 8, "ElementConfigUnion.floatingElementConfig has unexpected size % instead of 8", size_of(type_of(ElementConfigUnion.floatingElementConfig)));
assert(((cast(*void)(*instance.customElementConfig)) - cast(*void)(*instance)) == 0, "ElementConfigUnion.customElementConfig has unexpected offset % instead of 0", ((cast(*void)(*instance.customElementConfig)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfigUnion.customElementConfig)) == 8, "ElementConfigUnion.customElementConfig has unexpected size % instead of 8", size_of(type_of(ElementConfigUnion.customElementConfig)));
assert(((cast(*void)(*instance.scrollElementConfig)) - cast(*void)(*instance)) == 0, "ElementConfigUnion.scrollElementConfig has unexpected offset % instead of 0", ((cast(*void)(*instance.scrollElementConfig)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfigUnion.scrollElementConfig)) == 8, "ElementConfigUnion.scrollElementConfig has unexpected size % instead of 8", size_of(type_of(ElementConfigUnion.scrollElementConfig)));
assert(((cast(*void)(*instance.borderElementConfig)) - cast(*void)(*instance)) == 0, "ElementConfigUnion.borderElementConfig has unexpected offset % instead of 0", ((cast(*void)(*instance.borderElementConfig)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfigUnion.borderElementConfig)) == 8, "ElementConfigUnion.borderElementConfig has unexpected size % instead of 8", size_of(type_of(ElementConfigUnion.borderElementConfig)));
assert(size_of(ElementConfigUnion) == 8, "ElementConfigUnion has size % instead of 8", size_of(ElementConfigUnion));
}
{
instance: ElementConfig;
assert(((cast(*void)(*instance.type)) - cast(*void)(*instance)) == 0, "ElementConfig.type has unexpected offset % instead of 0", ((cast(*void)(*instance.type)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfig.type)) == 1, "ElementConfig.type has unexpected size % instead of 1", size_of(type_of(ElementConfig.type)));
assert(((cast(*void)(*instance.config)) - cast(*void)(*instance)) == 8, "ElementConfig.config has unexpected offset % instead of 8", ((cast(*void)(*instance.config)) - cast(*void)(*instance)));
assert(size_of(type_of(ElementConfig.config)) == 8, "ElementConfig.config has unexpected size % instead of 8", size_of(type_of(ElementConfig.config)));
assert(size_of(ElementConfig) == 16, "ElementConfig has size % instead of 16", size_of(ElementConfig));
}
{
instance: ScrollContainerData;
assert(((cast(*void)(*instance.scrollPosition)) - cast(*void)(*instance)) == 0, "ScrollContainerData.scrollPosition has unexpected offset % instead of 0", ((cast(*void)(*instance.scrollPosition)) - cast(*void)(*instance)));
assert(size_of(type_of(ScrollContainerData.scrollPosition)) == 8, "ScrollContainerData.scrollPosition has unexpected size % instead of 8", size_of(type_of(ScrollContainerData.scrollPosition)));
assert(((cast(*void)(*instance.scrollContainerDimensions)) - cast(*void)(*instance)) == 8, "ScrollContainerData.scrollContainerDimensions has unexpected offset % instead of 8", ((cast(*void)(*instance.scrollContainerDimensions)) - cast(*void)(*instance)));
assert(size_of(type_of(ScrollContainerData.scrollContainerDimensions)) == 8, "ScrollContainerData.scrollContainerDimensions has unexpected size % instead of 8", size_of(type_of(ScrollContainerData.scrollContainerDimensions)));
assert(((cast(*void)(*instance.contentDimensions)) - cast(*void)(*instance)) == 16, "ScrollContainerData.contentDimensions has unexpected offset % instead of 16", ((cast(*void)(*instance.contentDimensions)) - cast(*void)(*instance)));
assert(size_of(type_of(ScrollContainerData.contentDimensions)) == 8, "ScrollContainerData.contentDimensions has unexpected size % instead of 8", size_of(type_of(ScrollContainerData.contentDimensions)));
assert(((cast(*void)(*instance.config)) - cast(*void)(*instance)) == 24, "ScrollContainerData.config has unexpected offset % instead of 24", ((cast(*void)(*instance.config)) - cast(*void)(*instance)));
assert(size_of(type_of(ScrollContainerData.config)) == 2, "ScrollContainerData.config has unexpected size % instead of 2", size_of(type_of(ScrollContainerData.config)));
assert(((cast(*void)(*instance.found)) - cast(*void)(*instance)) == 26, "ScrollContainerData.found has unexpected offset % instead of 26", ((cast(*void)(*instance.found)) - cast(*void)(*instance)));
assert(size_of(type_of(ScrollContainerData.found)) == 1, "ScrollContainerData.found has unexpected size % instead of 1", size_of(type_of(ScrollContainerData.found)));
assert(size_of(ScrollContainerData) == 32, "ScrollContainerData has size % instead of 32", size_of(ScrollContainerData));
}
{
instance: RenderCommand;
assert(((cast(*void)(*instance.boundingBox)) - cast(*void)(*instance)) == 0, "RenderCommand.boundingBox has unexpected offset % instead of 0", ((cast(*void)(*instance.boundingBox)) - cast(*void)(*instance)));
assert(size_of(type_of(RenderCommand.boundingBox)) == 16, "RenderCommand.boundingBox has unexpected size % instead of 16", size_of(type_of(RenderCommand.boundingBox)));
assert(((cast(*void)(*instance.config)) - cast(*void)(*instance)) == 16, "RenderCommand.config has unexpected offset % instead of 16", ((cast(*void)(*instance.config)) - cast(*void)(*instance)));
assert(size_of(type_of(RenderCommand.config)) == 8, "RenderCommand.config has unexpected size % instead of 8", size_of(type_of(RenderCommand.config)));
assert(((cast(*void)(*instance.text)) - cast(*void)(*instance)) == 24, "RenderCommand.text has unexpected offset % instead of 24", ((cast(*void)(*instance.text)) - cast(*void)(*instance)));
assert(size_of(type_of(RenderCommand.text)) == 16, "RenderCommand.text has unexpected size % instead of 16", size_of(type_of(RenderCommand.text)));
assert(((cast(*void)(*instance.id)) - cast(*void)(*instance)) == 40, "RenderCommand.id has unexpected offset % instead of 40", ((cast(*void)(*instance.id)) - cast(*void)(*instance)));
assert(size_of(type_of(RenderCommand.id)) == 4, "RenderCommand.id has unexpected size % instead of 4", size_of(type_of(RenderCommand.id)));
assert(((cast(*void)(*instance.commandType)) - cast(*void)(*instance)) == 44, "RenderCommand.commandType has unexpected offset % instead of 44", ((cast(*void)(*instance.commandType)) - cast(*void)(*instance)));
assert(size_of(type_of(RenderCommand.commandType)) == 1, "RenderCommand.commandType has unexpected size % instead of 1", size_of(type_of(RenderCommand.commandType)));
assert(size_of(RenderCommand) == 48, "RenderCommand has size % instead of 48", size_of(RenderCommand));
}
{
instance: RenderCommandArray;
assert(((cast(*void)(*instance.capacity)) - cast(*void)(*instance)) == 0, "RenderCommandArray.capacity has unexpected offset % instead of 0", ((cast(*void)(*instance.capacity)) - cast(*void)(*instance)));
assert(size_of(type_of(RenderCommandArray.capacity)) == 4, "RenderCommandArray.capacity has unexpected size % instead of 4", size_of(type_of(RenderCommandArray.capacity)));
assert(((cast(*void)(*instance.length)) - cast(*void)(*instance)) == 4, "RenderCommandArray.length has unexpected offset % instead of 4", ((cast(*void)(*instance.length)) - cast(*void)(*instance)));
assert(size_of(type_of(RenderCommandArray.length)) == 4, "RenderCommandArray.length has unexpected size % instead of 4", size_of(type_of(RenderCommandArray.length)));
assert(((cast(*void)(*instance.internalArray)) - cast(*void)(*instance)) == 8, "RenderCommandArray.internalArray has unexpected offset % instead of 8", ((cast(*void)(*instance.internalArray)) - cast(*void)(*instance)));
assert(size_of(type_of(RenderCommandArray.internalArray)) == 8, "RenderCommandArray.internalArray has unexpected size % instead of 8", size_of(type_of(RenderCommandArray.internalArray)));
assert(size_of(RenderCommandArray) == 16, "RenderCommandArray has size % instead of 16", size_of(RenderCommandArray));
}
{
instance: PointerData;
assert(((cast(*void)(*instance.position)) - cast(*void)(*instance)) == 0, "PointerData.position has unexpected offset % instead of 0", ((cast(*void)(*instance.position)) - cast(*void)(*instance)));
assert(size_of(type_of(PointerData.position)) == 8, "PointerData.position has unexpected size % instead of 8", size_of(type_of(PointerData.position)));
assert(((cast(*void)(*instance.state)) - cast(*void)(*instance)) == 8, "PointerData.state has unexpected offset % instead of 8", ((cast(*void)(*instance.state)) - cast(*void)(*instance)));
assert(size_of(type_of(PointerData.state)) == 4, "PointerData.state has unexpected size % instead of 4", size_of(type_of(PointerData.state)));
assert(size_of(PointerData) == 12, "PointerData has size % instead of 12", size_of(PointerData));
}
{
instance: ErrorData;
assert(((cast(*void)(*instance.errorType)) - cast(*void)(*instance)) == 0, "ErrorData.errorType has unexpected offset % instead of 0", ((cast(*void)(*instance.errorType)) - cast(*void)(*instance)));
assert(size_of(type_of(ErrorData.errorType)) == 4, "ErrorData.errorType has unexpected size % instead of 4", size_of(type_of(ErrorData.errorType)));
assert(((cast(*void)(*instance.errorText)) - cast(*void)(*instance)) == 8, "ErrorData.errorText has unexpected offset % instead of 8", ((cast(*void)(*instance.errorText)) - cast(*void)(*instance)));
assert(size_of(type_of(ErrorData.errorText)) == 16, "ErrorData.errorText has unexpected size % instead of 16", size_of(type_of(ErrorData.errorText)));
assert(((cast(*void)(*instance.userData)) - cast(*void)(*instance)) == 24, "ErrorData.userData has unexpected offset % instead of 24", ((cast(*void)(*instance.userData)) - cast(*void)(*instance)));
assert(size_of(type_of(ErrorData.userData)) == 8, "ErrorData.userData has unexpected size % instead of 8", size_of(type_of(ErrorData.userData)));
assert(size_of(ErrorData) == 32, "ErrorData has size % instead of 32", size_of(ErrorData));
}
{
instance: ErrorHandler;
assert(((cast(*void)(*instance.errorHandlerFunction)) - cast(*void)(*instance)) == 0, "ErrorHandler.errorHandlerFunction has unexpected offset % instead of 0", ((cast(*void)(*instance.errorHandlerFunction)) - cast(*void)(*instance)));
assert(size_of(type_of(ErrorHandler.errorHandlerFunction)) == 8, "ErrorHandler.errorHandlerFunction has unexpected size % instead of 8", size_of(type_of(ErrorHandler.errorHandlerFunction)));
assert(((cast(*void)(*instance.userData)) - cast(*void)(*instance)) == 8, "ErrorHandler.userData has unexpected offset % instead of 8", ((cast(*void)(*instance.userData)) - cast(*void)(*instance)));
assert(size_of(type_of(ErrorHandler.userData)) == 8, "ErrorHandler.userData has unexpected size % instead of 8", size_of(type_of(ErrorHandler.userData)));
assert(size_of(ErrorHandler) == 16, "ErrorHandler has size % instead of 16", size_of(ErrorHandler));
}
}

Binary file not shown.

View File

@ -26,8 +26,6 @@ Another option used in these bindings : https://github.com/nick-celestin-zizic/c
But I'm not a big fan of that since it's possible to forget the scope braces or to put the children before the element.
TODO This part is wrong... delete it and write the code that works
Another option to consider is to pass a code block to a macro that puts it between the start and the end.
UI :: (id: ElementId, layout: LayoutConfig, configs: ..ElementConfig, $code: Code) {
@ -75,7 +73,7 @@ With the downside that it's not obvious why the for is there before reading the
Vector2 :: Math.Vector2;
ElementConfigType :: enum u8 {
ElementConfigType :: enum s32 {
NONE :: 0;
RECTANGLE :: 1;
BORDER_CONTAINER :: 2;
@ -96,8 +94,8 @@ ElementConfigType :: enum u8 {
// Jai bindings specific types, please don't assume any value in those
// a it might change if the enums above overlap with it
// TODO Check if these values need to be powers of two
ID :: 250;
LAYOUT :: 251;
ID :: 256;
LAYOUT :: 257;
}
// This is passed to UI so that we can omit layout
@ -289,8 +287,6 @@ InternalElementConfigArray :: struct {
#if OS == .WINDOWS {
#load "windows.jai";
} else #if OS == .LINUX {
#load "linux.jai";
} else {
assert(false);
}

View File

@ -75,8 +75,7 @@ main :: () {
flags := Raylib.ConfigFlags.WINDOW_RESIZABLE | .MSAA_4X_HINT | .VSYNC_HINT;
raylib_initialize(1024, 768, "Introducing Clay Demo", flags);
// For some reason, on linux, this is 8 bytes off ???
clay_required_memory := Clay.MinMemorySize() + 8;
clay_required_memory := Clay.MinMemorySize();
memory := alloc(clay_required_memory);
clay_memory := Clay.CreateArenaWithCapacityAndMemory(clay_required_memory, memory);
Clay.Initialize(

View File

@ -1,4 +0,0 @@
.build
.vscode
raylib/
.DS_Store

View File

@ -61,17 +61,17 @@ UpdateCamera :: (camera: *Camera, mode: CameraMode) -> void { return UpdateCamer
SetTraceLogLevel :: (logLevel: TraceLogLevel) -> void { return SetTraceLogLevel(cast(s32) logLevel); }
TraceLog :: (logLevel: TraceLogLevel, text: string, __args: ..Any) { TraceLog(cast(s32) logLevel, text, __args); }
SetShaderValue :: (shader: Shader, locIndex: s32, value: *void, uniformType: ShaderUniformDataType) -> void {
return SetShaderValue(shader, locIndex, value, cast(s32) uniformType);
SetShaderValue :: (shader: Shader, locIndex: s32, value: *void, uniformType: ShaderUniformDataType) -> void {
return SetShaderValue(shader, locIndex, value, cast(s32) uniformType);
}
SetShaderValueV :: (shader: Shader, locIndex: s32, value: *void, uniformType: ShaderUniformDataType, count: s32) -> void {
return SetShaderValue(shader, locIndex, value, cast(s32) uniformType, count);
SetShaderValueV :: (shader: Shader, locIndex: s32, value: *void, uniformType: ShaderUniformDataType, count: s32) -> void {
return SetShaderValue(shader, locIndex, value, cast(s32) uniformType, count);
}
IsGamepadButtonPressed :: (gamepad: s32, button: GamepadButton) -> bool { return IsGamepadButtonPressed(gamepad, cast(s32) button); }
IsGamepadButtonDown :: (gamepad: s32, button: GamepadButton) -> bool { return IsGamepadButtonDown(gamepad, cast(s32) button); }
IsGamepadButtonPressed :: (gamepad: s32, button: GamepadButton) -> bool { return IsGamepadButtonPressed(gamepad, cast(s32) button); }
IsGamepadButtonDown :: (gamepad: s32, button: GamepadButton) -> bool { return IsGamepadButtonDown(gamepad, cast(s32) button); }
IsGamepadButtonReleased :: (gamepad: s32, button: GamepadButton) -> bool { return IsGamepadButtonReleased(gamepad, cast(s32) button); }
IsGamepadButtonUp :: (gamepad: s32, button: GamepadButton) -> bool { return IsGamepadButtonUp(gamepad, cast(s32) button); }
IsGamepadButtonUp :: (gamepad: s32, button: GamepadButton) -> bool { return IsGamepadButtonUp(gamepad, cast(s32) button); }
GetGamepadAxisMovement :: (gamepad: s32, axis: GamepadAxis) -> float { return GetGamepadAxisMovement(gamepad, cast(s32) axis); }
@ -82,8 +82,8 @@ BeginBlendMode :: (mode: BlendMode) -> void { return BeginBlendMode(cast(s32) mo
ImageFormat :: (image: *Image, newFormat: PixelFormat) -> void { return ImageFormat(image, cast(s32) newFormat); }
LoadImageRaw :: (fileName: *u8, width: s32, height: s32, format: PixelFormat, headerSize: s32) -> Image {
return LoadImageRaw(fileName, width, height, cast(s32) format, headerSize);
LoadImageRaw :: (fileName: *u8, width: s32, height: s32, format: PixelFormat, headerSize: s32) -> Image {
return LoadImageRaw(fileName, width, height, cast(s32) format, headerSize);
}
LoadFontData :: (fileData: *u8, dataSize: s32, fontSize: s32, codepoints: *s32, codepointCount: s32, type: FontType) -> *GlyphInfo {
@ -123,23 +123,8 @@ TraceLogCallback :: #type (logLevel: TraceLogLevel, text: *u8, args: .. Any) #c_
winmm :: #system_library,link_always "winmm";
raylib :: #library,no_dll "windows/raylib";
#load "windows.jai";
} else #if OS == .LINUX {
math :: #system_library,link_always "m";
raylib :: #library,no_dll "linux/raylib";
#load "linux.jai";
} else #if OS == .MACOS {
#system_library,link_always "Cocoa";
#system_library,link_always "OpenGL";
#system_library,link_always "CoreGraphics";
#system_library,link_always "AppKit";
#system_library,link_always "IOKit";
raylib :: #library,no_dll "macos/raylib";
#load "macos.jai";
} else {
assert(false);
}

View File

@ -1,7 +1,7 @@
//
// This file was auto-generated using the following command:
//
// jai generate.jai - -compile
// jai ./generate.jai - -compile
//
@ -24,6 +24,8 @@ RAD2DEG :: 180.0/PI;
GetMouseRay :: GetScreenToWorldRay;
EPSILON :: 0.000001;
RLGL_VERSION :: "5.0";
RL_DEFAULT_BATCH_BUFFER_ELEMENTS :: 8192;
@ -133,8 +135,6 @@ RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 :: 5;
RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES :: 6;
EPSILON :: 0.000001;
// Color, 4 components, R8G8B8A8 (32bit)
Color :: struct {
r: u8; // Color red value
@ -1868,316 +1868,6 @@ DetachAudioStreamProcessor :: (stream: AudioStream, processor: AudioCallback) ->
AttachAudioMixedProcessor :: (processor: AudioCallback) -> void #foreign raylib;
DetachAudioMixedProcessor :: (processor: AudioCallback) -> void #foreign raylib;
// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
VertexBuffer :: struct {
elementCount: s32; // Number of elements in the buffer (QUADS)
vertices: *float; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
texcoords: *float; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
normals: *float; // Vertex normal (XYZ - 3 components per vertex) (shader-location = 2)
colors: *u8; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
indices: *u32; // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
vaoId: u32; // OpenGL Vertex Array Object id
vboId: [5] u32; // OpenGL Vertex Buffer Objects id (5 types of vertex data)
}
// Draw call type
// NOTE: Only texture changes register a new draw, other state-change-related elements are not
// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any
// of those state-change happens (this is done in core module)
DrawCall :: struct {
mode: s32; // Drawing mode: LINES, TRIANGLES, QUADS
vertexCount: s32; // Number of vertex of the draw
vertexAlignment: s32; // Number of vertex required for index alignment (LINES, TRIANGLES)
textureId: u32; // Texture id to be used on the draw -> Use to create new draw call if changes
}
// rlRenderBatch type
RenderBatch :: struct {
bufferCount: s32; // Number of vertex buffers (multi-buffering support)
currentBuffer: s32; // Current buffer tracking in case of multi-buffering
vertexBuffer: *VertexBuffer; // Dynamic buffer(s) for vertex data
draws: *DrawCall; // Draw calls array, depends on textureId
drawCounter: s32; // Draw calls counter
currentDepth: float; // Current depth value for next draw
}
// OpenGL version
GlVersion :: enum s32 {
_11 :: 1;
_21 :: 2;
_33 :: 3;
_43 :: 4;
ES_20 :: 5;
ES_30 :: 6;
RL_OPENGL_11 :: _11;
RL_OPENGL_21 :: _21;
RL_OPENGL_33 :: _33;
RL_OPENGL_43 :: _43;
RL_OPENGL_ES_20 :: ES_20;
RL_OPENGL_ES_30 :: ES_30;
}
// Framebuffer attachment type
// NOTE: By default up to 8 color channels defined, but it can be more
FramebufferAttachType :: enum s32 {
COLOR_CHANNEL0 :: 0;
COLOR_CHANNEL1 :: 1;
COLOR_CHANNEL2 :: 2;
COLOR_CHANNEL3 :: 3;
COLOR_CHANNEL4 :: 4;
COLOR_CHANNEL5 :: 5;
COLOR_CHANNEL6 :: 6;
COLOR_CHANNEL7 :: 7;
DEPTH :: 100;
STENCIL :: 200;
RL_ATTACHMENT_COLOR_CHANNEL0 :: COLOR_CHANNEL0;
RL_ATTACHMENT_COLOR_CHANNEL1 :: COLOR_CHANNEL1;
RL_ATTACHMENT_COLOR_CHANNEL2 :: COLOR_CHANNEL2;
RL_ATTACHMENT_COLOR_CHANNEL3 :: COLOR_CHANNEL3;
RL_ATTACHMENT_COLOR_CHANNEL4 :: COLOR_CHANNEL4;
RL_ATTACHMENT_COLOR_CHANNEL5 :: COLOR_CHANNEL5;
RL_ATTACHMENT_COLOR_CHANNEL6 :: COLOR_CHANNEL6;
RL_ATTACHMENT_COLOR_CHANNEL7 :: COLOR_CHANNEL7;
RL_ATTACHMENT_DEPTH :: DEPTH;
RL_ATTACHMENT_STENCIL :: STENCIL;
}
// Framebuffer texture attachment type
FramebufferAttachTextureType :: enum s32 {
CUBEMAP_POSITIVE_X :: 0;
CUBEMAP_NEGATIVE_X :: 1;
CUBEMAP_POSITIVE_Y :: 2;
CUBEMAP_NEGATIVE_Y :: 3;
CUBEMAP_POSITIVE_Z :: 4;
CUBEMAP_NEGATIVE_Z :: 5;
TEXTURE2D :: 100;
RENDERBUFFER :: 200;
RL_ATTACHMENT_CUBEMAP_POSITIVE_X :: CUBEMAP_POSITIVE_X;
RL_ATTACHMENT_CUBEMAP_NEGATIVE_X :: CUBEMAP_NEGATIVE_X;
RL_ATTACHMENT_CUBEMAP_POSITIVE_Y :: CUBEMAP_POSITIVE_Y;
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y :: CUBEMAP_NEGATIVE_Y;
RL_ATTACHMENT_CUBEMAP_POSITIVE_Z :: CUBEMAP_POSITIVE_Z;
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z :: CUBEMAP_NEGATIVE_Z;
RL_ATTACHMENT_TEXTURE2D :: TEXTURE2D;
RL_ATTACHMENT_RENDERBUFFER :: RENDERBUFFER;
}
// Face culling mode
CullMode :: enum s32 {
FRONT :: 0;
BACK :: 1;
RL_CULL_FACE_FRONT :: FRONT;
RL_CULL_FACE_BACK :: BACK;
}
MatrixMode :: (mode: s32) -> void #foreign raylib "rlMatrixMode";
PushMatrix :: () -> void #foreign raylib "rlPushMatrix";
PopMatrix :: () -> void #foreign raylib "rlPopMatrix";
LoadIdentity :: () -> void #foreign raylib "rlLoadIdentity";
Translatef :: (x: float, y: float, z: float) -> void #foreign raylib "rlTranslatef";
Rotatef :: (angle: float, x: float, y: float, z: float) -> void #foreign raylib "rlRotatef";
Scalef :: (x: float, y: float, z: float) -> void #foreign raylib "rlScalef";
MultMatrixf :: (matf: *float) -> void #foreign raylib "rlMultMatrixf";
Frustum :: (left: float64, right: float64, bottom: float64, top: float64, znear: float64, zfar: float64) -> void #foreign raylib "rlFrustum";
Ortho :: (left: float64, right: float64, bottom: float64, top: float64, znear: float64, zfar: float64) -> void #foreign raylib "rlOrtho";
Viewport :: (x: s32, y: s32, width: s32, height: s32) -> void #foreign raylib "rlViewport";
SetClipPlanes :: (nearPlane: float64, farPlane: float64) -> void #foreign raylib "rlSetClipPlanes";
GetCullDistanceNear :: () -> float64 #foreign raylib "rlGetCullDistanceNear";
GetCullDistanceFar :: () -> float64 #foreign raylib "rlGetCullDistanceFar";
//------------------------------------------------------------------------------------
// Functions Declaration - Vertex level operations
//------------------------------------------------------------------------------------
Begin :: (mode: s32) -> void #foreign raylib "rlBegin";
End :: () -> void #foreign raylib "rlEnd";
Vertex2i :: (x: s32, y: s32) -> void #foreign raylib "rlVertex2i";
Vertex2f :: (x: float, y: float) -> void #foreign raylib "rlVertex2f";
Vertex3f :: (x: float, y: float, z: float) -> void #foreign raylib "rlVertex3f";
TexCoord2f :: (x: float, y: float) -> void #foreign raylib "rlTexCoord2f";
Normal3f :: (x: float, y: float, z: float) -> void #foreign raylib "rlNormal3f";
Color4ub :: (r: u8, g: u8, b: u8, a: u8) -> void #foreign raylib "rlColor4ub";
Color3f :: (x: float, y: float, z: float) -> void #foreign raylib "rlColor3f";
Color4f :: (x: float, y: float, z: float, w: float) -> void #foreign raylib "rlColor4f";
// Vertex buffers state
EnableVertexArray :: (vaoId: u32) -> bool #foreign raylib "rlEnableVertexArray";
DisableVertexArray :: () -> void #foreign raylib "rlDisableVertexArray";
EnableVertexBuffer :: (id: u32) -> void #foreign raylib "rlEnableVertexBuffer";
DisableVertexBuffer :: () -> void #foreign raylib "rlDisableVertexBuffer";
EnableVertexBufferElement :: (id: u32) -> void #foreign raylib "rlEnableVertexBufferElement";
DisableVertexBufferElement :: () -> void #foreign raylib "rlDisableVertexBufferElement";
EnableVertexAttribute :: (index: u32) -> void #foreign raylib "rlEnableVertexAttribute";
DisableVertexAttribute :: (index: u32) -> void #foreign raylib "rlDisableVertexAttribute";
// Textures state
ActiveTextureSlot :: (slot: s32) -> void #foreign raylib "rlActiveTextureSlot";
EnableTexture :: (id: u32) -> void #foreign raylib "rlEnableTexture";
DisableTexture :: () -> void #foreign raylib "rlDisableTexture";
EnableTextureCubemap :: (id: u32) -> void #foreign raylib "rlEnableTextureCubemap";
DisableTextureCubemap :: () -> void #foreign raylib "rlDisableTextureCubemap";
TextureParameters :: (id: u32, param: s32, value: s32) -> void #foreign raylib "rlTextureParameters";
CubemapParameters :: (id: u32, param: s32, value: s32) -> void #foreign raylib "rlCubemapParameters";
// Shader state
EnableShader :: (id: u32) -> void #foreign raylib "rlEnableShader";
DisableShader :: () -> void #foreign raylib "rlDisableShader";
// Framebuffer state
EnableFramebuffer :: (id: u32) -> void #foreign raylib "rlEnableFramebuffer";
DisableFramebuffer :: () -> void #foreign raylib "rlDisableFramebuffer";
GetActiveFramebuffer :: () -> u32 #foreign raylib "rlGetActiveFramebuffer";
ActiveDrawBuffers :: (count: s32) -> void #foreign raylib "rlActiveDrawBuffers";
BlitFramebuffer :: (srcX: s32, srcY: s32, srcWidth: s32, srcHeight: s32, dstX: s32, dstY: s32, dstWidth: s32, dstHeight: s32, bufferMask: s32) -> void #foreign raylib "rlBlitFramebuffer";
BindFramebuffer :: (target: u32, framebuffer: u32) -> void #foreign raylib "rlBindFramebuffer";
// General render state
EnableColorBlend :: () -> void #foreign raylib "rlEnableColorBlend";
DisableColorBlend :: () -> void #foreign raylib "rlDisableColorBlend";
EnableDepthTest :: () -> void #foreign raylib "rlEnableDepthTest";
DisableDepthTest :: () -> void #foreign raylib "rlDisableDepthTest";
EnableDepthMask :: () -> void #foreign raylib "rlEnableDepthMask";
DisableDepthMask :: () -> void #foreign raylib "rlDisableDepthMask";
EnableBackfaceCulling :: () -> void #foreign raylib "rlEnableBackfaceCulling";
DisableBackfaceCulling :: () -> void #foreign raylib "rlDisableBackfaceCulling";
ColorMask :: (r: bool, g: bool, b: bool, a: bool) -> void #foreign raylib "rlColorMask";
SetCullFace :: (mode: s32) -> void #foreign raylib "rlSetCullFace";
EnableScissorTest :: () -> void #foreign raylib "rlEnableScissorTest";
DisableScissorTest :: () -> void #foreign raylib "rlDisableScissorTest";
Scissor :: (x: s32, y: s32, width: s32, height: s32) -> void #foreign raylib "rlScissor";
EnableWireMode :: () -> void #foreign raylib "rlEnableWireMode";
EnablePointMode :: () -> void #foreign raylib "rlEnablePointMode";
DisableWireMode :: () -> void #foreign raylib "rlDisableWireMode";
SetLineWidth :: (width: float) -> void #foreign raylib "rlSetLineWidth";
GetLineWidth :: () -> float #foreign raylib "rlGetLineWidth";
EnableSmoothLines :: () -> void #foreign raylib "rlEnableSmoothLines";
DisableSmoothLines :: () -> void #foreign raylib "rlDisableSmoothLines";
EnableStereoRender :: () -> void #foreign raylib "rlEnableStereoRender";
DisableStereoRender :: () -> void #foreign raylib "rlDisableStereoRender";
IsStereoRenderEnabled :: () -> bool #foreign raylib "rlIsStereoRenderEnabled";
ClearColor :: (r: u8, g: u8, b: u8, a: u8) -> void #foreign raylib "rlClearColor";
ClearScreenBuffers :: () -> void #foreign raylib "rlClearScreenBuffers";
CheckErrors :: () -> void #foreign raylib "rlCheckErrors";
SetBlendMode :: (mode: s32) -> void #foreign raylib "rlSetBlendMode";
SetBlendFactors :: (glSrcFactor: s32, glDstFactor: s32, glEquation: s32) -> void #foreign raylib "rlSetBlendFactors";
SetBlendFactorsSeparate :: (glSrcRGB: s32, glDstRGB: s32, glSrcAlpha: s32, glDstAlpha: s32, glEqRGB: s32, glEqAlpha: s32) -> void #foreign raylib "rlSetBlendFactorsSeparate";
//------------------------------------------------------------------------------------
// Functions Declaration - rlgl functionality
//------------------------------------------------------------------------------------
// rlgl initialization functions
glInit :: (width: s32, height: s32) -> void #foreign raylib "rlglInit";
glClose :: () -> void #foreign raylib "rlglClose";
LoadExtensions :: (loader: *void) -> void #foreign raylib "rlLoadExtensions";
GetVersion :: () -> s32 #foreign raylib "rlGetVersion";
SetFramebufferWidth :: (width: s32) -> void #foreign raylib "rlSetFramebufferWidth";
GetFramebufferWidth :: () -> s32 #foreign raylib "rlGetFramebufferWidth";
SetFramebufferHeight :: (height: s32) -> void #foreign raylib "rlSetFramebufferHeight";
GetFramebufferHeight :: () -> s32 #foreign raylib "rlGetFramebufferHeight";
GetTextureIdDefault :: () -> u32 #foreign raylib "rlGetTextureIdDefault";
GetShaderIdDefault :: () -> u32 #foreign raylib "rlGetShaderIdDefault";
GetShaderLocsDefault :: () -> *s32 #foreign raylib "rlGetShaderLocsDefault";
// Render batch management
// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
// but this render batch API is exposed in case of custom batches are required
LoadRenderBatch :: (numBuffers: s32, bufferElements: s32) -> RenderBatch #foreign raylib "rlLoadRenderBatch";
UnloadRenderBatch :: (batch: RenderBatch) -> void #foreign raylib "rlUnloadRenderBatch";
DrawRenderBatch :: (batch: *RenderBatch) -> void #foreign raylib "rlDrawRenderBatch";
SetRenderBatchActive :: (batch: *RenderBatch) -> void #foreign raylib "rlSetRenderBatchActive";
DrawRenderBatchActive :: () -> void #foreign raylib "rlDrawRenderBatchActive";
CheckRenderBatchLimit :: (vCount: s32) -> bool #foreign raylib "rlCheckRenderBatchLimit";
SetTexture :: (id: u32) -> void #foreign raylib "rlSetTexture";
// Vertex buffers management
LoadVertexArray :: () -> u32 #foreign raylib "rlLoadVertexArray";
LoadVertexBuffer :: (buffer: *void, size: s32, dynamic: bool) -> u32 #foreign raylib "rlLoadVertexBuffer";
LoadVertexBufferElement :: (buffer: *void, size: s32, dynamic: bool) -> u32 #foreign raylib "rlLoadVertexBufferElement";
UpdateVertexBuffer :: (bufferId: u32, data: *void, dataSize: s32, offset: s32) -> void #foreign raylib "rlUpdateVertexBuffer";
UpdateVertexBufferElements :: (id: u32, data: *void, dataSize: s32, offset: s32) -> void #foreign raylib "rlUpdateVertexBufferElements";
UnloadVertexArray :: (vaoId: u32) -> void #foreign raylib "rlUnloadVertexArray";
UnloadVertexBuffer :: (vboId: u32) -> void #foreign raylib "rlUnloadVertexBuffer";
SetVertexAttribute :: (index: u32, compSize: s32, type: s32, normalized: bool, stride: s32, offset: s32) -> void #foreign raylib "rlSetVertexAttribute";
SetVertexAttributeDivisor :: (index: u32, divisor: s32) -> void #foreign raylib "rlSetVertexAttributeDivisor";
SetVertexAttributeDefault :: (locIndex: s32, value: *void, attribType: s32, count: s32) -> void #foreign raylib "rlSetVertexAttributeDefault";
DrawVertexArray :: (offset: s32, count: s32) -> void #foreign raylib "rlDrawVertexArray";
DrawVertexArrayElements :: (offset: s32, count: s32, buffer: *void) -> void #foreign raylib "rlDrawVertexArrayElements";
DrawVertexArrayInstanced :: (offset: s32, count: s32, instances: s32) -> void #foreign raylib "rlDrawVertexArrayInstanced";
DrawVertexArrayElementsInstanced :: (offset: s32, count: s32, buffer: *void, instances: s32) -> void #foreign raylib "rlDrawVertexArrayElementsInstanced";
// Textures management
LoadTexture :: (data: *void, width: s32, height: s32, format: s32, mipmapCount: s32) -> u32 #foreign raylib "rlLoadTexture";
LoadTextureDepth :: (width: s32, height: s32, useRenderBuffer: bool) -> u32 #foreign raylib "rlLoadTextureDepth";
LoadTextureCubemap :: (data: *void, size: s32, format: s32, mipmapCount: s32) -> u32 #foreign raylib "rlLoadTextureCubemap";
UpdateTexture :: (id: u32, offsetX: s32, offsetY: s32, width: s32, height: s32, format: s32, data: *void) -> void #foreign raylib "rlUpdateTexture";
GetGlTextureFormats :: (format: s32, glInternalFormat: *u32, glFormat: *u32, glType: *u32) -> void #foreign raylib "rlGetGlTextureFormats";
GetPixelFormatName :: (format: u32) -> *u8 #foreign raylib "rlGetPixelFormatName";
UnloadTexture :: (id: u32) -> void #foreign raylib "rlUnloadTexture";
GenTextureMipmaps :: (id: u32, width: s32, height: s32, format: s32, mipmaps: *s32) -> void #foreign raylib "rlGenTextureMipmaps";
ReadTexturePixels :: (id: u32, width: s32, height: s32, format: s32) -> *void #foreign raylib "rlReadTexturePixels";
ReadScreenPixels :: (width: s32, height: s32) -> *u8 #foreign raylib "rlReadScreenPixels";
// Framebuffer management (fbo)
LoadFramebuffer :: () -> u32 #foreign raylib "rlLoadFramebuffer";
FramebufferAttach :: (fboId: u32, texId: u32, attachType: s32, texType: s32, mipLevel: s32) -> void #foreign raylib "rlFramebufferAttach";
FramebufferComplete :: (id: u32) -> bool #foreign raylib "rlFramebufferComplete";
UnloadFramebuffer :: (id: u32) -> void #foreign raylib "rlUnloadFramebuffer";
// Shaders management
LoadShaderCode :: (vsCode: *u8, fsCode: *u8) -> u32 #foreign raylib "rlLoadShaderCode";
CompileShader :: (shaderCode: *u8, type: s32) -> u32 #foreign raylib "rlCompileShader";
LoadShaderProgram :: (vShaderId: u32, fShaderId: u32) -> u32 #foreign raylib "rlLoadShaderProgram";
UnloadShaderProgram :: (id: u32) -> void #foreign raylib "rlUnloadShaderProgram";
GetLocationUniform :: (shaderId: u32, uniformName: *u8) -> s32 #foreign raylib "rlGetLocationUniform";
GetLocationAttrib :: (shaderId: u32, attribName: *u8) -> s32 #foreign raylib "rlGetLocationAttrib";
SetUniform :: (locIndex: s32, value: *void, uniformType: s32, count: s32) -> void #foreign raylib "rlSetUniform";
SetUniformMatrix :: (locIndex: s32, mat: Matrix) -> void #foreign raylib "rlSetUniformMatrix";
SetUniformMatrices :: (locIndex: s32, mat: *Matrix, count: s32) -> void #foreign raylib "rlSetUniformMatrices";
SetUniformSampler :: (locIndex: s32, textureId: u32) -> void #foreign raylib "rlSetUniformSampler";
SetShader :: (id: u32, locs: *s32) -> void #foreign raylib "rlSetShader";
// Compute shader management
LoadComputeShaderProgram :: (shaderId: u32) -> u32 #foreign raylib "rlLoadComputeShaderProgram";
ComputeShaderDispatch :: (groupX: u32, groupY: u32, groupZ: u32) -> void #foreign raylib "rlComputeShaderDispatch";
// Shader buffer storage object management (ssbo)
LoadShaderBuffer :: (size: u32, data: *void, usageHint: s32) -> u32 #foreign raylib "rlLoadShaderBuffer";
UnloadShaderBuffer :: (ssboId: u32) -> void #foreign raylib "rlUnloadShaderBuffer";
UpdateShaderBuffer :: (id: u32, data: *void, dataSize: u32, offset: u32) -> void #foreign raylib "rlUpdateShaderBuffer";
BindShaderBuffer :: (id: u32, index: u32) -> void #foreign raylib "rlBindShaderBuffer";
ReadShaderBuffer :: (id: u32, dest: *void, count: u32, offset: u32) -> void #foreign raylib "rlReadShaderBuffer";
CopyShaderBuffer :: (destId: u32, srcId: u32, destOffset: u32, srcOffset: u32, count: u32) -> void #foreign raylib "rlCopyShaderBuffer";
GetShaderBufferSize :: (id: u32) -> u32 #foreign raylib "rlGetShaderBufferSize";
// Buffer management
BindImageTexture :: (id: u32, index: u32, format: s32, readonly: bool) -> void #foreign raylib "rlBindImageTexture";
// Matrix state management
GetMatrixModelview :: () -> Matrix #foreign raylib "rlGetMatrixModelview";
GetMatrixProjection :: () -> Matrix #foreign raylib "rlGetMatrixProjection";
GetMatrixTransform :: () -> Matrix #foreign raylib "rlGetMatrixTransform";
GetMatrixProjectionStereo :: (eye: s32) -> Matrix #foreign raylib "rlGetMatrixProjectionStereo";
GetMatrixViewOffsetStereo :: (eye: s32) -> Matrix #foreign raylib "rlGetMatrixViewOffsetStereo";
SetMatrixProjection :: (proj: Matrix) -> void #foreign raylib "rlSetMatrixProjection";
SetMatrixModelview :: (view: Matrix) -> void #foreign raylib "rlSetMatrixModelview";
SetMatrixProjectionStereo :: (right: Matrix, left: Matrix) -> void #foreign raylib "rlSetMatrixProjectionStereo";
SetMatrixViewOffsetStereo :: (right: Matrix, left: Matrix) -> void #foreign raylib "rlSetMatrixViewOffsetStereo";
// Quick and dirty cube/quad buffers load->draw->unload
LoadDrawCube :: () -> void #foreign raylib "rlLoadDrawCube";
LoadDrawQuad :: () -> void #foreign raylib "rlLoadDrawQuad";
// NOTE: Helper types to be used instead of array return types for *ToFloat functions
float3 :: struct {
v: [3] float;
@ -2639,6 +2329,316 @@ QuaternionEquals :: (p: Quaternion, q: Quaternion) -> s32 #foreign raylib;
// Decompose a transformation matrix into its rotational, translational and scaling components
MatrixDecompose :: (mat: Matrix, translation: *Vector3, rotation: *Quaternion, scale: *Vector3) -> void #foreign raylib;
// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
VertexBuffer :: struct {
elementCount: s32; // Number of elements in the buffer (QUADS)
vertices: *float; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
texcoords: *float; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
normals: *float; // Vertex normal (XYZ - 3 components per vertex) (shader-location = 2)
colors: *u8; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
indices: *u32; // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
vaoId: u32; // OpenGL Vertex Array Object id
vboId: [5] u32; // OpenGL Vertex Buffer Objects id (5 types of vertex data)
}
// Draw call type
// NOTE: Only texture changes register a new draw, other state-change-related elements are not
// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any
// of those state-change happens (this is done in core module)
DrawCall :: struct {
mode: s32; // Drawing mode: LINES, TRIANGLES, QUADS
vertexCount: s32; // Number of vertex of the draw
vertexAlignment: s32; // Number of vertex required for index alignment (LINES, TRIANGLES)
textureId: u32; // Texture id to be used on the draw -> Use to create new draw call if changes
}
// rlRenderBatch type
RenderBatch :: struct {
bufferCount: s32; // Number of vertex buffers (multi-buffering support)
currentBuffer: s32; // Current buffer tracking in case of multi-buffering
vertexBuffer: *VertexBuffer; // Dynamic buffer(s) for vertex data
draws: *DrawCall; // Draw calls array, depends on textureId
drawCounter: s32; // Draw calls counter
currentDepth: float; // Current depth value for next draw
}
// OpenGL version
GlVersion :: enum s32 {
_11 :: 1;
_21 :: 2;
_33 :: 3;
_43 :: 4;
ES_20 :: 5;
ES_30 :: 6;
RL_OPENGL_11 :: _11;
RL_OPENGL_21 :: _21;
RL_OPENGL_33 :: _33;
RL_OPENGL_43 :: _43;
RL_OPENGL_ES_20 :: ES_20;
RL_OPENGL_ES_30 :: ES_30;
}
// Framebuffer attachment type
// NOTE: By default up to 8 color channels defined, but it can be more
FramebufferAttachType :: enum s32 {
COLOR_CHANNEL0 :: 0;
COLOR_CHANNEL1 :: 1;
COLOR_CHANNEL2 :: 2;
COLOR_CHANNEL3 :: 3;
COLOR_CHANNEL4 :: 4;
COLOR_CHANNEL5 :: 5;
COLOR_CHANNEL6 :: 6;
COLOR_CHANNEL7 :: 7;
DEPTH :: 100;
STENCIL :: 200;
RL_ATTACHMENT_COLOR_CHANNEL0 :: COLOR_CHANNEL0;
RL_ATTACHMENT_COLOR_CHANNEL1 :: COLOR_CHANNEL1;
RL_ATTACHMENT_COLOR_CHANNEL2 :: COLOR_CHANNEL2;
RL_ATTACHMENT_COLOR_CHANNEL3 :: COLOR_CHANNEL3;
RL_ATTACHMENT_COLOR_CHANNEL4 :: COLOR_CHANNEL4;
RL_ATTACHMENT_COLOR_CHANNEL5 :: COLOR_CHANNEL5;
RL_ATTACHMENT_COLOR_CHANNEL6 :: COLOR_CHANNEL6;
RL_ATTACHMENT_COLOR_CHANNEL7 :: COLOR_CHANNEL7;
RL_ATTACHMENT_DEPTH :: DEPTH;
RL_ATTACHMENT_STENCIL :: STENCIL;
}
// Framebuffer texture attachment type
FramebufferAttachTextureType :: enum s32 {
CUBEMAP_POSITIVE_X :: 0;
CUBEMAP_NEGATIVE_X :: 1;
CUBEMAP_POSITIVE_Y :: 2;
CUBEMAP_NEGATIVE_Y :: 3;
CUBEMAP_POSITIVE_Z :: 4;
CUBEMAP_NEGATIVE_Z :: 5;
TEXTURE2D :: 100;
RENDERBUFFER :: 200;
RL_ATTACHMENT_CUBEMAP_POSITIVE_X :: CUBEMAP_POSITIVE_X;
RL_ATTACHMENT_CUBEMAP_NEGATIVE_X :: CUBEMAP_NEGATIVE_X;
RL_ATTACHMENT_CUBEMAP_POSITIVE_Y :: CUBEMAP_POSITIVE_Y;
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y :: CUBEMAP_NEGATIVE_Y;
RL_ATTACHMENT_CUBEMAP_POSITIVE_Z :: CUBEMAP_POSITIVE_Z;
RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z :: CUBEMAP_NEGATIVE_Z;
RL_ATTACHMENT_TEXTURE2D :: TEXTURE2D;
RL_ATTACHMENT_RENDERBUFFER :: RENDERBUFFER;
}
// Face culling mode
CullMode :: enum s32 {
FRONT :: 0;
BACK :: 1;
RL_CULL_FACE_FRONT :: FRONT;
RL_CULL_FACE_BACK :: BACK;
}
MatrixMode :: (mode: s32) -> void #foreign raylib "rlMatrixMode";
PushMatrix :: () -> void #foreign raylib "rlPushMatrix";
PopMatrix :: () -> void #foreign raylib "rlPopMatrix";
LoadIdentity :: () -> void #foreign raylib "rlLoadIdentity";
Translatef :: (x: float, y: float, z: float) -> void #foreign raylib "rlTranslatef";
Rotatef :: (angle: float, x: float, y: float, z: float) -> void #foreign raylib "rlRotatef";
Scalef :: (x: float, y: float, z: float) -> void #foreign raylib "rlScalef";
MultMatrixf :: (matf: *float) -> void #foreign raylib "rlMultMatrixf";
Frustum :: (left: float64, right: float64, bottom: float64, top: float64, znear: float64, zfar: float64) -> void #foreign raylib "rlFrustum";
Ortho :: (left: float64, right: float64, bottom: float64, top: float64, znear: float64, zfar: float64) -> void #foreign raylib "rlOrtho";
Viewport :: (x: s32, y: s32, width: s32, height: s32) -> void #foreign raylib "rlViewport";
SetClipPlanes :: (nearPlane: float64, farPlane: float64) -> void #foreign raylib "rlSetClipPlanes";
GetCullDistanceNear :: () -> float64 #foreign raylib "rlGetCullDistanceNear";
GetCullDistanceFar :: () -> float64 #foreign raylib "rlGetCullDistanceFar";
//------------------------------------------------------------------------------------
// Functions Declaration - Vertex level operations
//------------------------------------------------------------------------------------
Begin :: (mode: s32) -> void #foreign raylib "rlBegin";
End :: () -> void #foreign raylib "rlEnd";
Vertex2i :: (x: s32, y: s32) -> void #foreign raylib "rlVertex2i";
Vertex2f :: (x: float, y: float) -> void #foreign raylib "rlVertex2f";
Vertex3f :: (x: float, y: float, z: float) -> void #foreign raylib "rlVertex3f";
TexCoord2f :: (x: float, y: float) -> void #foreign raylib "rlTexCoord2f";
Normal3f :: (x: float, y: float, z: float) -> void #foreign raylib "rlNormal3f";
Color4ub :: (r: u8, g: u8, b: u8, a: u8) -> void #foreign raylib "rlColor4ub";
Color3f :: (x: float, y: float, z: float) -> void #foreign raylib "rlColor3f";
Color4f :: (x: float, y: float, z: float, w: float) -> void #foreign raylib "rlColor4f";
// Vertex buffers state
EnableVertexArray :: (vaoId: u32) -> bool #foreign raylib "rlEnableVertexArray";
DisableVertexArray :: () -> void #foreign raylib "rlDisableVertexArray";
EnableVertexBuffer :: (id: u32) -> void #foreign raylib "rlEnableVertexBuffer";
DisableVertexBuffer :: () -> void #foreign raylib "rlDisableVertexBuffer";
EnableVertexBufferElement :: (id: u32) -> void #foreign raylib "rlEnableVertexBufferElement";
DisableVertexBufferElement :: () -> void #foreign raylib "rlDisableVertexBufferElement";
EnableVertexAttribute :: (index: u32) -> void #foreign raylib "rlEnableVertexAttribute";
DisableVertexAttribute :: (index: u32) -> void #foreign raylib "rlDisableVertexAttribute";
// Textures state
ActiveTextureSlot :: (slot: s32) -> void #foreign raylib "rlActiveTextureSlot";
EnableTexture :: (id: u32) -> void #foreign raylib "rlEnableTexture";
DisableTexture :: () -> void #foreign raylib "rlDisableTexture";
EnableTextureCubemap :: (id: u32) -> void #foreign raylib "rlEnableTextureCubemap";
DisableTextureCubemap :: () -> void #foreign raylib "rlDisableTextureCubemap";
TextureParameters :: (id: u32, param: s32, value: s32) -> void #foreign raylib "rlTextureParameters";
CubemapParameters :: (id: u32, param: s32, value: s32) -> void #foreign raylib "rlCubemapParameters";
// Shader state
EnableShader :: (id: u32) -> void #foreign raylib "rlEnableShader";
DisableShader :: () -> void #foreign raylib "rlDisableShader";
// Framebuffer state
EnableFramebuffer :: (id: u32) -> void #foreign raylib "rlEnableFramebuffer";
DisableFramebuffer :: () -> void #foreign raylib "rlDisableFramebuffer";
GetActiveFramebuffer :: () -> u32 #foreign raylib "rlGetActiveFramebuffer";
ActiveDrawBuffers :: (count: s32) -> void #foreign raylib "rlActiveDrawBuffers";
BlitFramebuffer :: (srcX: s32, srcY: s32, srcWidth: s32, srcHeight: s32, dstX: s32, dstY: s32, dstWidth: s32, dstHeight: s32, bufferMask: s32) -> void #foreign raylib "rlBlitFramebuffer";
BindFramebuffer :: (target: u32, framebuffer: u32) -> void #foreign raylib "rlBindFramebuffer";
// General render state
EnableColorBlend :: () -> void #foreign raylib "rlEnableColorBlend";
DisableColorBlend :: () -> void #foreign raylib "rlDisableColorBlend";
EnableDepthTest :: () -> void #foreign raylib "rlEnableDepthTest";
DisableDepthTest :: () -> void #foreign raylib "rlDisableDepthTest";
EnableDepthMask :: () -> void #foreign raylib "rlEnableDepthMask";
DisableDepthMask :: () -> void #foreign raylib "rlDisableDepthMask";
EnableBackfaceCulling :: () -> void #foreign raylib "rlEnableBackfaceCulling";
DisableBackfaceCulling :: () -> void #foreign raylib "rlDisableBackfaceCulling";
ColorMask :: (r: bool, g: bool, b: bool, a: bool) -> void #foreign raylib "rlColorMask";
SetCullFace :: (mode: s32) -> void #foreign raylib "rlSetCullFace";
EnableScissorTest :: () -> void #foreign raylib "rlEnableScissorTest";
DisableScissorTest :: () -> void #foreign raylib "rlDisableScissorTest";
Scissor :: (x: s32, y: s32, width: s32, height: s32) -> void #foreign raylib "rlScissor";
EnableWireMode :: () -> void #foreign raylib "rlEnableWireMode";
EnablePointMode :: () -> void #foreign raylib "rlEnablePointMode";
DisableWireMode :: () -> void #foreign raylib "rlDisableWireMode";
SetLineWidth :: (width: float) -> void #foreign raylib "rlSetLineWidth";
GetLineWidth :: () -> float #foreign raylib "rlGetLineWidth";
EnableSmoothLines :: () -> void #foreign raylib "rlEnableSmoothLines";
DisableSmoothLines :: () -> void #foreign raylib "rlDisableSmoothLines";
EnableStereoRender :: () -> void #foreign raylib "rlEnableStereoRender";
DisableStereoRender :: () -> void #foreign raylib "rlDisableStereoRender";
IsStereoRenderEnabled :: () -> bool #foreign raylib "rlIsStereoRenderEnabled";
ClearColor :: (r: u8, g: u8, b: u8, a: u8) -> void #foreign raylib "rlClearColor";
ClearScreenBuffers :: () -> void #foreign raylib "rlClearScreenBuffers";
CheckErrors :: () -> void #foreign raylib "rlCheckErrors";
SetBlendMode :: (mode: s32) -> void #foreign raylib "rlSetBlendMode";
SetBlendFactors :: (glSrcFactor: s32, glDstFactor: s32, glEquation: s32) -> void #foreign raylib "rlSetBlendFactors";
SetBlendFactorsSeparate :: (glSrcRGB: s32, glDstRGB: s32, glSrcAlpha: s32, glDstAlpha: s32, glEqRGB: s32, glEqAlpha: s32) -> void #foreign raylib "rlSetBlendFactorsSeparate";
//------------------------------------------------------------------------------------
// Functions Declaration - rlgl functionality
//------------------------------------------------------------------------------------
// rlgl initialization functions
glInit :: (width: s32, height: s32) -> void #foreign raylib "rlglInit";
glClose :: () -> void #foreign raylib "rlglClose";
LoadExtensions :: (loader: *void) -> void #foreign raylib "rlLoadExtensions";
GetVersion :: () -> s32 #foreign raylib "rlGetVersion";
SetFramebufferWidth :: (width: s32) -> void #foreign raylib "rlSetFramebufferWidth";
GetFramebufferWidth :: () -> s32 #foreign raylib "rlGetFramebufferWidth";
SetFramebufferHeight :: (height: s32) -> void #foreign raylib "rlSetFramebufferHeight";
GetFramebufferHeight :: () -> s32 #foreign raylib "rlGetFramebufferHeight";
GetTextureIdDefault :: () -> u32 #foreign raylib "rlGetTextureIdDefault";
GetShaderIdDefault :: () -> u32 #foreign raylib "rlGetShaderIdDefault";
GetShaderLocsDefault :: () -> *s32 #foreign raylib "rlGetShaderLocsDefault";
// Render batch management
// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
// but this render batch API is exposed in case of custom batches are required
LoadRenderBatch :: (numBuffers: s32, bufferElements: s32) -> RenderBatch #foreign raylib "rlLoadRenderBatch";
UnloadRenderBatch :: (batch: RenderBatch) -> void #foreign raylib "rlUnloadRenderBatch";
DrawRenderBatch :: (batch: *RenderBatch) -> void #foreign raylib "rlDrawRenderBatch";
SetRenderBatchActive :: (batch: *RenderBatch) -> void #foreign raylib "rlSetRenderBatchActive";
DrawRenderBatchActive :: () -> void #foreign raylib "rlDrawRenderBatchActive";
CheckRenderBatchLimit :: (vCount: s32) -> bool #foreign raylib "rlCheckRenderBatchLimit";
SetTexture :: (id: u32) -> void #foreign raylib "rlSetTexture";
// Vertex buffers management
LoadVertexArray :: () -> u32 #foreign raylib "rlLoadVertexArray";
LoadVertexBuffer :: (buffer: *void, size: s32, dynamic: bool) -> u32 #foreign raylib "rlLoadVertexBuffer";
LoadVertexBufferElement :: (buffer: *void, size: s32, dynamic: bool) -> u32 #foreign raylib "rlLoadVertexBufferElement";
UpdateVertexBuffer :: (bufferId: u32, data: *void, dataSize: s32, offset: s32) -> void #foreign raylib "rlUpdateVertexBuffer";
UpdateVertexBufferElements :: (id: u32, data: *void, dataSize: s32, offset: s32) -> void #foreign raylib "rlUpdateVertexBufferElements";
UnloadVertexArray :: (vaoId: u32) -> void #foreign raylib "rlUnloadVertexArray";
UnloadVertexBuffer :: (vboId: u32) -> void #foreign raylib "rlUnloadVertexBuffer";
SetVertexAttribute :: (index: u32, compSize: s32, type: s32, normalized: bool, stride: s32, offset: s32) -> void #foreign raylib "rlSetVertexAttribute";
SetVertexAttributeDivisor :: (index: u32, divisor: s32) -> void #foreign raylib "rlSetVertexAttributeDivisor";
SetVertexAttributeDefault :: (locIndex: s32, value: *void, attribType: s32, count: s32) -> void #foreign raylib "rlSetVertexAttributeDefault";
DrawVertexArray :: (offset: s32, count: s32) -> void #foreign raylib "rlDrawVertexArray";
DrawVertexArrayElements :: (offset: s32, count: s32, buffer: *void) -> void #foreign raylib "rlDrawVertexArrayElements";
DrawVertexArrayInstanced :: (offset: s32, count: s32, instances: s32) -> void #foreign raylib "rlDrawVertexArrayInstanced";
DrawVertexArrayElementsInstanced :: (offset: s32, count: s32, buffer: *void, instances: s32) -> void #foreign raylib "rlDrawVertexArrayElementsInstanced";
// Textures management
LoadTexture :: (data: *void, width: s32, height: s32, format: s32, mipmapCount: s32) -> u32 #foreign raylib "rlLoadTexture";
LoadTextureDepth :: (width: s32, height: s32, useRenderBuffer: bool) -> u32 #foreign raylib "rlLoadTextureDepth";
LoadTextureCubemap :: (data: *void, size: s32, format: s32, mipmapCount: s32) -> u32 #foreign raylib "rlLoadTextureCubemap";
UpdateTexture :: (id: u32, offsetX: s32, offsetY: s32, width: s32, height: s32, format: s32, data: *void) -> void #foreign raylib "rlUpdateTexture";
GetGlTextureFormats :: (format: s32, glInternalFormat: *u32, glFormat: *u32, glType: *u32) -> void #foreign raylib "rlGetGlTextureFormats";
GetPixelFormatName :: (format: u32) -> *u8 #foreign raylib "rlGetPixelFormatName";
UnloadTexture :: (id: u32) -> void #foreign raylib "rlUnloadTexture";
GenTextureMipmaps :: (id: u32, width: s32, height: s32, format: s32, mipmaps: *s32) -> void #foreign raylib "rlGenTextureMipmaps";
ReadTexturePixels :: (id: u32, width: s32, height: s32, format: s32) -> *void #foreign raylib "rlReadTexturePixels";
ReadScreenPixels :: (width: s32, height: s32) -> *u8 #foreign raylib "rlReadScreenPixels";
// Framebuffer management (fbo)
LoadFramebuffer :: () -> u32 #foreign raylib "rlLoadFramebuffer";
FramebufferAttach :: (fboId: u32, texId: u32, attachType: s32, texType: s32, mipLevel: s32) -> void #foreign raylib "rlFramebufferAttach";
FramebufferComplete :: (id: u32) -> bool #foreign raylib "rlFramebufferComplete";
UnloadFramebuffer :: (id: u32) -> void #foreign raylib "rlUnloadFramebuffer";
// Shaders management
LoadShaderCode :: (vsCode: *u8, fsCode: *u8) -> u32 #foreign raylib "rlLoadShaderCode";
CompileShader :: (shaderCode: *u8, type: s32) -> u32 #foreign raylib "rlCompileShader";
LoadShaderProgram :: (vShaderId: u32, fShaderId: u32) -> u32 #foreign raylib "rlLoadShaderProgram";
UnloadShaderProgram :: (id: u32) -> void #foreign raylib "rlUnloadShaderProgram";
GetLocationUniform :: (shaderId: u32, uniformName: *u8) -> s32 #foreign raylib "rlGetLocationUniform";
GetLocationAttrib :: (shaderId: u32, attribName: *u8) -> s32 #foreign raylib "rlGetLocationAttrib";
SetUniform :: (locIndex: s32, value: *void, uniformType: s32, count: s32) -> void #foreign raylib "rlSetUniform";
SetUniformMatrix :: (locIndex: s32, mat: Matrix) -> void #foreign raylib "rlSetUniformMatrix";
SetUniformMatrices :: (locIndex: s32, mat: *Matrix, count: s32) -> void #foreign raylib "rlSetUniformMatrices";
SetUniformSampler :: (locIndex: s32, textureId: u32) -> void #foreign raylib "rlSetUniformSampler";
SetShader :: (id: u32, locs: *s32) -> void #foreign raylib "rlSetShader";
// Compute shader management
LoadComputeShaderProgram :: (shaderId: u32) -> u32 #foreign raylib "rlLoadComputeShaderProgram";
ComputeShaderDispatch :: (groupX: u32, groupY: u32, groupZ: u32) -> void #foreign raylib "rlComputeShaderDispatch";
// Shader buffer storage object management (ssbo)
LoadShaderBuffer :: (size: u32, data: *void, usageHint: s32) -> u32 #foreign raylib "rlLoadShaderBuffer";
UnloadShaderBuffer :: (ssboId: u32) -> void #foreign raylib "rlUnloadShaderBuffer";
UpdateShaderBuffer :: (id: u32, data: *void, dataSize: u32, offset: u32) -> void #foreign raylib "rlUpdateShaderBuffer";
BindShaderBuffer :: (id: u32, index: u32) -> void #foreign raylib "rlBindShaderBuffer";
ReadShaderBuffer :: (id: u32, dest: *void, count: u32, offset: u32) -> void #foreign raylib "rlReadShaderBuffer";
CopyShaderBuffer :: (destId: u32, srcId: u32, destOffset: u32, srcOffset: u32, count: u32) -> void #foreign raylib "rlCopyShaderBuffer";
GetShaderBufferSize :: (id: u32) -> u32 #foreign raylib "rlGetShaderBufferSize";
// Buffer management
BindImageTexture :: (id: u32, index: u32, format: s32, readonly: bool) -> void #foreign raylib "rlBindImageTexture";
// Matrix state management
GetMatrixModelview :: () -> Matrix #foreign raylib "rlGetMatrixModelview";
GetMatrixProjection :: () -> Matrix #foreign raylib "rlGetMatrixProjection";
GetMatrixTransform :: () -> Matrix #foreign raylib "rlGetMatrixTransform";
GetMatrixProjectionStereo :: (eye: s32) -> Matrix #foreign raylib "rlGetMatrixProjectionStereo";
GetMatrixViewOffsetStereo :: (eye: s32) -> Matrix #foreign raylib "rlGetMatrixViewOffsetStereo";
SetMatrixProjection :: (proj: Matrix) -> void #foreign raylib "rlSetMatrixProjection";
SetMatrixModelview :: (view: Matrix) -> void #foreign raylib "rlSetMatrixModelview";
SetMatrixProjectionStereo :: (right: Matrix, left: Matrix) -> void #foreign raylib "rlSetMatrixProjectionStereo";
SetMatrixViewOffsetStereo :: (right: Matrix, left: Matrix) -> void #foreign raylib "rlSetMatrixViewOffsetStereo";
// Quick and dirty cube/quad buffers load->draw->unload
LoadDrawCube :: () -> void #foreign raylib "rlLoadDrawCube";
LoadDrawQuad :: () -> void #foreign raylib "rlLoadDrawQuad";
#scope_file
#import "Basic"; // For assert, push_context
@ -3064,6 +3064,20 @@ MatrixDecompose :: (mat: Matrix, translation: *Vector3, rotation: *Quaternion, s
assert(size_of(AutomationEventList) == 16, "AutomationEventList has size % instead of 16", size_of(AutomationEventList));
}
{
instance: float3;
assert(((cast(*void)(*instance.v)) - cast(*void)(*instance)) == 0, "float3.v has unexpected offset % instead of 0", ((cast(*void)(*instance.v)) - cast(*void)(*instance)));
assert(size_of(type_of(float3.v)) == 12, "float3.v has unexpected size % instead of 12", size_of(type_of(float3.v)));
assert(size_of(float3) == 12, "float3 has size % instead of 12", size_of(float3));
}
{
instance: float16;
assert(((cast(*void)(*instance.v)) - cast(*void)(*instance)) == 0, "float16.v has unexpected offset % instead of 0", ((cast(*void)(*instance.v)) - cast(*void)(*instance)));
assert(size_of(type_of(float16.v)) == 64, "float16.v has unexpected size % instead of 64", size_of(type_of(float16.v)));
assert(size_of(float16) == 64, "float16 has size % instead of 64", size_of(float16));
}
{
instance: VertexBuffer;
assert(((cast(*void)(*instance.elementCount)) - cast(*void)(*instance)) == 0, "VertexBuffer.elementCount has unexpected offset % instead of 0", ((cast(*void)(*instance.elementCount)) - cast(*void)(*instance)));
@ -3114,19 +3128,5 @@ MatrixDecompose :: (mat: Matrix, translation: *Vector3, rotation: *Quaternion, s
assert(size_of(type_of(RenderBatch.currentDepth)) == 4, "RenderBatch.currentDepth has unexpected size % instead of 4", size_of(type_of(RenderBatch.currentDepth)));
assert(size_of(RenderBatch) == 32, "RenderBatch has size % instead of 32", size_of(RenderBatch));
}
{
instance: float3;
assert(((cast(*void)(*instance.v)) - cast(*void)(*instance)) == 0, "float3.v has unexpected offset % instead of 0", ((cast(*void)(*instance.v)) - cast(*void)(*instance)));
assert(size_of(type_of(float3.v)) == 12, "float3.v has unexpected size % instead of 12", size_of(type_of(float3.v)));
assert(size_of(float3) == 12, "float3 has size % instead of 12", size_of(float3));
}
{
instance: float16;
assert(((cast(*void)(*instance.v)) - cast(*void)(*instance)) == 0, "float16.v has unexpected offset % instead of 0", ((cast(*void)(*instance.v)) - cast(*void)(*instance)));
assert(size_of(type_of(float16.v)) == 64, "float16.v has unexpected size % instead of 64", size_of(type_of(float16.v)));
assert(size_of(float16) == 64, "float16 has size % instead of 64", size_of(float16));
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

1382
clay.h

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

View File

@ -1,789 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="preload" href="/clay/fonts/Calistoga-Regular.ttf" as="font" type="font/ttf" crossorigin>
<link rel="preload" href="/clay/fonts/Quicksand-Semibold.ttf" as="font" type="font/ttf" crossorigin>
<title>Clay - UI Layout Library</title>
<style>
html, body {
width: 100%;
height: 100%;
overflow: hidden;
padding: 0;
margin: 0;
pointer-events: none;
background: rgb(244, 235, 230);
}
/* Import the font using @font-face */
@font-face {
font-family: 'Calistoga';
font-style: normal;
font-weight: 400;
src: url('/clay/fonts/Calistoga-Regular.ttf') format('truetype');
}
@font-face {
font-family: 'Quicksand';
font-style: normal;
font-weight: 400;
src: url('/clay/fonts/Quicksand-Semibold.ttf') format('truetype');
}
body > canvas {
width: 100%;
height: 100%;
touch-action: none;
}
div, a, img {
position: absolute;
box-sizing: border-box;
-webkit-backface-visibility: hidden;
pointer-events: none;
}
a {
cursor: pointer;
pointer-events: all;
}
.text {
pointer-events: all;
white-space: pre;
}
/* TODO special exception for text selection in debug tools */
[id='2067877626'] > * {
pointer-events: none !important;
}
</style>
</head>
<script type="module">
const CLAY_RENDER_COMMAND_TYPE_NONE = 0;
const CLAY_RENDER_COMMAND_TYPE_RECTANGLE = 1;
const CLAY_RENDER_COMMAND_TYPE_BORDER = 2;
const CLAY_RENDER_COMMAND_TYPE_TEXT = 3;
const CLAY_RENDER_COMMAND_TYPE_IMAGE = 4;
const CLAY_RENDER_COMMAND_TYPE_SCISSOR_START = 5;
const CLAY_RENDER_COMMAND_TYPE_SCISSOR_END = 6;
const CLAY_RENDER_COMMAND_TYPE_CUSTOM = 7;
const GLOBAL_FONT_SCALING_FACTOR = 0.8;
let renderCommandSize = 0;
let scratchSpaceAddress = 8;
let heapSpaceAddress = 0;
let memoryDataView;
let textDecoder = new TextDecoder("utf-8");
let previousFrameTime;
let fontsById = [
'Quicksand',
'Calistoga',
'Quicksand',
'Quicksand',
'Quicksand',
];
let elementCache = {};
let imageCache = {};
let colorDefinition = { type: 'struct', members: [
{name: 'r', type: 'float' },
{name: 'g', type: 'float' },
{name: 'b', type: 'float' },
{name: 'a', type: 'float' },
]};
let stringDefinition = { type: 'struct', members: [
{name: 'length', type: 'uint32_t' },
{name: 'chars', type: 'uint32_t' },
]};
let borderDefinition = { type: 'struct', members: [
{name: 'width', type: 'uint32_t'},
{name: 'color', ...colorDefinition},
]};
let cornerRadiusDefinition = { type: 'struct', members: [
{name: 'topLeft', type: 'float'},
{name: 'topRight', type: 'float'},
{name: 'bottomLeft', type: 'float'},
{name: 'bottomRight', type: 'float'},
]};
let rectangleConfigDefinition = { name: 'rectangle', type: 'struct', members: [
{ name: 'color', ...colorDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition },
{ name: 'link', ...stringDefinition },
{ name: 'cursorPointer', type: 'uint8_t' },
]};
let borderConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'left', ...borderDefinition },
{ name: 'right', ...borderDefinition },
{ name: 'top', ...borderDefinition },
{ name: 'bottom', ...borderDefinition },
{ name: 'betweenChildren', ...borderDefinition },
{ name: 'cornerRadius', ...cornerRadiusDefinition }
]};
let textConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'textColor', ...colorDefinition },
{ name: 'fontId', type: 'uint16_t' },
{ name: 'fontSize', type: 'uint16_t' },
{ name: 'letterSpacing', type: 'uint16_t' },
{ name: 'lineSpacing', type: 'uint16_t' },
{ name: 'wrapMode', type: 'uint32_t' },
{ name: 'disablePointerEvents', type: 'uint8_t' }
]};
let scrollConfigDefinition = { name: 'text', type: 'struct', members: [
{ name: 'horizontal', type: 'bool' },
{ name: 'vertical', type: 'bool' },
]};
let imageConfigDefinition = { name: 'image', type: 'struct', members: [
{ name: 'imageData', type: 'uint32_t' },
{ name: 'sourceDimensions', type: 'struct', members: [
{ name: 'width', type: 'float' },
{ name: 'height', type: 'float' },
]},
{ name: 'sourceURL', ...stringDefinition }
]};
let customConfigDefinition = { name: 'custom', type: 'struct', members: [
{ name: 'customData', type: 'uint32_t' },
]}
let renderCommandDefinition = {
name: 'CLay_RenderCommand',
type: 'struct',
members: [
{ name: 'boundingBox', type: 'struct', members: [
{ name: 'x', type: 'float' },
{ name: 'y', type: 'float' },
{ name: 'width', type: 'float' },
{ name: 'height', type: 'float' },
]},
{ name: 'config', type: 'uint32_t'},
{ name: 'text', ...stringDefinition },
{ name: 'id', type: 'uint32_t' },
{ name: 'commandType', type: 'uint32_t', },
]
};
function getStructTotalSize(definition) {
switch(definition.type) {
case 'union':
case 'struct': {
let totalSize = 0;
for (const member of definition.members) {
let result = getStructTotalSize(member);
if (definition.type === 'struct') {
totalSize += result;
} else {
totalSize = Math.max(totalSize, result);
}
}
return totalSize;
}
case 'float': return 4;
case 'uint32_t': return 4;
case 'int32_t': return 4;
case 'uint16_t': return 2;
case 'uint8_t': return 1;
case 'bool': return 1;
default: {
throw "Unimplemented C data type " + definition.type
}
}
}
function readStructAtAddress(address, definition) {
switch(definition.type) {
case 'union':
case 'struct': {
let struct = { __size: 0 };
for (const member of definition.members) {
let result = readStructAtAddress(address, member);
struct[member.name] = result;
if (definition.type === 'struct') {
struct.__size += result.__size;
address += result.__size;
} else {
struct.__size = Math.max(struct.__size, result.__size);
}
}
return struct;
}
case 'float': return { value: memoryDataView.getFloat32(address, true), __size: 4 };
case 'uint32_t': return { value: memoryDataView.getUint32(address, true), __size: 4 };
case 'int32_t': return { value: memoryDataView.getUint32(address, true), __size: 4 };
case 'uint16_t': return { value: memoryDataView.getUint16(address, true), __size: 2 };
case 'uint8_t': return { value: memoryDataView.getUint8(address, true), __size: 1 };
case 'bool': return { value: memoryDataView.getUint8(address, true), __size: 1 };
default: {
throw "Unimplemented C data type " + definition.type
}
}
}
function getTextDimensions(text, font) {
// re-use canvas object for better performance
window.canvasContext.font = font;
let metrics = window.canvasContext.measureText(text);
return { width: metrics.width, height: metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent };
}
function createMainArena(arenaStructAddress, arenaMemoryAddress) {
let memorySize = instance.exports.Clay_MinMemorySize();
// Last arg is address to store return value
instance.exports.Clay_CreateArenaWithCapacityAndMemory(arenaStructAddress, memorySize, arenaMemoryAddress);
}
async function init() {
await Promise.all(fontsById.map(f => document.fonts.load(`12px "${f}"`)));
window.htmlRoot = document.body.appendChild(document.createElement('div'));
window.canvasRoot = document.body.appendChild(document.createElement('canvas'));
window.canvasContext = window.canvasRoot.getContext("2d");
window.mousePositionXThisFrame = 0;
window.mousePositionYThisFrame = 0;
window.mouseWheelXThisFrame = 0;
window.mouseWheelYThisFrame = 0;
window.touchDown = false;
window.arrowKeyDownPressedThisFrame = false;
window.arrowKeyUpPressedThisFrame = false;
let zeroTimeout = null;
document.addEventListener("wheel", (event) => {
window.mouseWheelXThisFrame = event.deltaX * -0.1;
window.mouseWheelYThisFrame = event.deltaY * -0.1;
clearTimeout(zeroTimeout);
zeroTimeout = setTimeout(() => {
window.mouseWheelXThisFrame = 0;
window.mouseWheelYThisFrame = 0;
}, 10);
});
function handleTouch (event) {
if (event.touches.length === 1) {
window.touchDown = true;
let target = event.target;
let scrollTop = 0;
let scrollLeft = 0;
let activeRendererIndex = memoryDataView.getUint32(instance.exports.ACTIVE_RENDERER_INDEX.value, true);
while (activeRendererIndex !== 1 && target) {
scrollLeft += target.scrollLeft;
scrollTop += target.scrollTop;
target = target.parentElement;
}
window.mousePositionXThisFrame = event.changedTouches[0].pageX + scrollLeft;
window.mousePositionYThisFrame = event.changedTouches[0].pageY + scrollTop;
}
}
document.addEventListener("touchstart", handleTouch);
document.addEventListener("touchmove", handleTouch);
document.addEventListener("touchend", () => {
window.touchDown = false;
window.mousePositionXThisFrame = 0;
window.mousePositionYThisFrame = 0;
})
document.addEventListener("mousemove", (event) => {
let target = event.target;
let scrollTop = 0;
let scrollLeft = 0;
let activeRendererIndex = memoryDataView.getUint32(instance.exports.ACTIVE_RENDERER_INDEX.value, true);
while (activeRendererIndex !== 1 && target) {
scrollLeft += target.scrollLeft;
scrollTop += target.scrollTop;
target = target.parentElement;
}
window.mousePositionXThisFrame = event.x + scrollLeft;
window.mousePositionYThisFrame = event.y + scrollTop;
});
document.addEventListener("mousedown", (event) => {
window.mouseDown = true;
window.mouseDownThisFrame = true;
});
document.addEventListener("mouseup", (event) => {
window.mouseDown = false;
});
document.addEventListener("keydown", (event) => {
if (event.key === "ArrowDown") {
window.arrowKeyDownPressedThisFrame = true;
}
if (event.key === "ArrowUp") {
window.arrowKeyUpPressedThisFrame = true;
}
if (event.key === "d") {
window.dKeyPressedThisFrame = true;
}
});
const importObject = {
clay: {
measureTextFunction: (addressOfDimensions, textToMeasure, addressOfConfig) => {
let stringLength = memoryDataView.getUint32(textToMeasure, true);
let pointerToString = memoryDataView.getUint32(textToMeasure + 4, true);
let textConfig = readStructAtAddress(addressOfConfig, textConfigDefinition);
let textDecoder = new TextDecoder("utf-8");
let text = textDecoder.decode(memoryDataView.buffer.slice(pointerToString, pointerToString + stringLength));
let sourceDimensions = getTextDimensions(text, `${Math.round(textConfig.fontSize.value * GLOBAL_FONT_SCALING_FACTOR)}px ${fontsById[textConfig.fontId.value]}`);
memoryDataView.setFloat32(addressOfDimensions, sourceDimensions.width, true);
memoryDataView.setFloat32(addressOfDimensions + 4, sourceDimensions.height, true);
},
queryScrollOffsetFunction: (addressOfOffset, elementId) => {
let container = document.getElementById(elementId.toString());
if (container) {
memoryDataView.setFloat32(addressOfOffset, -container.scrollLeft, true);
memoryDataView.setFloat32(addressOfOffset + 4, -container.scrollTop, true);
}
}
},
};
const { instance } = await WebAssembly.instantiateStreaming(
fetch("/clay/index.wasm"), importObject
);
memoryDataView = new DataView(new Uint8Array(instance.exports.memory.buffer).buffer);
scratchSpaceAddress = instance.exports.__heap_base.value;
heapSpaceAddress = instance.exports.__heap_base.value + 1024;
let arenaAddress = scratchSpaceAddress + 8;
window.instance = instance;
createMainArena(arenaAddress, heapSpaceAddress);
memoryDataView.setFloat32(instance.exports.__heap_base.value, window.innerWidth, true);
memoryDataView.setFloat32(instance.exports.__heap_base.value + 4, window.innerHeight, true);
instance.exports.Clay_Initialize(arenaAddress, instance.exports.__heap_base.value);
renderCommandSize = getStructTotalSize(renderCommandDefinition);
renderLoop();
}
function MemoryIsDifferent(one, two, length) {
for (let i = 0; i < length; i++) {
if (one[i] !== two[i]) {
return true;
}
}
return false;
}
function renderLoopHTML() {
let capacity = memoryDataView.getInt32(scratchSpaceAddress, true);
let length = memoryDataView.getInt32(scratchSpaceAddress + 4, true);
let arrayOffset = memoryDataView.getUint32(scratchSpaceAddress + 8, true);
let scissorStack = [{ nextAllocation: { x: 0, y: 0 }, element: htmlRoot, nextElementIndex: 0 }];
let previousId = 0;
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
let entireRenderCommandMemory = new Uint32Array(memoryDataView.buffer.slice(arrayOffset, arrayOffset + renderCommandSize));
let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition);
let parentElement = scissorStack[scissorStack.length - 1];
let element = null;
let isMultiConfigElement = previousId === renderCommand.id.value;
if (!elementCache[renderCommand.id.value]) {
let elementType = 'div';
switch (renderCommand.commandType.value) {
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
if (readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition).link.length.value > 0) {
elementType = 'a';
}
break;
}
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
elementType = 'img'; break;
}
default: break;
}
element = document.createElement(elementType);
element.id = renderCommand.id.value;
if (renderCommand.commandType.value === CLAY_RENDER_COMMAND_TYPE_SCISSOR_START) {
element.style.overflow = 'hidden';
}
elementCache[renderCommand.id.value] = {
exists: true,
element: element,
previousMemoryCommand: new Uint8Array(0),
previousMemoryConfig: new Uint8Array(0),
previousMemoryText: new Uint8Array(0)
};
}
let elementData = elementCache[renderCommand.id.value];
element = elementData.element;
if (!isMultiConfigElement && Array.prototype.indexOf.call(parentElement.element.children, element) !== parentElement.nextElementIndex) {
if (parentElement.nextElementIndex === 0) {
parentElement.element.insertAdjacentElement('afterbegin', element);
} else {
parentElement.element.childNodes[Math.min(parentElement.nextElementIndex - 1, parentElement.element.childNodes.length - 1)].insertAdjacentElement('afterend', element);
}
}
elementData.exists = true;
// Don't get me started. Cheaper to compare the render command memory than to update HTML elements
let dirty = MemoryIsDifferent(elementData.previousMemoryCommand, entireRenderCommandMemory, renderCommandSize) && !isMultiConfigElement;
if (!isMultiConfigElement) {
parentElement.nextElementIndex++;
}
previousId = renderCommand.id.value;
elementData.previousMemoryCommand = entireRenderCommandMemory;
let offsetX = scissorStack.length > 0 ? scissorStack[scissorStack.length - 1].nextAllocation.x : 0;
let offsetY = scissorStack.length > 0 ? scissorStack[scissorStack.length - 1].nextAllocation.y : 0;
if (dirty) {
element.style.transform = `translate(${Math.round(renderCommand.boundingBox.x.value - offsetX)}px, ${Math.round(renderCommand.boundingBox.y.value - offsetY)}px)`
element.style.width = Math.round(renderCommand.boundingBox.width.value) + 'px';
element.style.height = Math.round(renderCommand.boundingBox.height.value) + 'px';
}
// note: commandType is packed to uint8_t and has 3 garbage bytes of padding
switch(renderCommand.commandType.value & 0xff) {
case (CLAY_RENDER_COMMAND_TYPE_NONE): {
break;
}
case (CLAY_RENDER_COMMAND_TYPE_RECTANGLE): {
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0;
memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents;
}
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
break;
}
if (linkContents.length > 0) {
element.href = linkContents;
}
if (linkContents.length > 0 || config.cursorPointer.value) {
element.style.pointerEvents = 'all';
element.style.cursor = 'pointer';
}
elementData.previousMemoryConfig = configMemory;
let color = config.color;
element.style.backgroundColor = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
if (config.cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = config.cornerRadius.topLeft.value + 'px';
}
if (config.cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = config.cornerRadius.topRight.value + 'px';
}
if (config.cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = config.cornerRadius.bottomLeft.value + 'px';
}
if (config.cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = config.cornerRadius.bottomRight.value + 'px';
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_BORDER): {
let config = readStructAtAddress(renderCommand.config.value, borderConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
if (!dirty && !MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
break;
}
elementData.previousMemoryConfig = configMemory;
if (config.left.width.value > 0) {
let color = config.left.color;
element.style.borderLeft = `${config.left.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`
}
if (config.right.width.value > 0) {
let color = config.right.color;
element.style.borderRight = `${config.right.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`
}
if (config.top.width.value > 0) {
let color = config.top.color;
element.style.borderTop = `${config.top.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`
}
if (config.bottom.width.value > 0) {
let color = config.bottom.color;
element.style.borderBottom = `${config.bottom.width.value}px solid rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`
}
if (config.cornerRadius.topLeft.value > 0) {
element.style.borderTopLeftRadius = config.cornerRadius.topLeft.value + 'px';
}
if (config.cornerRadius.topRight.value > 0) {
element.style.borderTopRightRadius = config.cornerRadius.topRight.value + 'px';
}
if (config.cornerRadius.bottomLeft.value > 0) {
element.style.borderBottomLeftRadius = config.cornerRadius.bottomLeft.value + 'px';
}
if (config.cornerRadius.bottomRight.value > 0) {
element.style.borderBottomRightRadius = config.cornerRadius.bottomRight.value + 'px';
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
let config = readStructAtAddress(renderCommand.config.value, textConfigDefinition);
let configMemory = new Uint8Array(memoryDataView.buffer.slice(renderCommand.config.value, renderCommand.config.value + config.__size));
let textContents = renderCommand.text;
let stringContents = new Uint8Array(memoryDataView.buffer.slice(textContents.chars.value, textContents.chars.value + textContents.length.value));
if (MemoryIsDifferent(configMemory, elementData.previousMemoryConfig, config.__size)) {
element.className = 'text';
let textColor = config.textColor;
let fontSize = Math.round(config.fontSize.value * GLOBAL_FONT_SCALING_FACTOR);
element.style.color = `rgba(${textColor.r.value}, ${textColor.g.value}, ${textColor.b.value}, ${textColor.a.value})`;
element.style.fontFamily = fontsById[config.fontId.value];
element.style.fontSize = fontSize + 'px';
element.style.pointerEvents = config.disablePointerEvents.value ? 'none' : 'all';
elementData.previousMemoryConfig = configMemory;
}
if (stringContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(stringContents, elementData.previousMemoryText, stringContents.length)) {
element.innerHTML = textDecoder.decode(stringContents);
}
elementData.previousMemoryText = stringContents;
break;
}
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
scissorStack.push({ nextAllocation: { x: renderCommand.boundingBox.x.value, y: renderCommand.boundingBox.y.value }, element, nextElementIndex: 0 });
let config = readStructAtAddress(renderCommand.config.value, scrollConfigDefinition);
if (config.horizontal.value) {
element.style.overflowX = 'scroll';
element.style.pointerEvents = 'auto';
}
if (config.vertical.value) {
element.style.overflowY = 'scroll';
element.style.pointerEvents = 'auto';
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {
scissorStack.splice(scissorStack.length - 1, 1);
break;
}
case (CLAY_RENDER_COMMAND_TYPE_IMAGE): {
let config = readStructAtAddress(renderCommand.config.value, imageConfigDefinition);
let srcContents = new Uint8Array(memoryDataView.buffer.slice(config.sourceURL.chars.value, config.sourceURL.chars.value + config.sourceURL.length.value));
if (srcContents.length !== elementData.previousMemoryText.length || MemoryIsDifferent(srcContents, elementData.previousMemoryText, srcContents.length)) {
element.src = textDecoder.decode(srcContents);
}
elementData.previousMemoryText = srcContents;
break;
}
case (CLAY_RENDER_COMMAND_TYPE_CUSTOM): break;
}
}
for (const key of Object.keys(elementCache)) {
if (elementCache[key].exists) {
elementCache[key].exists = false;
} else {
elementCache[key].element.remove();
delete elementCache[key];
}
}
}
function renderLoopCanvas() {
// Note: Rendering to canvas needs to be scaled up by window.devicePixelRatio in both width and height.
// e.g. if we're working on a device where devicePixelRatio is 2, we need to render
// everything at width^2 x height^2 resolution, then scale back down with css to get the correct pixel density.
let capacity = memoryDataView.getUint32(scratchSpaceAddress, true);
let length = memoryDataView.getUint32(scratchSpaceAddress + 4, true);
let arrayOffset = memoryDataView.getUint32(scratchSpaceAddress + 8, true);
window.canvasRoot.width = window.innerWidth * window.devicePixelRatio;
window.canvasRoot.height = window.innerHeight * window.devicePixelRatio;
window.canvasRoot.style.width = window.innerWidth + 'px';
window.canvasRoot.style.height = window.innerHeight + 'px';
let ctx = window.canvasContext;
let scale = window.devicePixelRatio;
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition);
let boundingBox = renderCommand.boundingBox;
// note: commandType is packed to uint8_t and has 3 garbage bytes of padding
switch(renderCommand.commandType.value & 0xff) {
case (CLAY_RENDER_COMMAND_TYPE_NONE): {
break;
}
case (CLAY_RENDER_COMMAND_TYPE_RECTANGLE): {
let config = readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition);
let color = config.color;
ctx.beginPath();
window.canvasContext.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
window.canvasContext.roundRect(
boundingBox.x.value * scale, // x
boundingBox.y.value * scale, // y
boundingBox.width.value * scale, // width
boundingBox.height.value * scale,
[config.cornerRadius.topLeft.value * scale, config.cornerRadius.topRight.value * scale, config.cornerRadius.bottomRight.value * scale, config.cornerRadius.bottomLeft.value * scale]) // height;
ctx.fill();
ctx.closePath();
// Handle link clicks
let linkContents = config.link.length.value > 0 ? textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.link.chars.value, config.link.chars.value + config.link.length.value))) : 0;
memoryDataView.setUint32(0, renderCommand.id.value, true);
if (linkContents.length > 0 && (window.mouseDownThisFrame || window.touchDown) && instance.exports.Clay_PointerOver(0)) {
window.location.href = linkContents;
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_BORDER): {
let config = readStructAtAddress(renderCommand.config.value, borderConfigDefinition);
ctx.beginPath();
ctx.moveTo(boundingBox.x.value * scale, boundingBox.y.value * scale);
// Top Left Corner
if (config.cornerRadius.topLeft.value > 0) {
let lineWidth = config.top.width.value;
let halfLineWidth = lineWidth / 2;
ctx.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale);
let color = config.top.color;
ctx.lineWidth = lineWidth * scale;
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.arcTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, (boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, config.cornerRadius.topLeft.value * scale);
ctx.stroke();
}
// Top border
if (config.top.width.value > 0) {
let lineWidth = config.top.width.value;
let halfLineWidth = lineWidth / 2;
let color = config.top.color;
ctx.lineWidth = lineWidth * scale;
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.moveTo((boundingBox.x.value + config.cornerRadius.topLeft.value + halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
ctx.lineTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
ctx.stroke();
}
// Top Right Corner
if (config.cornerRadius.topRight.value > 0) {
let lineWidth = config.top.width.value;
let halfLineWidth = lineWidth / 2;
ctx.moveTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.topRight.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale);
let color = config.top.color;
ctx.lineWidth = lineWidth * scale;
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.arcTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + halfLineWidth) * scale, (boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topRight.value + halfLineWidth) * scale, config.cornerRadius.topRight.value * scale);
ctx.stroke();
}
// Right border
if (config.right.width.value > 0) {
let color = config.right.color;
let lineWidth = config.right.width.value;
let halfLineWidth = lineWidth / 2;
ctx.lineWidth = lineWidth * scale;
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.moveTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.topRight.value + halfLineWidth) * scale);
ctx.lineTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.topRight.value - halfLineWidth) * scale);
ctx.stroke();
}
// Bottom Right Corner
if (config.cornerRadius.bottomRight.value > 0) {
let color = config.top.color;
let lineWidth = config.top.width.value;
let halfLineWidth = lineWidth / 2;
ctx.moveTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale);
ctx.lineWidth = lineWidth * scale;
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.arcTo((boundingBox.x.value + boundingBox.width.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, (boundingBox.x.value + boundingBox.width.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, config.cornerRadius.bottomRight.value * scale);
ctx.stroke();
}
// Bottom Border
if (config.bottom.width.value > 0) {
let color = config.bottom.color;
let lineWidth = config.bottom.width.value;
let halfLineWidth = lineWidth / 2;
ctx.lineWidth = lineWidth * scale;
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale);
ctx.lineTo((boundingBox.x.value + boundingBox.width.value - config.cornerRadius.bottomRight.value - halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale);
ctx.stroke();
}
// Bottom Left Corner
if (config.cornerRadius.bottomLeft.value > 0) {
let color = config.bottom.color;
let lineWidth = config.bottom.width.value;
let halfLineWidth = lineWidth / 2;
ctx.moveTo((boundingBox.x.value + config.cornerRadius.bottomLeft.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale);
ctx.lineWidth = lineWidth * scale;
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.arcTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - halfLineWidth) * scale, (boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomLeft.value - halfLineWidth) * scale, config.cornerRadius.bottomLeft.value * scale);
ctx.stroke();
}
// Left Border
if (config.left.width.value > 0) {
let color = config.left.color;
let lineWidth = config.left.width.value;
let halfLineWidth = lineWidth / 2;
ctx.lineWidth = lineWidth * scale;
ctx.strokeStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.moveTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + boundingBox.height.value - config.cornerRadius.bottomLeft.value - halfLineWidth) * scale);
ctx.lineTo((boundingBox.x.value + halfLineWidth) * scale, (boundingBox.y.value + config.cornerRadius.bottomRight.value + halfLineWidth) * scale);
ctx.stroke();
}
ctx.closePath();
break;
}
case (CLAY_RENDER_COMMAND_TYPE_TEXT): {
let config = readStructAtAddress(renderCommand.config.value, textConfigDefinition);
let textContents = renderCommand.text;
let stringContents = new Uint8Array(memoryDataView.buffer.slice(textContents.chars.value, textContents.chars.value + textContents.length.value));
let fontSize = config.fontSize.value * GLOBAL_FONT_SCALING_FACTOR * scale;
ctx.font = `${fontSize}px ${fontsById[config.fontId.value]}`;
let color = config.textColor;
ctx.textBaseline = 'middle';
ctx.fillStyle = `rgba(${color.r.value}, ${color.g.value}, ${color.b.value}, ${color.a.value / 255})`;
ctx.fillText(textDecoder.decode(stringContents), boundingBox.x.value * scale, (boundingBox.y.value + boundingBox.height.value / 2 + 1) * scale);
break;
}
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_START): {
window.canvasContext.save();
window.canvasContext.beginPath();
window.canvasContext.rect(boundingBox.x.value * scale, boundingBox.y.value * scale, boundingBox.width.value * scale, boundingBox.height.value * scale);
window.canvasContext.clip();
window.canvasContext.closePath();
break;
}
case (CLAY_RENDER_COMMAND_TYPE_SCISSOR_END): {
window.canvasContext.restore();
break;
}
case (CLAY_RENDER_COMMAND_TYPE_IMAGE): {
let config = readStructAtAddress(renderCommand.config.value, imageConfigDefinition);
let src = textDecoder.decode(new Uint8Array(memoryDataView.buffer.slice(config.sourceURL.chars.value, config.sourceURL.chars.value + config.sourceURL.length.value)));
if (!imageCache[src]) {
imageCache[src] = {
image: new Image(),
loaded: false,
}
imageCache[src].image.onload = () => imageCache[src].loaded = true;
imageCache[src].image.src = src;
} else if (imageCache[src].loaded) {
ctx.drawImage(imageCache[src].image, boundingBox.x.value * scale, boundingBox.y.value * scale, boundingBox.width.value * scale, boundingBox.height.value * scale);
}
break;
}
case (CLAY_RENDER_COMMAND_TYPE_CUSTOM): break;
}
}
}
function renderLoop(currentTime) {
const elapsed = currentTime - previousFrameTime;
previousFrameTime = currentTime;
let activeRendererIndex = memoryDataView.getUint32(instance.exports.ACTIVE_RENDERER_INDEX.value, true);
if (activeRendererIndex === 0) {
instance.exports.UpdateDrawFrame(scratchSpaceAddress, window.innerWidth, window.innerHeight, 0, 0, window.mousePositionXThisFrame, window.mousePositionYThisFrame, window.touchDown, window.mouseDown, 0, 0, window.dKeyPressedThisFrame, elapsed / 1000);
} else {
instance.exports.UpdateDrawFrame(scratchSpaceAddress, window.innerWidth, window.innerHeight, window.mouseWheelXThisFrame, window.mouseWheelYThisFrame, window.mousePositionXThisFrame, window.mousePositionYThisFrame, window.touchDown, window.mouseDown, window.arrowKeyDownPressedThisFrame, window.arrowKeyUpPressedThisFrame, window.dKeyPressedThisFrame, elapsed / 1000);
}
let rendererChanged = activeRendererIndex !== window.previousActiveRendererIndex;
switch (activeRendererIndex) {
case 0: {
renderLoopHTML();
if (rendererChanged) {
window.htmlRoot.style.display = 'block';
window.canvasRoot.style.display = 'none';
}
break;
}
case 1: {
renderLoopCanvas();
if (rendererChanged) {
window.htmlRoot.style.display = 'none';
window.canvasRoot.style.display = 'block';
}
break;
}
}
window.previousActiveRendererIndex = activeRendererIndex;
requestAnimationFrame(renderLoop);
window.mouseDownThisFrame = false;
window.arrowKeyUpPressedThisFrame = false;
window.arrowKeyDownPressedThisFrame = false;
window.dKeyPressedThisFrame = false;
}
init();
</script>
<body>
</body>
</html>

View File

@ -426,8 +426,7 @@
element.style.height = Math.round(renderCommand.boundingBox.height.value) + 'px';
}
// note: commandType is packed to uint8_t and has 3 garbage bytes of padding
switch(renderCommand.commandType.value & 0xff) {
switch(renderCommand.commandType.value) {
case (CLAY_RENDER_COMMAND_TYPE_NONE): {
break;
}
@ -581,9 +580,7 @@
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition);
let boundingBox = renderCommand.boundingBox;
// note: commandType is packed to uint8_t and has 3 garbage bytes of padding
switch(renderCommand.commandType.value & 0xff) {
switch(renderCommand.commandType.value) {
case (CLAY_RENDER_COMMAND_TYPE_NONE): {
break;
}

View File

@ -165,7 +165,7 @@ Clay_Color ColorLerp(Clay_Color a, Clay_Color b, float amount) {
Clay_String LOREM_IPSUM_TEXT = CLAY_STRING("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
void HighPerformancePageDesktop(float lerpValue) {
CLAY(CLAY_ID("PerformancePageOuter"), CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT({ .min = windowHeight - 50 }) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 82, 32}, .childGap = 64 }), CLAY_RECTANGLE({ .color = COLOR_RED })) {
CLAY(CLAY_ID("PerformanceDesktop"), CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT({ .min = windowHeight - 50 }) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 82, 32}, .childGap = 64 }), CLAY_RECTANGLE({ .color = COLOR_RED })) {
CLAY(CLAY_ID("PerformanceLeftText"), CLAY_LAYOUT({ .sizing = { CLAY_SIZING_PERCENT(0.5) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 })) {
CLAY_TEXT(CLAY_STRING("High Performance"), CLAY_TEXT_CONFIG({ .fontSize = 52, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
CLAY(CLAY_ID("PerformanceSpacer"), CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW({ .max = 16 }) }})) {}
@ -187,7 +187,7 @@ void HighPerformancePageDesktop(float lerpValue) {
}
void HighPerformancePageMobile(float lerpValue) {
CLAY(CLAY_ID("PerformancePageOuter"), CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT({ .min = windowHeight - 50 }) }, .childAlignment = {CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 16, 32}, .childGap = 32 }), CLAY_RECTANGLE({ .color = COLOR_RED })) {
CLAY(CLAY_ID("PerformanceMobile"), CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT({ .min = windowHeight - 50 }) }, .childAlignment = {CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER}, .padding = {.x = 16, 32}, .childGap = 32 }), CLAY_RECTANGLE({ .color = COLOR_RED })) {
CLAY(CLAY_ID("PerformanceLeftText"), CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW() }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 })) {
CLAY_TEXT(CLAY_STRING("High Performance"), CLAY_TEXT_CONFIG({ .fontSize = 48, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_LIGHT }));
CLAY(CLAY_ID("PerformanceSpacer"), CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW({ .max = 16 }) }})) {}
@ -390,11 +390,7 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa
windowWidth = width;
windowHeight = height;
Clay_SetLayoutDimensions((Clay_Dimensions) { width, height });
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("OuterScrollContainer")));
Clay_LayoutElementHashMapItem *perfPage = Clay__GetHashMapItem(Clay_GetElementId(CLAY_STRING("PerformancePageOuter")).id);
// NaN propagation can cause pain here
float perfPageYOffset = perfPage->boundingBox.y + scrollContainerData.scrollPosition->y;
if (deltaTime == deltaTime && perfPageYOffset < height && perfPageYOffset + perfPage->boundingBox.height > 0) {
if (deltaTime == deltaTime) { // NaN propagation can cause pain here
animationLerpValue += deltaTime;
if (animationLerpValue > 1) {
animationLerpValue -= 2;
@ -417,10 +413,12 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa
}
if (isMouseDown && !scrollbarData.mouseDown && Clay_PointerOver(Clay_GetElementId(CLAY_STRING("ScrollBar")))) {
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("OuterScrollContainer")));
scrollbarData.clickOrigin = (Clay_Vector2) { mousePositionX, mousePositionY };
scrollbarData.positionOrigin = *scrollContainerData.scrollPosition;
scrollbarData.mouseDown = true;
} else if (scrollbarData.mouseDown) {
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("OuterScrollContainer")));
if (scrollContainerData.contentDimensions.height > 0) {
Clay_Vector2 ratio = (Clay_Vector2) {
scrollContainerData.contentDimensions.width / scrollContainerData.scrollContainerDimensions.width,
@ -436,10 +434,12 @@ CLAY_WASM_EXPORT("UpdateDrawFrame") Clay_RenderCommandArray UpdateDrawFrame(floa
}
if (arrowKeyDownPressedThisFrame) {
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("OuterScrollContainer")));
if (scrollContainerData.contentDimensions.height > 0) {
scrollContainerData.scrollPosition->y = scrollContainerData.scrollPosition->y - 50;
}
} else if (arrowKeyUpPressedThisFrame) {
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay_GetElementId(CLAY_STRING("OuterScrollContainer")));
if (scrollContainerData.contentDimensions.height > 0) {
scrollContainerData.scrollPosition->y = scrollContainerData.scrollPosition->y + 50;
}

View File

@ -8,5 +8,5 @@ add_executable(clay_examples_cpp_project_example main.cpp)
target_include_directories(clay_examples_cpp_project_example PUBLIC .)
set(CMAKE_CXX_FLAGS_DEBUG "-Werror -Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-Werror -Wall -Wno-error=missing-braces")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

View File

@ -1,35 +0,0 @@
cmake_minimum_required(VERSION 3.27)
project(clay_examples_raylib_multi_context C)
set(CMAKE_C_STANDARD 99)
# Adding Raylib
include(FetchContent)
set(FETCHCONTENT_QUIET FALSE)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples
set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # don't build the supplied example games
FetchContent_Declare(
raylib
GIT_REPOSITORY "https://github.com/raysan5/raylib.git"
GIT_TAG "master"
GIT_PROGRESS TRUE
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(raylib)
add_executable(clay_examples_raylib_multi_context main.c)
target_compile_options(clay_examples_raylib_multi_context PUBLIC)
target_include_directories(clay_examples_raylib_multi_context PUBLIC .)
target_link_libraries(clay_examples_raylib_multi_context PUBLIC raylib)
set(CMAKE_C_FLAGS_DEBUG "-Wall -Werror -Wno-error=missing-braces -DCLAY_DEBUG")
set(CMAKE_C_FLAGS_RELEASE "-O3")
add_custom_command(
TARGET clay_examples_raylib_multi_context POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/resources
${CMAKE_CURRENT_BINARY_DIR}/resources)

View File

@ -1,267 +0,0 @@
#define CLAY_IMPLEMENTATION
#include "../../clay.h"
#include "../../renderers/raylib/clay_renderer_raylib.c"
const int FONT_ID_BODY_16 = 0;
Clay_Color COLOR_WHITE = { 255, 255, 255, 255};
void RenderHeaderButton(Clay_String text) {
CLAY(
CLAY_LAYOUT({ .padding = { 16, 8 }}),
CLAY_RECTANGLE({
.color = { 140, 140, 140, 255 },
.cornerRadius = 5
})
) {
CLAY_TEXT(text, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
.fontSize = 16,
.textColor = { 255, 255, 255, 255 }
}));
}
}
void RenderDropdownMenuItem(Clay_String text) {
CLAY(CLAY_LAYOUT({ .padding = { 16, 16 }})) {
CLAY_TEXT(text, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
.fontSize = 16,
.textColor = { 255, 255, 255, 255 }
}));
}
}
typedef struct {
Clay_String title;
Clay_String contents;
} Document;
typedef struct {
Document *documents;
int32_t length;
} DocumentArray;
DocumentArray documents = {
.documents = NULL, // TODO figure out if it's possible to const init this list
.length = 5
};
int32_t selectedDocumentIndexTop = 0;
int32_t selectedDocumentIndexBottom = 0;
typedef struct {
int32_t requestedDocumentIndex;
int32_t* selectedDocumentIndex;
} SidebarClickData;
void HandleSidebarInteraction(
Clay_ElementId elementId,
Clay_PointerData pointerData,
intptr_t userData
) {
SidebarClickData *clickData = (SidebarClickData*)userData;
// If this button was clicked
if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
if (clickData->requestedDocumentIndex >= 0 && clickData->requestedDocumentIndex < documents.length) {
// Select the corresponding document
*clickData->selectedDocumentIndex = clickData->requestedDocumentIndex;
}
}
}
// This function is new since the video was published
void HandleClayErrors(Clay_ErrorData errorData) {
printf("%s", errorData.errorText.chars);
}
typedef struct {
intptr_t next;
intptr_t memory;
} Arena;
Arena frameArena = {};
Clay_RenderCommandArray CreateLayout(Clay_Context* context, float yOffset, int32_t* documentIndex) {
Clay_SetCurrentContext(context);
Clay_SetDebugModeEnabled(true);
// Run once per frame
Clay_SetLayoutDimensions((Clay_Dimensions) {
.width = GetScreenWidth(),
.height = GetScreenHeight() / 2
});
Vector2 mousePosition = GetMousePosition();
mousePosition.y -= yOffset;
Vector2 scrollDelta = GetMouseWheelMoveV();
Clay_SetPointerState(
(Clay_Vector2) { mousePosition.x, mousePosition.y },
IsMouseButtonDown(0)
);
Clay_UpdateScrollContainers(
true,
(Clay_Vector2) { scrollDelta.x, scrollDelta.y },
GetFrameTime()
);
Clay_Sizing layoutExpand = {
.width = CLAY_SIZING_GROW(),
.height = CLAY_SIZING_GROW()
};
Clay_RectangleElementConfig contentBackgroundConfig = {
.color = { 90, 90, 90, 255 },
.cornerRadius = 8
};
Clay_BeginLayout();
// Build UI here
CLAY(
CLAY_ID("OuterContainer"),
CLAY_RECTANGLE({ .color = { 43, 41, 51, 255 } }),
CLAY_LAYOUT({
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.sizing = layoutExpand,
.padding = { 16, 16 },
.childGap = 16
})
) {
CLAY(
CLAY_ID("LowerContent"),
CLAY_LAYOUT({ .sizing = layoutExpand, .childGap = 16 })
) {
CLAY(
CLAY_ID("Sidebar"),
CLAY_RECTANGLE(contentBackgroundConfig),
CLAY_LAYOUT({
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.padding = { 16, 16 },
.childGap = 8,
.sizing = {
.width = CLAY_SIZING_FIXED(250),
.height = CLAY_SIZING_GROW()
}
})
) {
for (int i = 0; i < documents.length; i++) {
Document document = documents.documents[i];
Clay_LayoutConfig sidebarButtonLayout = {
.sizing = { .width = CLAY_SIZING_GROW() },
.padding = { 16, 16 }
};
if (i == *documentIndex) {
CLAY(
CLAY_LAYOUT(sidebarButtonLayout),
CLAY_RECTANGLE({
.color = { 120, 120, 120, 255 },
.cornerRadius = 8,
})
) {
CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
.fontSize = 20,
.textColor = { 255, 255, 255, 255 }
}));
}
} else {
SidebarClickData *clickData = (SidebarClickData *)frameArena.next;
*clickData = (SidebarClickData) { .requestedDocumentIndex = i, .selectedDocumentIndex = documentIndex };
frameArena.next += sizeof(SidebarClickData);
CLAY(
CLAY_LAYOUT(sidebarButtonLayout),
Clay_OnHover(HandleSidebarInteraction, (intptr_t)clickData),
Clay_Hovered()
? CLAY_RECTANGLE({
.color = { 120, 120, 120, 120 },
.cornerRadius = 8
})
: 0
) {
CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
.fontSize = 20,
.textColor = { 255, 255, 255, 255 }
}));
}
}
}
}
CLAY(
CLAY_ID("MainContent"),
CLAY_RECTANGLE(contentBackgroundConfig),
CLAY_SCROLL({ .vertical = true }),
CLAY_LAYOUT({
.layoutDirection = CLAY_TOP_TO_BOTTOM,
.childGap = 16,
.padding = { 16, 16 },
.sizing = layoutExpand
})
) {
Document selectedDocument = documents.documents[*documentIndex];
CLAY_TEXT(selectedDocument.title, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
.fontSize = 24,
.textColor = COLOR_WHITE
}));
CLAY_TEXT(selectedDocument.contents, CLAY_TEXT_CONFIG({
.fontId = FONT_ID_BODY_16,
.fontSize = 24,
.textColor = COLOR_WHITE
}));
}
}
}
Clay_RenderCommandArray renderCommands = Clay_EndLayout();
for (int i = 0; i < renderCommands.length; ++i) {
Clay_RenderCommandArray_Get(&renderCommands,i)->boundingBox.y += yOffset;
}
return renderCommands;
}
int main(void) {
frameArena = (Arena) { .memory = (intptr_t)malloc(1024) };
frameArena.next = frameArena.memory;
documents.documents = (Document[]) {
{ .title = CLAY_STRING("Squirrels"), .contents = CLAY_STRING("The Secret Life of Squirrels: Nature's Clever Acrobats\n""Squirrels are often overlooked creatures, dismissed as mere park inhabitants or backyard nuisances. Yet, beneath their fluffy tails and twitching noses lies an intricate world of cunning, agility, and survival tactics that are nothing short of fascinating. As one of the most common mammals in North America, squirrels have adapted to a wide range of environments from bustling urban centers to tranquil forests and have developed a variety of unique behaviors that continue to intrigue scientists and nature enthusiasts alike.\n""\n""Master Tree Climbers\n""At the heart of a squirrel's skill set is its impressive ability to navigate trees with ease. Whether they're darting from branch to branch or leaping across wide gaps, squirrels possess an innate talent for acrobatics. Their powerful hind legs, which are longer than their front legs, give them remarkable jumping power. With a tail that acts as a counterbalance, squirrels can leap distances of up to ten times the length of their body, making them some of the best aerial acrobats in the animal kingdom.\n""But it's not just their agility that makes them exceptional climbers. Squirrels' sharp, curved claws allow them to grip tree bark with precision, while the soft pads on their feet provide traction on slippery surfaces. Their ability to run at high speeds and scale vertical trunks with ease is a testament to the evolutionary adaptations that have made them so successful in their arboreal habitats.\n""\n""Food Hoarders Extraordinaire\n""Squirrels are often seen frantically gathering nuts, seeds, and even fungi in preparation for winter. While this behavior may seem like instinctual hoarding, it is actually a survival strategy that has been honed over millions of years. Known as \"scatter hoarding,\" squirrels store their food in a variety of hidden locations, often burying it deep in the soil or stashing it in hollowed-out tree trunks.\n""Interestingly, squirrels have an incredible memory for the locations of their caches. Research has shown that they can remember thousands of hiding spots, often returning to them months later when food is scarce. However, they don't always recover every stash some forgotten caches eventually sprout into new trees, contributing to forest regeneration. This unintentional role as forest gardeners highlights the ecological importance of squirrels in their ecosystems.\n""\n""The Great Squirrel Debate: Urban vs. Wild\n""While squirrels are most commonly associated with rural or wooded areas, their adaptability has allowed them to thrive in urban environments as well. In cities, squirrels have become adept at finding food sources in places like parks, streets, and even garbage cans. However, their urban counterparts face unique challenges, including traffic, predators, and the lack of natural shelters. Despite these obstacles, squirrels in urban areas are often observed using human infrastructure such as buildings, bridges, and power lines as highways for their acrobatic escapades.\n""There is, however, a growing concern regarding the impact of urban life on squirrel populations. Pollution, deforestation, and the loss of natural habitats are making it more difficult for squirrels to find adequate food and shelter. As a result, conservationists are focusing on creating squirrel-friendly spaces within cities, with the goal of ensuring these resourceful creatures continue to thrive in both rural and urban landscapes.\n""\n""A Symbol of Resilience\n""In many cultures, squirrels are symbols of resourcefulness, adaptability, and preparation. Their ability to thrive in a variety of environments while navigating challenges with agility and grace serves as a reminder of the resilience inherent in nature. Whether you encounter them in a quiet forest, a city park, or your own backyard, squirrels are creatures that never fail to amaze with their endless energy and ingenuity.\n""In the end, squirrels may be small, but they are mighty in their ability to survive and thrive in a world that is constantly changing. So next time you spot one hopping across a branch or darting across your lawn, take a moment to appreciate the remarkable acrobat at work a true marvel of the natural world.\n") },
{ .title = CLAY_STRING("Lorem Ipsum"), .contents = CLAY_STRING("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") },
{ .title = CLAY_STRING("Vacuum Instructions"), .contents = CLAY_STRING("Chapter 3: Getting Started - Unpacking and Setup\n""\n""Congratulations on your new SuperClean Pro 5000 vacuum cleaner! In this section, we will guide you through the simple steps to get your vacuum up and running. Before you begin, please ensure that you have all the components listed in the \"Package Contents\" section on page 2.\n""\n""1. Unboxing Your Vacuum\n""Carefully remove the vacuum cleaner from the box. Avoid using sharp objects that could damage the product. Once removed, place the unit on a flat, stable surface to proceed with the setup. Inside the box, you should find:\n""\n"" The main vacuum unit\n"" A telescoping extension wand\n"" A set of specialized cleaning tools (crevice tool, upholstery brush, etc.)\n"" A reusable dust bag (if applicable)\n"" A power cord with a 3-prong plug\n"" A set of quick-start instructions\n""\n""2. Assembling Your Vacuum\n""Begin by attaching the extension wand to the main body of the vacuum cleaner. Line up the connectors and twist the wand into place until you hear a click. Next, select the desired cleaning tool and firmly attach it to the wand's end, ensuring it is securely locked in.\n""\n""For models that require a dust bag, slide the bag into the compartment at the back of the vacuum, making sure it is properly aligned with the internal mechanism. If your vacuum uses a bagless system, ensure the dust container is correctly seated and locked in place before use.\n""\n""3. Powering On\n""To start the vacuum, plug the power cord into a grounded electrical outlet. Once plugged in, locate the power switch, usually positioned on the side of the handle or body of the unit, depending on your model. Press the switch to the \"On\" position, and you should hear the motor begin to hum. If the vacuum does not power on, check that the power cord is securely plugged in, and ensure there are no blockages in the power switch.\n""\n""Note: Before first use, ensure that the vacuum filter (if your model has one) is properly installed. If unsure, refer to \"Section 5: Maintenance\" for filter installation instructions.") },
{ .title = CLAY_STRING("Article 4"), .contents = CLAY_STRING("Article 4") },
{ .title = CLAY_STRING("Article 5"), .contents = CLAY_STRING("Article 5") },
};
Clay_Raylib_Initialize(1024, 768, "Introducing Clay Demo", FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); // Extra parameters to this function are new since the video was published
uint64_t clayRequiredMemory = Clay_MinMemorySize();
Clay_Arena clayMemoryTop = Clay_CreateArenaWithCapacityAndMemory(clayRequiredMemory, malloc(clayRequiredMemory));
Clay_Context *clayContextTop = Clay_Initialize(clayMemoryTop, (Clay_Dimensions) {
.width = GetScreenWidth(),
.height = GetScreenHeight() / 2
}, (Clay_ErrorHandler) { HandleClayErrors }); // This final argument is new since the video was published
Clay_Arena clayMemoryBottom = Clay_CreateArenaWithCapacityAndMemory(clayRequiredMemory, malloc(clayRequiredMemory));
Clay_Context *clayContextBottom = Clay_Initialize(clayMemoryBottom, (Clay_Dimensions) {
.width = GetScreenWidth(),
.height = GetScreenHeight() / 2
}, (Clay_ErrorHandler) { HandleClayErrors }); // This final argument is new since the video was published
Clay_SetMeasureTextFunction(Raylib_MeasureText);
Raylib_fonts[FONT_ID_BODY_16] = (Raylib_Font) {
.font = LoadFontEx("resources/Roboto-Regular.ttf", 48, 0, 400),
.fontId = FONT_ID_BODY_16
};
SetTextureFilter(Raylib_fonts[FONT_ID_BODY_16].font.texture, TEXTURE_FILTER_BILINEAR);
while (!WindowShouldClose()) {
frameArena.next = frameArena.memory;
Clay_RenderCommandArray renderCommandsTop = CreateLayout(clayContextTop, 0, &selectedDocumentIndexTop);
Clay_RenderCommandArray renderCommandsBottom = CreateLayout(clayContextBottom, GetScreenHeight() / 2, &selectedDocumentIndexBottom);
BeginDrawing();
ClearBackground(BLACK);
Clay_Raylib_Render(renderCommandsTop);
Clay_Raylib_Render(renderCommandsBottom);
EndDrawing();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

View File

@ -10,8 +10,8 @@ const uint32_t FONT_ID_BODY_16 = 1;
Texture2D profilePicture;
#define RAYLIB_VECTOR2_TO_CLAY_VECTOR2(vector) (Clay_Vector2) { .x = vector.x, .y = vector.y }
Clay_String profileText = {.length = 101, .chars = "Profile Page one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen" };
Clay_TextElementConfig headerTextConfig = { .fontId = 1, .fontSize = 16, .textColor = {0,0,0,255} };
Clay_String profileText = CLAY_STRING("Profile Page one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen");
Clay_TextElementConfig headerTextConfig = (Clay_TextElementConfig) { .fontId = 1, .fontSize = 16, .textColor = {0,0,0,255} };
void HandleHeaderButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, intptr_t userData) {
if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
@ -28,9 +28,9 @@ void RenderHeaderButton(Clay_String text) {
}
}
Clay_LayoutConfig dropdownTextItemLayout = { .padding = {8, 4} };
Clay_RectangleElementConfig dropdownRectangleConfig = { .color = {180, 180, 180, 255} };
Clay_TextElementConfig dropdownTextElementConfig = { .fontSize = 24, .textColor = {255,255,255,255} };
Clay_LayoutConfig dropdownTextItemLayout = (Clay_LayoutConfig) { .padding = {8, 4} };
Clay_RectangleElementConfig dropdownRectangleConfig = (Clay_RectangleElementConfig) { .color = {180, 180, 180, 255} };
Clay_TextElementConfig dropdownTextElementConfig = (Clay_TextElementConfig) { .fontSize = 24, .textColor = {255,255,255,255} };
void RenderDropdownTextItem(int index) {
CLAY(CLAY_IDI("ScrollContainerItem", index), CLAY_LAYOUT(dropdownTextItemLayout), CLAY_RECTANGLE(dropdownRectangleConfig)) {
@ -142,7 +142,7 @@ typedef struct
bool mouseDown;
} ScrollbarData;
ScrollbarData scrollbarData = {};
ScrollbarData scrollbarData = (ScrollbarData) {};
bool debugEnabled = false;
@ -208,10 +208,10 @@ void HandleClayErrors(Clay_ErrorData errorData) {
printf("%s", errorData.errorText.chars);
if (errorData.errorType == CLAY_ERROR_TYPE_ELEMENTS_CAPACITY_EXCEEDED) {
reinitializeClay = true;
Clay_SetMaxElementCount(Clay_GetMaxElementCount() * 2);
Clay_SetMaxElementCount(Clay__maxElementCount * 2);
} else if (errorData.errorType == CLAY_ERROR_TYPE_TEXT_MEASUREMENT_CAPACITY_EXCEEDED) {
reinitializeClay = true;
Clay_SetMaxMeasureTextCacheWordCount(Clay_GetMaxMeasureTextCacheWordCount() * 2);
Clay_SetMaxMeasureTextCacheWordCount(Clay__maxMeasureTextCacheWordCount * 2);
}
}

View File

@ -317,9 +317,7 @@
for (let i = 0; i < length; i++, arrayOffset += renderCommandSize) {
let renderCommand = readStructAtAddress(arrayOffset, renderCommandDefinition);
let boundingBox = renderCommand.boundingBox;
// note: commandType is packed to uint8_t and has 3 garbage bytes of padding
switch(renderCommand.commandType.value & 0xff) {
switch(renderCommand.commandType.value) {
case (CLAY_RENDER_COMMAND_TYPE_NONE): {
break;
}

View File

@ -336,7 +336,7 @@
let element = null;
if (!elementCache[renderCommand.id.value]) {
let elementType = 'div';
switch (renderCommand.commandType.value & 0xff) {
switch (renderCommand.commandType.value) {
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
if (readStructAtAddress(renderCommand.config.value, rectangleConfigDefinition).link.length.value > 0) {
elementType = 'a';
@ -384,8 +384,7 @@
element.style.height = Math.round(renderCommand.boundingBox.height.value) + 'px';
}
// note: commandType is packed to uint8_t and has 3 garbage bytes of padding
switch(renderCommand.commandType.value & 0xff) {
switch(renderCommand.commandType.value) {
case (CLAY_RENDER_COMMAND_TYPE_NONE): {
break;
}