mirror of
https://github.com/nicbarker/clay.git
synced 2025-04-19 04:38:01 +00:00
added .gitkeeps to the lib and build folder
This commit is contained in:
parent
e9f2e6c4f1
commit
1b67696843
0
bindings/c3/build/.gitkeep
Normal file
0
bindings/c3/build/.gitkeep
Normal file
4126
bindings/c3/c-lang/source/clay.c
Normal file
4126
bindings/c3/c-lang/source/clay.c
Normal file
File diff suppressed because it is too large
Load Diff
292
bindings/c3/examples/video-example.c3
Normal file
292
bindings/c3/examples/video-example.c3
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
module videoexample;
|
||||||
|
|
||||||
|
import clay;
|
||||||
|
import raylib5::rl;
|
||||||
|
|
||||||
|
const uint FONT_ID_BODY_16 = 0;
|
||||||
|
|
||||||
|
fn void errorHandler(ErrorData errorData)
|
||||||
|
{
|
||||||
|
// std::io::printfn("ERROR: \"%s\"", errorData.errorText.chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void renderDropdownMenuItem(String text) {
|
||||||
|
@clay(
|
||||||
|
clay::layout({ .padding = clay::paddingUni(16)})
|
||||||
|
) {
|
||||||
|
clay::text(
|
||||||
|
text, clay::textConfig({
|
||||||
|
.textColor = { 255, 255, 255, 255 },
|
||||||
|
.fontId = FONT_ID_BODY_16,
|
||||||
|
.fontSize = 16,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void renderHeaderButton(String text) {
|
||||||
|
@clay(
|
||||||
|
clay::layout({ .padding = { 16, 16, 8, 8 }}),
|
||||||
|
clay::rectangle({
|
||||||
|
.color = { 140, 140, 140, 255 },
|
||||||
|
.cornerRadius = clay::cornerRadiusUni(5)
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
clay::text(text, clay::textConfig({
|
||||||
|
.textColor = { 255, 255, 255, 255 },
|
||||||
|
.fontId = FONT_ID_BODY_16,
|
||||||
|
.fontSize = 16,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void handleSidebarInteraction(
|
||||||
|
ElementId elementId,
|
||||||
|
PointerData pointerData,
|
||||||
|
iptr userData
|
||||||
|
) {
|
||||||
|
// If this button was clicked
|
||||||
|
if (pointerData.state == PointerState.RELEASED_THIS_FRAME) {
|
||||||
|
if (userData >= 0 && userData < ALL_DOCUMENTS.len) {
|
||||||
|
// Select the corresponding document
|
||||||
|
selectedDocumentIndex = (uint)userData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Document {
|
||||||
|
String title;
|
||||||
|
String contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Document[*] ALL_DOCUMENTS = {
|
||||||
|
{ "Squirrels", "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" },
|
||||||
|
{ "Lorem Ipsum", "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." },
|
||||||
|
{ "Vacuum Instructions", "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." },
|
||||||
|
{ "Article 4", "Article 4" },
|
||||||
|
{ "Article 5", "Article 5" }
|
||||||
|
};
|
||||||
|
|
||||||
|
uint selectedDocumentIndex = 0;
|
||||||
|
|
||||||
|
RectangleElementConfig contentBackgroundConfig = {
|
||||||
|
{ 90, 90, 90, 255 },
|
||||||
|
clay::@cornerRadiusUniCT(8)
|
||||||
|
};
|
||||||
|
|
||||||
|
Sizing layoutExpand = Sizing{ clay::sizingGrow(), clay::sizingGrow() };
|
||||||
|
|
||||||
|
LayoutConfig sidebarButtonLayout = LayoutConfig{
|
||||||
|
.sizing = { .width = clay::sizingGrow() },
|
||||||
|
.padding = clay::paddingCT(16, 16, 16, 16)
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isDebugModeEnabled = false;
|
||||||
|
|
||||||
|
fn void main() @public
|
||||||
|
{
|
||||||
|
rl::setConfigFlags(rl::FLAG_VSYNC_HINT | rl::FLAG_WINDOW_RESIZABLE | rl::FLAG_WINDOW_HIGHDPI | rl::FLAG_MSAA_4X_HINT);
|
||||||
|
rl::initWindow(1024, 768, "Introducing Clay C3-Demo");
|
||||||
|
defer rl::closeWindow();
|
||||||
|
|
||||||
|
uint clayRequiredMemory = clay::minMemorySize();
|
||||||
|
Arena clayMemory = clay::createArena(clayRequiredMemory, malloc(clayRequiredMemory));
|
||||||
|
clay::initialize(clayMemory, { rl::getScreenWidth(), rl::getScreenHeight() }, { &errorHandler, 0 });
|
||||||
|
|
||||||
|
|
||||||
|
clay::setMeasureTextFunction(&clay::renderer::raylibMeasureText);
|
||||||
|
clay::renderer::raylibFonts[FONT_ID_BODY_16] = {
|
||||||
|
FONT_ID_BODY_16,
|
||||||
|
rl::loadFontEx("resources/Lexend-Regular.ttf", 48, null, 400)
|
||||||
|
};
|
||||||
|
|
||||||
|
rl::setTextureFilter(
|
||||||
|
clay::renderer::raylibFonts[FONT_ID_BODY_16].font.texture,
|
||||||
|
TextureFilter.BILINEAR
|
||||||
|
);
|
||||||
|
|
||||||
|
while (!rl::windowShouldClose()) {
|
||||||
|
clay::setLayoutDimensions({rl::getScreenWidth(), rl::getScreenHeight()});
|
||||||
|
Vector2 mouse_position = rl::getMousePosition();
|
||||||
|
Vector2 scroll_delta = rl::getMouseWheelMoveV();
|
||||||
|
clay::setPointerState({mouse_position.x, mouse_position.y}, rl::isMouseButtonDown(MouseButton.LEFT));
|
||||||
|
clay::updateScrollContainer(true, {scroll_delta.x, scroll_delta.y}, rl::getFrameTime());
|
||||||
|
|
||||||
|
if (rl::isKeyReleased(rl::KEY_D)) { isDebugModeEnabled = !isDebugModeEnabled; clay::setDebugModeEnabled(isDebugModeEnabled); }
|
||||||
|
|
||||||
|
clay::beginLayout();
|
||||||
|
|
||||||
|
@clay(
|
||||||
|
clay::id("OuterContainer"),
|
||||||
|
clay::rectangle({ .color = { 43, 41, 51, 255 } }),
|
||||||
|
clay::layout({
|
||||||
|
.sizing = layoutExpand,
|
||||||
|
.padding = clay::paddingUni(16),
|
||||||
|
.childGap = 16,
|
||||||
|
.layoutDirection = LayoutDirection.TOP_TO_BOTTOM,
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
@clay(
|
||||||
|
clay::id("HeaderBar"),
|
||||||
|
clay::rectangle(contentBackgroundConfig),
|
||||||
|
clay::layout({
|
||||||
|
.sizing = {
|
||||||
|
.height = clay::sizingFixed(60),
|
||||||
|
.width = clay::sizingGrow()
|
||||||
|
},
|
||||||
|
.padding = { 16, 16, 0, 0 },
|
||||||
|
.childGap = 16,
|
||||||
|
.childAlignment = {
|
||||||
|
.y = AlignY.CENTER
|
||||||
|
}
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
// Header buttons go here
|
||||||
|
@clay(
|
||||||
|
clay::id("FileButton"),
|
||||||
|
clay::layout({ .padding = { 16, 16, 8, 8 }}),
|
||||||
|
clay::rectangle({
|
||||||
|
.color = { 140, 140, 140, 255 },
|
||||||
|
.cornerRadius = clay::cornerRadiusUni(5)
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
clay::text("File", clay::textConfig({
|
||||||
|
.textColor = { 255, 255, 255, 255 },
|
||||||
|
.fontId = FONT_ID_BODY_16,
|
||||||
|
.fontSize = 16,
|
||||||
|
}));
|
||||||
|
|
||||||
|
bool fileMenuVisible =
|
||||||
|
clay::pointerOver(clay::getElementId("FileButton"))
|
||||||
|
||
|
||||||
|
clay::pointerOver(clay::getElementId("FileMenu"));
|
||||||
|
|
||||||
|
if (fileMenuVisible) { // Below has been changed slightly to fix the small bug where the menu would dismiss when mousing over the top gap
|
||||||
|
@clay(
|
||||||
|
clay::id("FileMenu"),
|
||||||
|
clay::floating({
|
||||||
|
.attachment = {
|
||||||
|
.parent = AttachPoint.LEFT_BOTTOM
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
clay::layout({
|
||||||
|
.padding = {0, 0, 8, 8 }
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
@clay(
|
||||||
|
clay::layout({
|
||||||
|
.sizing = {
|
||||||
|
.width = clay::sizingFixed(200)
|
||||||
|
},
|
||||||
|
.layoutDirection = LayoutDirection.TOP_TO_BOTTOM,
|
||||||
|
}),
|
||||||
|
clay::rectangle({
|
||||||
|
.color = { 40, 40, 40, 255 },
|
||||||
|
.cornerRadius = clay::cornerRadiusUni(8)
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
// Render dropdown items here
|
||||||
|
renderDropdownMenuItem("New");
|
||||||
|
renderDropdownMenuItem("Open");
|
||||||
|
renderDropdownMenuItem("Close");
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
renderHeaderButton("Edit");
|
||||||
|
@clay(clay::layout({ .sizing = { .width = clay::sizingGrow() }})) {};
|
||||||
|
renderHeaderButton("Upload");
|
||||||
|
renderHeaderButton("Media");
|
||||||
|
renderHeaderButton("Support");
|
||||||
|
};
|
||||||
|
|
||||||
|
@clay(
|
||||||
|
clay::id("LowerContent"),
|
||||||
|
clay::layout({ .sizing = layoutExpand, .childGap = 16 })
|
||||||
|
) {
|
||||||
|
@clay(
|
||||||
|
clay::id("Sidebar"),
|
||||||
|
contentBackgroundConfig,
|
||||||
|
clay::layout({
|
||||||
|
.sizing = {
|
||||||
|
.width = clay::sizingFixed(250),
|
||||||
|
.height = clay::sizingGrow()
|
||||||
|
},
|
||||||
|
.padding = clay::paddingUni(16),
|
||||||
|
.childGap = 8,
|
||||||
|
.layoutDirection = LayoutDirection.TOP_TO_BOTTOM,
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
for (int i = 0; i < ALL_DOCUMENTS.len; i++) {
|
||||||
|
Document document = ALL_DOCUMENTS[i];
|
||||||
|
|
||||||
|
if (i == selectedDocumentIndex) {
|
||||||
|
@clay(
|
||||||
|
clay::layout(sidebarButtonLayout),
|
||||||
|
clay::rectangle({
|
||||||
|
.color = { 120, 120, 120, 255 },
|
||||||
|
.cornerRadius = clay::cornerRadiusUni(8),
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
clay::text(document.title, clay::textConfig({
|
||||||
|
.textColor = { 255, 255, 255, 255 },
|
||||||
|
.fontId = FONT_ID_BODY_16,
|
||||||
|
.fontSize = 20,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
@clay(
|
||||||
|
clay::layout(sidebarButtonLayout),
|
||||||
|
clay::onHover(&handleSidebarInteraction, i),
|
||||||
|
clay::@bodyIf(
|
||||||
|
clay::hovered(),
|
||||||
|
clay::rectangle({
|
||||||
|
.color = { 120, 120, 120, 120 },
|
||||||
|
.cornerRadius = clay::cornerRadiusUni(8)
|
||||||
|
})
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
clay::text(document.title, clay::textConfig({
|
||||||
|
.textColor = { 255, 255, 255, 255 },
|
||||||
|
.fontId = FONT_ID_BODY_16,
|
||||||
|
.fontSize = 20,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@clay(
|
||||||
|
clay::id("MainContent"),
|
||||||
|
clay::rectangle(contentBackgroundConfig),
|
||||||
|
clay::scroll({ .vertical = true }),
|
||||||
|
clay::layout({
|
||||||
|
.layoutDirection = LayoutDirection.TOP_TO_BOTTOM,
|
||||||
|
.childGap = 14,
|
||||||
|
.padding = clay::paddingUni(16),
|
||||||
|
.sizing = layoutExpand,
|
||||||
|
}),
|
||||||
|
) {
|
||||||
|
Document document = ALL_DOCUMENTS[selectedDocumentIndex];
|
||||||
|
clay::text(document.title, clay::textConfig({
|
||||||
|
.fontId = FONT_ID_BODY_16,
|
||||||
|
.fontSize = 24,
|
||||||
|
.textColor = {255, 255, 255, 255},
|
||||||
|
}));
|
||||||
|
clay::text(document.contents, clay::textConfig({
|
||||||
|
.fontId = FONT_ID_BODY_16,
|
||||||
|
.fontSize = 24,
|
||||||
|
.textColor = {255, 255, 255, 255},
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderCommandArray renderCommands = clay::endLayout();
|
||||||
|
|
||||||
|
|
||||||
|
rl::beginDrawing();
|
||||||
|
rl::clearBackground(rl::WHITE);
|
||||||
|
clay::renderer::raylibRender(renderCommands);
|
||||||
|
rl::endDrawing();
|
||||||
|
}
|
||||||
|
}
|
0
bindings/c3/lib/.gitkeep
Normal file
0
bindings/c3/lib/.gitkeep
Normal file
33
bindings/c3/project.json
Normal file
33
bindings/c3/project.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"langrev": "1",
|
||||||
|
"authors": [ "Jefferey Schlueter <jefferey.l.schlueter@gmail.com>" ],
|
||||||
|
"version": "0.1.0",
|
||||||
|
"dependency-search-paths": [ "lib" ],
|
||||||
|
"targets": {
|
||||||
|
|
||||||
|
// TODO: found out how to stop this from outputting a .lib and .pdb in addition to the .exe (they don't do anything)
|
||||||
|
"video-example": {
|
||||||
|
"output": "build/video-example/",
|
||||||
|
"c-sources": [ "c-lang/source/clay.c" ],
|
||||||
|
"cflags": "-DCLAY_IMPLEMENTATION", // makes the clay source actually define things
|
||||||
|
"type": "executable",
|
||||||
|
"dependencies": [ "raylib55" ],
|
||||||
|
"sources": [ "source/clay.c3", "source/clay-raylib-renderer.c3", "examples/video-example.c3" ],
|
||||||
|
// "link-libc": false, // TODO; leads to duplicate definitions (eg math_nolibc)
|
||||||
|
// "use-stdlib": false, // TODO: leads to ZString being undefined -> then missing main @main_to_void_main
|
||||||
|
// "features": ["NO_STDLIB"]
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: figure out why creating static/dynamic libraries with C sources doesn't work (emits no errors just crashes out and dumps an empty clay-win.h into the project dir)
|
||||||
|
// "clay-win": {
|
||||||
|
// "output": "build/clay.c3l/windows-x64",
|
||||||
|
// "c-sources": [ "c-lang/source/clay.c" ],
|
||||||
|
// "sources": [ "source/clay.c3" ],
|
||||||
|
// "type": "static-lib"
|
||||||
|
// },
|
||||||
|
// build args with no C references
|
||||||
|
//../c3c.exe --link-libc=no --use-stdlib=no -o clay --template static-lib --output-dir build/clay.c3l/windows-x64 --print-linking --print-output -vvv static-lib source/clay-slim.c3
|
||||||
|
},
|
||||||
|
"cc": "gcc",
|
||||||
|
"cpu": "generic",
|
||||||
|
}
|
BIN
bindings/c3/resources/Lexend-Regular.ttf
Normal file
BIN
bindings/c3/resources/Lexend-Regular.ttf
Normal file
Binary file not shown.
447
bindings/c3/source/clay-raylib-renderer.c3
Normal file
447
bindings/c3/source/clay-raylib-renderer.c3
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
module raylib5::rl @if($feature(NO_STDLIB));
|
||||||
|
|
||||||
|
distinct ZString = inline char*;
|
||||||
|
|
||||||
|
module clay::renderer;
|
||||||
|
import raylib5::rl;
|
||||||
|
|
||||||
|
// TODO: this entire file was very rushed so it can probably be cleaned up a LOT
|
||||||
|
fn double calculate_sine(double x) {
|
||||||
|
double term = x;
|
||||||
|
double sum = term;
|
||||||
|
double n = 1;
|
||||||
|
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
term *= (-1) * x * x / ((2 * n) * (2 * n + 1));
|
||||||
|
sum += term;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn double calculate_cosine(double x) {
|
||||||
|
double term = 1;
|
||||||
|
double sum = term;
|
||||||
|
double n = 1;
|
||||||
|
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
term *= (-1) * x * x / ((2 * n - 1) * (2 * n));
|
||||||
|
sum += term;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro double calculate_tangent(double x) {
|
||||||
|
double sine = calculate_sine(x);
|
||||||
|
double cosine = calculate_cosine(x);
|
||||||
|
// Check for cases where cosine is zero (tangent is undefined)
|
||||||
|
if (cosine == 0.0) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return sine / cosine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn Color clayToRaylibColor(ClayColor color) @inline
|
||||||
|
{
|
||||||
|
return { (char)$$round(color.r), (char)$$round(color.g), (char)$$round(color.b), (char)$$round(color.a)};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RaylibFont
|
||||||
|
{
|
||||||
|
int fontId;
|
||||||
|
rl::Font font;
|
||||||
|
}
|
||||||
|
|
||||||
|
RaylibFont[10] raylibFonts;
|
||||||
|
rl::Camera raylibCamera;
|
||||||
|
|
||||||
|
const Matrix MATRIX_IDENTITY = {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CustomLayoutElementType
|
||||||
|
{
|
||||||
|
MODEL_3D
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Model3DLayoutElement
|
||||||
|
{
|
||||||
|
rl::Model model;
|
||||||
|
float scale;
|
||||||
|
rl::Vector3 position;
|
||||||
|
rl::Matrix rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CustomLayoutElement
|
||||||
|
{
|
||||||
|
CustomLayoutElementType type;
|
||||||
|
union element
|
||||||
|
{
|
||||||
|
Model3DLayoutElement model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Matrix matrixPerspective(double fovY, double aspect, double nearPlane, double farPlane)
|
||||||
|
{
|
||||||
|
Matrix result = { 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0 };
|
||||||
|
|
||||||
|
double top = nearPlane * calculate_tangent(fovY*0.5*rl::RAD2DEG);
|
||||||
|
double bottom = -top;
|
||||||
|
double right = top*aspect;
|
||||||
|
double left = -right;
|
||||||
|
|
||||||
|
// MatrixFrustum(-right, right, -top, top, near, far);
|
||||||
|
float rl = (float)(right - left);
|
||||||
|
float tb = (float)(top - bottom);
|
||||||
|
float far_near = (float)(farPlane - nearPlane);
|
||||||
|
|
||||||
|
result.m0 = ((float)nearPlane*2.0f)/rl;
|
||||||
|
result.m5 = ((float)nearPlane*2.0f)/tb;
|
||||||
|
result.m8 = ((float)right + (float)left)/rl;
|
||||||
|
result.m9 = ((float)top + (float)bottom)/tb;
|
||||||
|
result.m10 = -((float)farPlane + (float)nearPlane)/far_near;
|
||||||
|
result.m11 = -1.0f;
|
||||||
|
result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/far_near;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Vector3 vector3Unproject(Vector3 source, Matrix projection, Matrix view)
|
||||||
|
{
|
||||||
|
Vector3 result = { 0, 0, 0 };
|
||||||
|
|
||||||
|
// Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it
|
||||||
|
Matrix matViewProj = { // MatrixMultiply(view, projection);
|
||||||
|
view.m0*projection.m0 + view.m1*projection.m4 + view.m2*projection.m8 + view.m3*projection.m12,
|
||||||
|
view.m0*projection.m1 + view.m1*projection.m5 + view.m2*projection.m9 + view.m3*projection.m13,
|
||||||
|
view.m0*projection.m2 + view.m1*projection.m6 + view.m2*projection.m10 + view.m3*projection.m14,
|
||||||
|
view.m0*projection.m3 + view.m1*projection.m7 + view.m2*projection.m11 + view.m3*projection.m15,
|
||||||
|
view.m4*projection.m0 + view.m5*projection.m4 + view.m6*projection.m8 + view.m7*projection.m12,
|
||||||
|
view.m4*projection.m1 + view.m5*projection.m5 + view.m6*projection.m9 + view.m7*projection.m13,
|
||||||
|
view.m4*projection.m2 + view.m5*projection.m6 + view.m6*projection.m10 + view.m7*projection.m14,
|
||||||
|
view.m4*projection.m3 + view.m5*projection.m7 + view.m6*projection.m11 + view.m7*projection.m15,
|
||||||
|
view.m8*projection.m0 + view.m9*projection.m4 + view.m10*projection.m8 + view.m11*projection.m12,
|
||||||
|
view.m8*projection.m1 + view.m9*projection.m5 + view.m10*projection.m9 + view.m11*projection.m13,
|
||||||
|
view.m8*projection.m2 + view.m9*projection.m6 + view.m10*projection.m10 + view.m11*projection.m14,
|
||||||
|
view.m8*projection.m3 + view.m9*projection.m7 + view.m10*projection.m11 + view.m11*projection.m15,
|
||||||
|
view.m12*projection.m0 + view.m13*projection.m4 + view.m14*projection.m8 + view.m15*projection.m12,
|
||||||
|
view.m12*projection.m1 + view.m13*projection.m5 + view.m14*projection.m9 + view.m15*projection.m13,
|
||||||
|
view.m12*projection.m2 + view.m13*projection.m6 + view.m14*projection.m10 + view.m15*projection.m14,
|
||||||
|
view.m12*projection.m3 + view.m13*projection.m7 + view.m14*projection.m11 + view.m15*projection.m15 };
|
||||||
|
|
||||||
|
// Calculate inverted matrix . MatrixInvert(matViewProj);
|
||||||
|
// Cache the matrix values (speed optimization)
|
||||||
|
float a00 = matViewProj.m0;
|
||||||
|
float a01 = matViewProj.m1;
|
||||||
|
float a02 = matViewProj.m2;
|
||||||
|
float a03 = matViewProj.m3;
|
||||||
|
float a10 = matViewProj.m4;
|
||||||
|
float a11 = matViewProj.m5;
|
||||||
|
float a12 = matViewProj.m6;
|
||||||
|
float a13 = matViewProj.m7;
|
||||||
|
float a20 = matViewProj.m8;
|
||||||
|
float a21 = matViewProj.m9;
|
||||||
|
float a22 = matViewProj.m10;
|
||||||
|
float a23 = matViewProj.m11;
|
||||||
|
float a30 = matViewProj.m12;
|
||||||
|
float a31 = matViewProj.m13;
|
||||||
|
float a32 = matViewProj.m14;
|
||||||
|
float a33 = matViewProj.m15;
|
||||||
|
|
||||||
|
float b00 = a00*a11 - a01*a10;
|
||||||
|
float b01 = a00*a12 - a02*a10;
|
||||||
|
float b02 = a00*a13 - a03*a10;
|
||||||
|
float b03 = a01*a12 - a02*a11;
|
||||||
|
float b04 = a01*a13 - a03*a11;
|
||||||
|
float b05 = a02*a13 - a03*a12;
|
||||||
|
float b06 = a20*a31 - a21*a30;
|
||||||
|
float b07 = a20*a32 - a22*a30;
|
||||||
|
float b08 = a20*a33 - a23*a30;
|
||||||
|
float b09 = a21*a32 - a22*a31;
|
||||||
|
float b10 = a21*a33 - a23*a31;
|
||||||
|
float b11 = a22*a33 - a23*a32;
|
||||||
|
|
||||||
|
// Calculate the invert determinant (inlined to avoid double-caching)
|
||||||
|
float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
|
||||||
|
|
||||||
|
Matrix matViewProjInv = {
|
||||||
|
(a11*b11 - a12*b10 + a13*b09)*invDet,
|
||||||
|
(-a01*b11 + a02*b10 - a03*b09)*invDet,
|
||||||
|
(a31*b05 - a32*b04 + a33*b03)*invDet,
|
||||||
|
(-a21*b05 + a22*b04 - a23*b03)*invDet,
|
||||||
|
(-a10*b11 + a12*b08 - a13*b07)*invDet,
|
||||||
|
(a00*b11 - a02*b08 + a03*b07)*invDet,
|
||||||
|
(-a30*b05 + a32*b02 - a33*b01)*invDet,
|
||||||
|
(a20*b05 - a22*b02 + a23*b01)*invDet,
|
||||||
|
(a10*b10 - a11*b08 + a13*b06)*invDet,
|
||||||
|
(-a00*b10 + a01*b08 - a03*b06)*invDet,
|
||||||
|
(a30*b04 - a31*b02 + a33*b00)*invDet,
|
||||||
|
(-a20*b04 + a21*b02 - a23*b00)*invDet,
|
||||||
|
(-a10*b09 + a11*b07 - a12*b06)*invDet,
|
||||||
|
(a00*b09 - a01*b07 + a02*b06)*invDet,
|
||||||
|
(-a30*b03 + a31*b01 - a32*b00)*invDet,
|
||||||
|
(a20*b03 - a21*b01 + a22*b00)*invDet };
|
||||||
|
|
||||||
|
// Create quaternion from source point
|
||||||
|
rl::Quaternion quat = { source.x, source.y, source.z, 1.0f };
|
||||||
|
|
||||||
|
// Multiply quat point by unprojecte matrix
|
||||||
|
rl::Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv)
|
||||||
|
matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w,
|
||||||
|
matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w,
|
||||||
|
matViewProjInv.m2*quat.x + matViewProjInv.m6*quat.y + matViewProjInv.m10*quat.z + matViewProjInv.m14*quat.w,
|
||||||
|
matViewProjInv.m3*quat.x + matViewProjInv.m7*quat.y + matViewProjInv.m11*quat.z + matViewProjInv.m15*quat.w };
|
||||||
|
|
||||||
|
// Normalized world points in vectors
|
||||||
|
result.x = qtransformed.x/qtransformed.w;
|
||||||
|
result.y = qtransformed.y/qtransformed.w;
|
||||||
|
result.z = qtransformed.z/qtransformed.w;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Matrix matrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane)
|
||||||
|
{
|
||||||
|
Matrix result = { 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0 };
|
||||||
|
|
||||||
|
float rl = (float)(right - left);
|
||||||
|
float tb = (float)(top - bottom);
|
||||||
|
float far_near = (float)(farPlane - nearPlane);
|
||||||
|
|
||||||
|
result.m0 = 2.0f/rl;
|
||||||
|
result.m1 = 0.0f;
|
||||||
|
result.m2 = 0.0f;
|
||||||
|
result.m3 = 0.0f;
|
||||||
|
result.m4 = 0.0f;
|
||||||
|
result.m5 = 2.0f/tb;
|
||||||
|
result.m6 = 0.0f;
|
||||||
|
result.m7 = 0.0f;
|
||||||
|
result.m8 = 0.0f;
|
||||||
|
result.m9 = 0.0f;
|
||||||
|
result.m10 = -2.0f/far_near;
|
||||||
|
result.m11 = 0.0f;
|
||||||
|
result.m12 = -((float)left + (float)right)/rl;
|
||||||
|
result.m13 = -((float)top + (float)bottom)/tb;
|
||||||
|
result.m14 = -((float)farPlane + (float)nearPlane)/far_near;
|
||||||
|
result.m15 = 1.0f;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Vector3 vector3Normalize(Vector3 v)
|
||||||
|
{
|
||||||
|
Vector3 result = v;
|
||||||
|
|
||||||
|
float length = $$sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
|
||||||
|
if (length != 0.0f)
|
||||||
|
{
|
||||||
|
float ilength = 1.0f/length;
|
||||||
|
|
||||||
|
result.x *= ilength;
|
||||||
|
result.y *= ilength;
|
||||||
|
result.z *= ilength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Vector3 vector3Subtract(Vector3 v1, Vector3 v2)
|
||||||
|
{
|
||||||
|
Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn Ray getScreenToWorldPointWithZDistance(Vector2 position, Camera camera, int screenWidth, int screenHeight, float zDistance)
|
||||||
|
{
|
||||||
|
Ray ray = { {0,0,0}, {0,0,0} };
|
||||||
|
float x = (2.0f*position.x)/(float)screenWidth - 1.0f;
|
||||||
|
float y = 1.0f - (2.0f*position.y)/(float)screenHeight;
|
||||||
|
float z = 1.0f;
|
||||||
|
|
||||||
|
// Store values in a vector
|
||||||
|
Vector3 deviceCoords = { x, y, z };
|
||||||
|
|
||||||
|
// Calculate view matrix from camera look at
|
||||||
|
Matrix matView = rl::getCameraMatrix(camera);
|
||||||
|
|
||||||
|
Matrix matProj = MATRIX_IDENTITY;
|
||||||
|
|
||||||
|
if (camera.projection == CameraProjection.PERSPECTIVE)
|
||||||
|
{
|
||||||
|
// Calculate projection matrix from perspective
|
||||||
|
matProj = matrixPerspective((double)(camera.fovy*rl::DEG2RAD), ((double)screenWidth/(double)screenHeight), 0.01f, zDistance);
|
||||||
|
}
|
||||||
|
else if (camera.projection == CameraProjection.ORTHOGRAPHIC)
|
||||||
|
{
|
||||||
|
double aspect = (double)screenWidth/(double)screenHeight;
|
||||||
|
double top = camera.fovy/2.0;
|
||||||
|
double right = top*aspect;
|
||||||
|
|
||||||
|
// Calculate projection matrix from orthographic
|
||||||
|
matProj = matrixOrtho(-right, right, -top, top, 0.01, 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unproject far/near points
|
||||||
|
Vector3 nearPoint = vector3Unproject({ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView);
|
||||||
|
Vector3 farPoint = vector3Unproject({ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
|
||||||
|
|
||||||
|
// Calculate normalized direction vector
|
||||||
|
Vector3 direction = vector3Normalize(vector3Subtract(farPoint, nearPoint));
|
||||||
|
|
||||||
|
ray.position = farPoint;
|
||||||
|
|
||||||
|
// Apply calculated vectors to ray
|
||||||
|
ray.direction = direction;
|
||||||
|
|
||||||
|
return ray;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Dimensions raylibMeasureText(ClayString *text, TextElementConfig *config)
|
||||||
|
{
|
||||||
|
// Measure string size for Font
|
||||||
|
Dimensions textSize = { 0, 0 };
|
||||||
|
|
||||||
|
float maxTextWidth = 0.0f;
|
||||||
|
float lineTextWidth = 0;
|
||||||
|
|
||||||
|
float textHeight = config.fontSize;
|
||||||
|
Font fontToUse = raylibFonts[config.fontId].font;
|
||||||
|
float scaleFactor = config.fontSize/(float)fontToUse.baseSize;
|
||||||
|
|
||||||
|
for (int i = 0; i < text.length; ++i)
|
||||||
|
{
|
||||||
|
if (text.chars[i] == '\n') {
|
||||||
|
maxTextWidth = $$max(maxTextWidth, lineTextWidth);
|
||||||
|
lineTextWidth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int index = text.chars[i] - 32;
|
||||||
|
if (fontToUse.glyphs[index].advanceX != 0) {lineTextWidth += fontToUse.glyphs[index].advanceX;}
|
||||||
|
else {lineTextWidth += (fontToUse.recs[index].width + fontToUse.glyphs[index].offsetX);}
|
||||||
|
}
|
||||||
|
|
||||||
|
maxTextWidth = $$max(maxTextWidth, lineTextWidth);
|
||||||
|
|
||||||
|
textSize.width = maxTextWidth * scaleFactor;
|
||||||
|
textSize.height = textHeight;
|
||||||
|
|
||||||
|
return textSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void raylibRender(RenderCommandArray renderCommands)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < renderCommands.length; j++)
|
||||||
|
{
|
||||||
|
RenderCommand *renderCommand = renderCommands.get(j);
|
||||||
|
ClayBoundingBox boundingBox = renderCommand.boundingBox;
|
||||||
|
switch (renderCommand.commandType)
|
||||||
|
{
|
||||||
|
case RenderCommandType.TEXT: {
|
||||||
|
// Raylib uses standard C strings so isn't compatible with cheap slices, we need to clone the string to append null terminator
|
||||||
|
ClayString text = renderCommand.text;
|
||||||
|
ZString cloned = (ZString)malloc((ulong)text.length + 1);
|
||||||
|
$$memcpy(cloned, text.chars, (isz)text.length, false, (isz)0, (isz)0);
|
||||||
|
cloned[text.length] = '\0';
|
||||||
|
Font fontToUse = raylibFonts[renderCommand.config.textElementConfig.fontId].font;
|
||||||
|
rl::drawTextEx(fontToUse, cloned, {boundingBox.x, boundingBox.y}, (float)renderCommand.config.textElementConfig.fontSize, (float)renderCommand.config.textElementConfig.letterSpacing, clayToRaylibColor(renderCommand.config.textElementConfig.textColor));
|
||||||
|
free(cloned);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RenderCommandType.IMAGE: {
|
||||||
|
Texture2D imageTexture = *(Texture2D *)renderCommand.config.imageElementConfig.imageData;
|
||||||
|
rl::drawTextureEx(
|
||||||
|
imageTexture,
|
||||||
|
{boundingBox.x, boundingBox.y},
|
||||||
|
0,
|
||||||
|
boundingBox.width / (float)imageTexture.width,
|
||||||
|
rl::WHITE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RenderCommandType.SCISSOR_START: {
|
||||||
|
rl::beginScissorMode((int)$$round(boundingBox.x), (int)$$round(boundingBox.y), (int)$$round(boundingBox.width), (int)$$round(boundingBox.height));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RenderCommandType.SCISSOR_END: {
|
||||||
|
rl::endScissorMode();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RenderCommandType.RECTANGLE: {
|
||||||
|
RectangleElementConfig *config = renderCommand.config.rectangleElementConfig;
|
||||||
|
if (config.cornerRadius.topLeft > 0) {
|
||||||
|
float radius = (config.cornerRadius.topLeft * 2) / (float)(boundingBox.width > boundingBox.height ? boundingBox.height : boundingBox.width);
|
||||||
|
rl::drawRectangleRounded({ boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height }, radius, 8, clayToRaylibColor(config.color));
|
||||||
|
} else {
|
||||||
|
rl::drawRectangle((int)$$round(boundingBox.x), (int)$$round(boundingBox.y), (int)$$round(boundingBox.width), (int)$$round(boundingBox.height), clayToRaylibColor(config.color));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RenderCommandType.BORDER: {
|
||||||
|
BorderElementConfig *config = renderCommand.config.borderElementConfig;
|
||||||
|
// Left border
|
||||||
|
if (config.left.width > 0) {
|
||||||
|
rl::drawRectangle((int)$$round(boundingBox.x), (int)$$round(boundingBox.y + config.cornerRadius.topLeft), (int)config.left.width, (int)$$round(boundingBox.height - config.cornerRadius.topLeft - config.cornerRadius.bottomLeft), clayToRaylibColor(config.left.color));
|
||||||
|
}
|
||||||
|
// Right border
|
||||||
|
if (config.right.width > 0) {
|
||||||
|
rl::drawRectangle((int)$$round(boundingBox.x + boundingBox.width - config.right.width), (int)$$round(boundingBox.y + config.cornerRadius.topRight), (int)config.right.width, (int)$$round(boundingBox.height - config.cornerRadius.topRight - config.cornerRadius.bottomRight), clayToRaylibColor(config.right.color));
|
||||||
|
}
|
||||||
|
// Top border
|
||||||
|
if (config.top.width > 0) {
|
||||||
|
rl::drawRectangle((int)$$round(boundingBox.x + config.cornerRadius.topLeft), (int)$$round(boundingBox.y), (int)$$round(boundingBox.width - config.cornerRadius.topLeft - config.cornerRadius.topRight), (int)config.top.width, clayToRaylibColor(config.top.color));
|
||||||
|
}
|
||||||
|
// Bottom border
|
||||||
|
if (config.bottom.width > 0) {
|
||||||
|
rl::drawRectangle((int)$$round(boundingBox.x + config.cornerRadius.bottomLeft), (int)$$round(boundingBox.y + boundingBox.height - config.bottom.width), (int)$$round(boundingBox.width - config.cornerRadius.bottomLeft - config.cornerRadius.bottomRight), (int)config.bottom.width, clayToRaylibColor(config.bottom.color));
|
||||||
|
}
|
||||||
|
if (config.cornerRadius.topLeft > 0) {
|
||||||
|
rl::drawRing({ $$round(boundingBox.x + config.cornerRadius.topLeft), $$round(boundingBox.y + config.cornerRadius.topLeft) }, $$round(config.cornerRadius.topLeft - config.top.width), config.cornerRadius.topLeft, 180, 270, 10, clayToRaylibColor(config.top.color));
|
||||||
|
}
|
||||||
|
if (config.cornerRadius.topRight > 0) {
|
||||||
|
rl::drawRing({ $$round(boundingBox.x + boundingBox.width - config.cornerRadius.topRight), $$round(boundingBox.y + config.cornerRadius.topRight) }, $$round(config.cornerRadius.topRight - config.top.width), config.cornerRadius.topRight, 270, 360, 10, clayToRaylibColor(config.top.color));
|
||||||
|
}
|
||||||
|
if (config.cornerRadius.bottomLeft > 0) {
|
||||||
|
rl::drawRing({ $$round(boundingBox.x + config.cornerRadius.bottomLeft), $$round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomLeft) }, $$round(config.cornerRadius.bottomLeft - config.top.width), config.cornerRadius.bottomLeft, 90, 180, 10, clayToRaylibColor(config.bottom.color));
|
||||||
|
}
|
||||||
|
if (config.cornerRadius.bottomRight > 0) {
|
||||||
|
rl::drawRing({ $$round(boundingBox.x + boundingBox.width - config.cornerRadius.bottomRight), $$round(boundingBox.y + boundingBox.height - config.cornerRadius.bottomRight) }, $$round(config.cornerRadius.bottomRight - config.bottom.width), config.cornerRadius.bottomRight, 0.1, 90, 10, clayToRaylibColor(config.bottom.color));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RenderCommandType.CUSTOM: {
|
||||||
|
CustomLayoutElement *customElement = (CustomLayoutElement *)renderCommand.config.customElementConfig.customData;
|
||||||
|
if (!customElement) continue;
|
||||||
|
switch (customElement.type) {
|
||||||
|
case CustomLayoutElementType.MODEL_3D: {
|
||||||
|
ClayBoundingBox rootBox = renderCommands.data[0].boundingBox;
|
||||||
|
float scaleValue = $$min($$min(1f, 768f / rootBox.height) * $$max(1f, rootBox.width / 1024f), 1.5f);
|
||||||
|
Ray positionRay = getScreenToWorldPointWithZDistance({ renderCommand.boundingBox.x + renderCommand.boundingBox.width / 2, renderCommand.boundingBox.y + (renderCommand.boundingBox.height / 2) + 20 }, raylibCamera, (int)$$round(rootBox.width), (int)$$round(rootBox.height), 140);
|
||||||
|
rl::beginMode3D(raylibCamera);
|
||||||
|
rl::drawModel(customElement.element.model.model, positionRay.position, customElement.element.model.scale * scaleValue, rl::WHITE); // Draw 3d model with texture
|
||||||
|
rl::endMode3D();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// std::io::printfn("ERROR: unhandled render command."); TODO: maybe make a workout for this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
478
bindings/c3/source/clay.c3
Normal file
478
bindings/c3/source/clay.c3
Normal file
@ -0,0 +1,478 @@
|
|||||||
|
module clay;
|
||||||
|
|
||||||
|
import clay::carray;
|
||||||
|
|
||||||
|
macro @clay(...; @body()) @builtin
|
||||||
|
{
|
||||||
|
clay::openElement();
|
||||||
|
$for (var $i = 0; $i < $vacount; $i++)
|
||||||
|
$vaexpr[$i]; // If you get an error here consisder the @body[...]() macros
|
||||||
|
$endfor
|
||||||
|
clay::elementPostConfiguration();
|
||||||
|
@body();
|
||||||
|
clay::closeElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
macro text(String text, TextElementConfig *config) { clay::openTextElement({text.len, text}, config); }
|
||||||
|
|
||||||
|
<*Provides you conditional calls (eg #booleanCondition ? #doA : 0) within the condifuration of @clay(...)*>
|
||||||
|
macro @bodyIf(#condition, #ifRes) { if (#condition) { #ifRes; } }
|
||||||
|
|
||||||
|
<*Provides you conditional calls (eg #booleanCondition ? #doA : #doB) within the condifuration of @clay(...)*>
|
||||||
|
macro @bodyIfElse(#condition, #ifRes, #elseRes) { if (#condition) { #ifRes; } else { #elseRes; } }
|
||||||
|
|
||||||
|
<*attaches a RectangleElementConfig to the clay element when called within @clay(...)*>
|
||||||
|
macro rectangle(RectangleElementConfig config) { clay::attachElementConfig({ .rectangleElementConfig = clay::storeRectangleElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_RECTANGLE ); }
|
||||||
|
|
||||||
|
<*attaches a LayoutConfig to the clay element when called within @clay(...)*>
|
||||||
|
macro layout(LayoutConfig config) { clay::attachLayoutConfig( clay::storeLayoutConfig(config) ); }
|
||||||
|
|
||||||
|
<*attaches a LayoutConfig to the clay element when called within @clay(...)*>
|
||||||
|
macro scroll(ScrollElementConfig config) { clay::attachElementConfig({ .scrollElementConfig = clay::storeScrollElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER ); }
|
||||||
|
|
||||||
|
<*attaches a FloatingElementConfig to the clay element when called within @clay(...)*>
|
||||||
|
macro floating(FloatingElementConfig config) { clay::attachElementConfig({ .floatingElementConfig = clay::storeFloatingElementConfig(config) }, clay::ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER ); }
|
||||||
|
|
||||||
|
<*attaches a BorderElementConfig to the clay element when called within @clay(...)*>
|
||||||
|
macro @borderRadiusUni(uint #width, ClayColor #color, float #cornerRadius = 0) { clay::attachElementConfig({ .borderElementConfig = clay::storeBorderElementConfig({ .left = { #width, #color }, .right = { #width, #color }, .top = { #width, #color }, .bottom = { #width, #color }, .#cornerRadius = {#cornerRadius, #cornerRadius, #cornerRadius, #cornerRadius}})}, clay::ELEMENT_CONFIG_TYPE_BORDER_CONTAINER); }
|
||||||
|
|
||||||
|
macro id(String idString) { clay::attachId(clay::hashString({idString.len, idString}, 0, 0)); }
|
||||||
|
|
||||||
|
macro TextElementConfig* textConfig(TextElementConfig config) { return clay::storeTextElementConfig(config); }
|
||||||
|
|
||||||
|
macro SizingAxis sizingFit(float min = 0, float max = float.max) { return { .size.minMax = {min, max}, .type = SizingType.FIT }; }
|
||||||
|
|
||||||
|
macro SizingAxis sizingGrow() { return { .size.minMax = {0, 0}, .type = SizingType.GROW }; }
|
||||||
|
|
||||||
|
macro SizingAxis sizingFixed(float pixels) { return { .size.minMax = {pixels, pixels}, .type = SizingType.FIXED }; }
|
||||||
|
|
||||||
|
macro SizingAxis sizingPercent(float percent) { return { .size.percent = percent, .type = SizingType.PERCENT }; }
|
||||||
|
|
||||||
|
macro Padding paddingUni(ushort uniform) { return {uniform, uniform, uniform, uniform}; }
|
||||||
|
|
||||||
|
macro Padding padding(ushort horizontal, ushort vertical) { return {horizontal, horizontal, vertical, vertical}; }
|
||||||
|
|
||||||
|
macro CornerRadius cornerRadiusUni(float uniform) { return {uniform, uniform, uniform, uniform}; }
|
||||||
|
|
||||||
|
macro SizingAxis sizingFitCT(float $min = 0, float $max = float.max) { return { .size.minMax = {$min, $max}, .type = SizingType.FIT }; }
|
||||||
|
|
||||||
|
macro SizingAxis sizingFixedCT(float $pixels) { return { .size.minMax = {$pixels, $pixels}, .type = SizingType.FIXED }; }
|
||||||
|
|
||||||
|
macro SizingAxis sizingPercentCT(float $percent) { return { .size.percent = $percent, .type = SizingType.PERCENT }; }
|
||||||
|
|
||||||
|
macro Padding paddingCT(ushort $a, ushort $b, ushort $c, ushort $d) { return { $a, $b, $c, $d }; }
|
||||||
|
|
||||||
|
macro CornerRadius @cornerRadiusUniCT(float #uniform) { return {#uniform, #uniform, #uniform, #uniform}; }
|
||||||
|
|
||||||
|
struct ClayString
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
char *chars;
|
||||||
|
}
|
||||||
|
def ClayStringArray = carray::Array(<ClayString>) @private;
|
||||||
|
|
||||||
|
struct Arena
|
||||||
|
{
|
||||||
|
uint128 nextAllocation;
|
||||||
|
uint128 capacity;
|
||||||
|
char *memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Dimensions
|
||||||
|
{
|
||||||
|
float width, height;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ClayVector2
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ClayColor
|
||||||
|
{
|
||||||
|
float r, g, b, a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ElementId
|
||||||
|
{
|
||||||
|
uint id;
|
||||||
|
uint offset;
|
||||||
|
uint baseId;
|
||||||
|
ClayString stringId;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CornerRadius
|
||||||
|
{
|
||||||
|
float topLeft;
|
||||||
|
float topRight;
|
||||||
|
float bottomLeft;
|
||||||
|
float bottomRight;
|
||||||
|
}
|
||||||
|
distinct ElementConfigType @private = char;
|
||||||
|
const ElementConfigType ELEMENT_CONFIG_TYPE_NONE @private = 0;
|
||||||
|
const ElementConfigType ELEMENT_CONFIG_TYPE_RECTANGLE @private = 1;
|
||||||
|
const ElementConfigType ELEMENT_CONFIG_TYPE_BORDER_CONTAINER @private = 2;
|
||||||
|
const ElementConfigType ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER @private = 4;
|
||||||
|
const ElementConfigType ELEMENT_CONFIG_TYPE_SCROLL_CONTAINER @private = 8;
|
||||||
|
const ElementConfigType ELEMENT_CONFIG_TYPE_IMAGE @private = 16;
|
||||||
|
const ElementConfigType ELEMENT_CONFIG_TYPE_TEXT @private = 32;
|
||||||
|
const ElementConfigType ELEMENT_CONFIG_TYPE_CUSTOM @private = 64;
|
||||||
|
|
||||||
|
enum LayoutDirection : char @export
|
||||||
|
{
|
||||||
|
LEFT_TO_RIGHT,
|
||||||
|
TOP_TO_BOTTOM,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AlignX : char @export
|
||||||
|
{
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
CENTER,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AlignY : char @export
|
||||||
|
{
|
||||||
|
TOP,
|
||||||
|
BOTTOM,
|
||||||
|
CENTER,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SizingType : char @export
|
||||||
|
{
|
||||||
|
FIT,
|
||||||
|
GROW,
|
||||||
|
PERCENT,
|
||||||
|
FIXED,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChildAlignment
|
||||||
|
{
|
||||||
|
AlignX x;
|
||||||
|
AlignY y;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SizingMinMax
|
||||||
|
{
|
||||||
|
float min;
|
||||||
|
float max;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SizingAxis
|
||||||
|
{
|
||||||
|
union size
|
||||||
|
{
|
||||||
|
SizingMinMax minMax;
|
||||||
|
float percent;
|
||||||
|
}
|
||||||
|
SizingType type;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Sizing
|
||||||
|
{
|
||||||
|
SizingAxis width;
|
||||||
|
SizingAxis height;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Padding
|
||||||
|
{
|
||||||
|
ushort left;
|
||||||
|
ushort right;
|
||||||
|
ushort top;
|
||||||
|
ushort bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LayoutConfig
|
||||||
|
{
|
||||||
|
Sizing sizing;
|
||||||
|
Padding padding;
|
||||||
|
ushort childGap;
|
||||||
|
ChildAlignment childAlignment;
|
||||||
|
LayoutDirection layoutDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RectangleElementConfig
|
||||||
|
{
|
||||||
|
ClayColor color;
|
||||||
|
CornerRadius cornerRadius;
|
||||||
|
// #ifdef CLAY_EXTEND_CONFIG_RECTANGLE
|
||||||
|
// CLAY_EXTEND_CONFIG_RECTANGLE
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WrapMode @export
|
||||||
|
{
|
||||||
|
WORDS,
|
||||||
|
NEWLINES,
|
||||||
|
NONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TextElementConfig
|
||||||
|
{
|
||||||
|
ClayColor textColor;
|
||||||
|
ushort fontId;
|
||||||
|
ushort fontSize;
|
||||||
|
ushort letterSpacing;
|
||||||
|
ushort lineHeight;
|
||||||
|
WrapMode wrapMode;
|
||||||
|
// #ifdef CLAY_EXTEND_CONFIG_TEXT
|
||||||
|
// CLAY_EXTEND_CONFIG_TEXT
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImageElementConfig
|
||||||
|
{
|
||||||
|
void *imageData;
|
||||||
|
Dimensions sourceDimensions;
|
||||||
|
// #ifdef CLAY_EXTEND_CONFIG_IMAGE
|
||||||
|
// CLAY_EXTEND_CONFIG_IMAGE
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AttachPoint : char @export
|
||||||
|
{
|
||||||
|
LEFT_TOP,
|
||||||
|
LEFT_CENTER,
|
||||||
|
LEFT_BOTTOM,
|
||||||
|
CENTER_TOP,
|
||||||
|
CENTER_CENTER,
|
||||||
|
CENTER_BOTTOM,
|
||||||
|
RIGHT_TOP,
|
||||||
|
RIGHT_CENTER,
|
||||||
|
RIGHT_BOTTOM,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FloatingAttachPoints
|
||||||
|
{
|
||||||
|
AttachPoint element;
|
||||||
|
AttachPoint parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PointerCaptureMode @export
|
||||||
|
{
|
||||||
|
CAPTURE,
|
||||||
|
// MODE_PASSTHROUGH,
|
||||||
|
PARENT,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FloatingElementConfig
|
||||||
|
{
|
||||||
|
ClayVector2 offset;
|
||||||
|
Dimensions expand;
|
||||||
|
ushort zIndex;
|
||||||
|
uint parentId;
|
||||||
|
FloatingAttachPoints attachment;
|
||||||
|
PointerCaptureMode pointerCaptureMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct CustomElementConfig
|
||||||
|
{
|
||||||
|
void *customData;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ScrollElementConfig
|
||||||
|
{
|
||||||
|
bool horizontal;
|
||||||
|
bool vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Border
|
||||||
|
struct Border
|
||||||
|
{
|
||||||
|
uint width;
|
||||||
|
ClayColor color;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BorderElementConfig
|
||||||
|
{
|
||||||
|
Border left;
|
||||||
|
Border right;
|
||||||
|
Border top;
|
||||||
|
Border bottom;
|
||||||
|
Border betweenChildren;
|
||||||
|
CornerRadius cornerRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
union ElementConfigUnion
|
||||||
|
{
|
||||||
|
RectangleElementConfig *rectangleElementConfig;
|
||||||
|
TextElementConfig *textElementConfig;
|
||||||
|
ImageElementConfig *imageElementConfig;
|
||||||
|
FloatingElementConfig *floatingElementConfig;
|
||||||
|
CustomElementConfig *customElementConfig;
|
||||||
|
ScrollElementConfig *scrollElementConfig;
|
||||||
|
BorderElementConfig *borderElementConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ElementConfig
|
||||||
|
{
|
||||||
|
ElementConfigType type;
|
||||||
|
ElementConfigUnion config;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ClayBoundingBox
|
||||||
|
{
|
||||||
|
float x, y, width, height;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RenderCommandType : char @export
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
RECTANGLE,
|
||||||
|
BORDER,
|
||||||
|
TEXT,
|
||||||
|
IMAGE,
|
||||||
|
SCISSOR_START,
|
||||||
|
SCISSOR_END,
|
||||||
|
CUSTOM,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RenderCommand
|
||||||
|
{
|
||||||
|
ClayBoundingBox boundingBox;
|
||||||
|
ElementConfigUnion config;
|
||||||
|
ClayString text;
|
||||||
|
uint id;
|
||||||
|
RenderCommandType commandType;
|
||||||
|
}
|
||||||
|
def RenderCommandArray = carray::Array(<RenderCommand>);
|
||||||
|
|
||||||
|
struct ScrollContainerData
|
||||||
|
{
|
||||||
|
// Note: This is a pointer to the real internal scroll position, mutating it may cause a change in final layout.
|
||||||
|
// Intended for use with external functionality that modifies scroll position, such as scroll bars or auto scrolling.
|
||||||
|
ClayVector2 *scrollPosition;
|
||||||
|
Dimensions scrollContainerDimensions;
|
||||||
|
Dimensions contentDimensions;
|
||||||
|
ScrollElementConfig config;
|
||||||
|
// Indicates whether an actual scroll container matched the provided ID or if the default struct was returned.
|
||||||
|
bool found;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ElementData
|
||||||
|
{
|
||||||
|
ClayBoundingBox boundingBox;
|
||||||
|
// Indicates whether an actual Element matched the provided ID or if the default struct was returned.
|
||||||
|
bool found;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PointerState @export
|
||||||
|
{
|
||||||
|
PRESSED_THIS_FRAME,
|
||||||
|
PRESSED,
|
||||||
|
RELEASED_THIS_FRAME,
|
||||||
|
RELEASED,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PointerData
|
||||||
|
{
|
||||||
|
ClayVector2 position;
|
||||||
|
PointerState state;
|
||||||
|
}
|
||||||
|
|
||||||
|
def OnHoverEvent = fn void(ElementId elementId, PointerData pointerData, iptr userData);
|
||||||
|
def MeasureTextFunc = fn Dimensions(ClayString *text, TextElementConfig *config);
|
||||||
|
def QueryScrollOffsetFunc = fn ClayVector2(uint elementId);
|
||||||
|
|
||||||
|
enum ErrorType @export
|
||||||
|
{
|
||||||
|
TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED,
|
||||||
|
ARENA_CAPACITY_EXCEEDED,
|
||||||
|
ELEMENTS_CAPACITY_EXCEEDED,
|
||||||
|
TEXT_MEASUREMENT_CAPACITY_EXCEEDED,
|
||||||
|
DUPLICATE_ID,
|
||||||
|
FLOATING_CONTAINER_PARENT_NOT_FOUND,
|
||||||
|
INTERNAL_ERROR,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ErrorData
|
||||||
|
{
|
||||||
|
ErrorType errorType;
|
||||||
|
ClayString errorText;
|
||||||
|
uint128 userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
def ErrorHandleFunc = fn void(ErrorData errorText);
|
||||||
|
|
||||||
|
struct ErrorHandler
|
||||||
|
{
|
||||||
|
ErrorHandleFunc errorHandler;
|
||||||
|
uint128 userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
distinct Context = void; // I'm not doing all that again
|
||||||
|
|
||||||
|
// =====================
|
||||||
|
// ===== FUNCTIONS =====
|
||||||
|
// =====================
|
||||||
|
|
||||||
|
// ===== Public Clay API C3 Functions (String replacement) ===== // TODO @export and @wasm can be ignored rn
|
||||||
|
// I haven't been able to get c3c and c compilations to work together for wasm32 or a c3 library
|
||||||
|
fn ElementId getElementIdWithIndex(String idString, uint index) @export @inline
|
||||||
|
{ return __getElementIdWithIndex({idString.len, idString}, (uint)index); }
|
||||||
|
fn ElementId getElementId(String idString) @export @inline
|
||||||
|
{ return __getElementId({idString.len, idString}); }
|
||||||
|
|
||||||
|
// ===== Public Clay API Functions =====
|
||||||
|
extern fn uint minMemorySize() @extern("Clay_MinMemorySize") @wasm @export;
|
||||||
|
extern fn Arena createArena(uint capacity, void* offset) @extern("Clay_CreateArenaWithCapacityAndMemory") @wasm @export;
|
||||||
|
extern fn void setPointerState(ClayVector2 position, bool pointerDown) @extern("Clay_SetPointerState") @export;
|
||||||
|
extern fn Context* initialize(Arena arena, Dimensions layoutDimensions, ErrorHandler errorHandler) @extern("Clay_Initialize") @wasm @export;
|
||||||
|
extern fn Context* getCurrentContext() @extern("Clay_GetCurrentContext") @export;
|
||||||
|
extern fn void setCurrentContext(Context* context) @extern("Clay_SetCurrentContext") @export;
|
||||||
|
extern fn void updateScrollContainer(bool enableDragScrolling, ClayVector2 scrollDelta, float deltaTime) @extern("Clay_UpdateScrollContainers") @export;
|
||||||
|
extern fn void setLayoutDimensions (Dimensions dimensions) @extern("Clay_SetLayoutDimensions") @export;
|
||||||
|
extern fn ElementData getElementData(ElementId id) @extern("Clay_GetElementData") @export;
|
||||||
|
extern fn bool hovered() @extern("Clay_Hovered") @export;
|
||||||
|
extern fn void onHover(OnHoverEvent onHover, iptr userData) @extern("Clay_OnHover") @export;
|
||||||
|
extern fn bool pointerOver(ElementId elementId) @extern("Clay_PointerOver") @wasm @export;
|
||||||
|
extern fn ScrollContainerData getScrollContainerData(ElementId id) @extern("Clay_GetScrollContainerData") @export;
|
||||||
|
extern fn void setMeasureTextFunction(MeasureTextFunc measureText) @extern("Clay_SetMeasureTextFunction") @export;
|
||||||
|
extern fn void setQueryScrollOffsetFunction(QueryScrollOffsetFunc queryScrollOffset) @extern("Clay_SetQueryScrollOffsetFunction") @export;
|
||||||
|
extern fn RenderCommand * RenderCommandArray.get(RenderCommandArray* array, int index) @extern("Clay_RenderCommandArray_Get") @export;
|
||||||
|
extern fn void setDebugModeEnabled(bool enabled) @extern("Clay_SetDebugModeEnabled") @export;
|
||||||
|
extern fn bool isDebugModeEnabled() @extern("Clay_IsDebugModeEnabled") @export;
|
||||||
|
extern fn void setCullingEnabled(bool enabled) @extern("Clay_SetCullingEnabled") @export;
|
||||||
|
extern fn int getMaxMeasuredTextCachedWordCount() @extern("Clay_GetMaxElementCount") @export;
|
||||||
|
extern fn void setMaxElementCount(int maxElementCount) @extern("Clay_SetMaxElementCount") @export;
|
||||||
|
extern fn int getMaxElementCount() @extern("Clay_GetMaxMeasureTextCacheWordCount") @export;
|
||||||
|
extern fn void setMaxMeasureTextCacheWordCount(int maxMeasureTextCacheWordCount) @extern("Clay_SetMaxMeasureTextCacheWordCount") @export;
|
||||||
|
extern fn void resetMeasureTextCache() @extern("Clay_ResetMeasureTextCache") @export;
|
||||||
|
extern fn void beginLayout() @extern("Clay_BeginLayout") @export;
|
||||||
|
extern fn RenderCommandArray endLayout() @extern("Clay_EndLayout") @export;
|
||||||
|
|
||||||
|
// ===== (NEW) Internal Clay API Functions (String replacement) =====
|
||||||
|
extern fn ElementId __getElementIdWithIndex(ClayString idString, uint index) @extern("Clay_GetElementIdWithIndex") @export @private;
|
||||||
|
extern fn ElementId __getElementId(ClayString idString) @extern("Clay_GetElementId") @export @private;
|
||||||
|
|
||||||
|
// ===== Internal Clay API Functions =====
|
||||||
|
extern fn void openElement() @extern ("Clay__OpenElement") @export @private;
|
||||||
|
extern fn void closeElement() @extern("Clay__CloseElement") @export @private;
|
||||||
|
extern fn void openTextElement(ClayString text, TextElementConfig *textConfig) @extern("Clay__OpenTextElement") @export @private;
|
||||||
|
extern fn void elementPostConfiguration() @extern("Clay__ElementPostConfiguration") @export @private;
|
||||||
|
extern fn LayoutConfig * storeLayoutConfig(LayoutConfig config) @extern("Clay__StoreLayoutConfig") @export @private;
|
||||||
|
extern fn void attachId(ElementId id) @extern("Clay__AttachId") @export @private;
|
||||||
|
extern fn void attachLayoutConfig(LayoutConfig *config) @extern("Clay__AttachLayoutConfig") @export @private;
|
||||||
|
extern fn void attachElementConfig(ElementConfigUnion config, ElementConfigType type) @extern("Clay__AttachElementConfig") @export @private;
|
||||||
|
extern fn RectangleElementConfig * storeRectangleElementConfig(RectangleElementConfig config) @extern("Clay__StoreRectangleElementConfig") @export @private;
|
||||||
|
extern fn TextElementConfig * storeTextElementConfig(TextElementConfig config) @extern("Clay__StoreTextElementConfig") @export @private;
|
||||||
|
extern fn ImageElementConfig * storeImageElementConfig(ImageElementConfig config) @extern("Clay__StoreImageElementConfig") @export @private;
|
||||||
|
extern fn FloatingElementConfig * storeFloatingElementConfig(FloatingElementConfig config) @extern("Clay__StoreFloatingElementConfig") @export @private;
|
||||||
|
extern fn CustomElementConfig * storeCustomElementConfig(CustomElementConfig config) @extern("Clay__StoreCustomElementConfig") @export @private;
|
||||||
|
extern fn ScrollElementConfig * storeScrollElementConfig(ScrollElementConfig config) @extern("Clay__StoreScrollElementConfig") @export @private;
|
||||||
|
extern fn BorderElementConfig * storeBorderElementConfig(BorderElementConfig config) @extern("Clay__StoreBorderElementConfig") @export @private;
|
||||||
|
extern fn ElementId hashString(ClayString key, uint offset, uint seed) @extern("Clay__HashString") @export @private;
|
||||||
|
extern fn uint getParentElementId() @extern("Clay__GetParentElementId") @export @private;
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// ===== An internal module for wrapping Struct Array's defined in Clay =====
|
||||||
|
// ==========================================================================
|
||||||
|
module clay::carray(<ElementType>);
|
||||||
|
|
||||||
|
struct Array {
|
||||||
|
int capacity;
|
||||||
|
int length;
|
||||||
|
ElementType *data;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user