Finished first version of the bindings with working demo !!

This commit is contained in:
Stowy 2025-01-02 23:19:31 +01:00
parent b7e1d69ca6
commit 672927d387
7 changed files with 236 additions and 84 deletions

View File

@ -19,18 +19,20 @@ raylib_measure_text :: (text: *Clay.String, config: *Clay.TextElementConfig) ->
text_height := cast(float)config.fontSize;
font_to_use := g_raylib_fonts[config.fontId].font;
for 0..text.length - 1 {
if text.chars[it] == #char "\n" {
max_text_width = c_max(max_text_width, line_text_width);
line_text_width = 0;
continue;
}
if text.length > 0 {
for 0..(text.length - 1) {
if text.chars[it] == #char "\n" {
max_text_width = c_max(max_text_width, line_text_width);
line_text_width = 0;
continue;
}
index := cast(s32) text.chars[it] - 32;
if font_to_use.glyphs[index].advanceX != 0 {
line_text_width += cast(float) font_to_use.glyphs[index].advanceX;
} else {
line_text_width += (font_to_use.recs[index].width + cast(float) font_to_use.glyphs[index].offsetX);
index := cast(s32, text.chars[it]) - 32;
if font_to_use.glyphs[index].advanceX != 0 {
line_text_width += cast(float) font_to_use.glyphs[index].advanceX;
} else {
line_text_width += (font_to_use.recs[index].width + cast(float) font_to_use.glyphs[index].offsetX);
}
}
}

View File

@ -3,6 +3,8 @@ using Basic :: #import "Basic";
Clay :: #import,file "../../module.jai";
Raylib :: #import "raylib-jai";
for_expansion :: Clay.for_expansion;;
#load "clay_renderer_raylib.jai";
FONT_ID_BODY_16 :: 0;
@ -28,14 +30,60 @@ to_jai_string :: (str: Clay.String) -> string {
return .{data = str.chars, count = cast(s64, str.length)};
}
// handle_sidebar_interaction :: (
// element_id: Clay.ElementId,
// pointer_data: Clay.PointerData,
// user_data: s64
// ) #c_call {
// // If this button was clicked
// if pointer_data.state == .PRESSED_THIS_FRAME {
// selected_document_index = user_data;
// }
// }
handle_clay_errors :: (error_data: Clay.ErrorData) #c_call {
push_context {
log_error("Clay Error : %", to_jai_string(error_data.errorText));
log_error(
"Clay Error [%]: % | %",
error_data.errorType,
to_jai_string(error_data.errorText),
error_data.userData
);
}
}
render_header_button :: (text: string) {
for Clay.Element(
Clay.Layout(.{padding = .{16, 8}}),
Clay.Rectangle(.{
color = .{140, 140, 140, 255},
cornerRadius = .{5, 5, 5, 5},
})
) {
Clay.Text(text, Clay.TextConfig(.{
fontId = FONT_ID_BODY_16,
fontSize = 16,
textColor = COLOR_WHITE,
}));
}
}
render_dropdown_menu_item :: (text: string) {
for Clay.Element(
Clay.Layout(.{padding = .{16, 16}})
) {
Clay.Text(text, Clay.TextConfig(.{
fontId = FONT_ID_BODY_16,
fontSize = 16,
textColor = COLOR_WHITE,
}));
}
}
selected_document_index : int = 0;
main :: () {
flags := Raylib.ConfigFlags.WINDOW_RESIZABLE | .WINDOW_HIGHDPI | .MSAA_4X_HINT | .VSYNC_HINT;
flags := Raylib.ConfigFlags.WINDOW_RESIZABLE | .MSAA_4X_HINT | .VSYNC_HINT;
raylib_initialize(1024, 768, "Introducing Clay Demo", flags);
clay_required_memory := Clay.MinMemorySize();
@ -76,7 +124,7 @@ main :: () {
};
Clay.BeginLayout();
Clay.UI(
for Clay.Element(
Clay.ID("OuterContainer"),
Clay.Rectangle(.{color = .{43, 41, 51, 255}}),
Clay.Layout(.{
@ -85,8 +133,8 @@ main :: () {
padding = .{16, 16},
childGap = 16,
}),
children = #code {
Clay.UI(
) {
for Clay.Element(
Clay.ID("HeaderBar"),
Clay.Rectangle(content_background_config),
Clay.Layout(.{
@ -100,33 +148,148 @@ main :: () {
y = .CENTER,
}
}),
children = #code {
Clay.UI(
) {
for Clay.Element(
Clay.ID("FileButton"),
Clay.Layout(.{padding = .{16, 8}}),
Clay.Rectangle(.{
color = .{140, 140, 140, 255},
cornerRadius = .{5, 5, 5, 5},
}),
children = #code {
) {
Clay.Text("File", Clay.TextConfig(.{
fontId = FONT_ID_BODY_16,
fontSize = 16,
textColor = Clay.Color.{255, 255, 255, 255},
fontId = FONT_ID_BODY_16,
fontSize = 16,
textColor = COLOR_WHITE,
}));
file_menu_visible := Clay.PointerOver(Clay.GetElementId("FileButton")) ||
Clay.PointerOver(Clay.GetElementId("FileMenu"));
Clay.PointerOver(Clay.GetElementId("FileMenu"));
if file_menu_visible {
for Clay.Element(
Clay.ID("FileMenu"),
Clay.Floating(.{attachment = .{parent = .LEFT_BOTTOM}}),
Clay.Layout(.{padding = .{0, 8}})
) {
for Clay.Element(
Clay.Layout(.{
layoutDirection=.TOP_TO_BOTTOM,
sizing = .{width = Clay.SizingFixed(200)}
}),
Clay.Rectangle(.{
color = .{40, 40, 40, 255},
cornerRadius = .{8, 8, 8, 8}
})
) {
// Render dropdown items here
render_dropdown_menu_item("New");
render_dropdown_menu_item("Open");
render_dropdown_menu_item("Close");
}
}
}
}
);
}
);
// Render header buttons
render_header_button("Edit");
for Clay.Element(Clay.Layout(.{
sizing = .{Clay.SizingGrow(), Clay.SizingGrow()}})) {}
render_header_button("Upload");
render_header_button("Media");
render_header_button("Support");
}
);
for Clay.Element(
Clay.ID("LowerContent"),
Clay.Layout(.{sizing = layout_expand, childGap = 16}),
) {
for Clay.Element(
Clay.ID("Sidebar"),
Clay.Rectangle(content_background_config),
Clay.Layout(.{
layoutDirection = .TOP_TO_BOTTOM,
padding = .{16, 16},
childGap = 8,
sizing = .{
width = Clay.SizingFixed(250),
height = Clay.SizingGrow(),
}
})
) {
for document : documents {
sidebar_button_layout := Clay.LayoutConfig.{
sizing = .{width = Clay.SizingGrow()},
padding = .{16, 16},
};
if it_index == selected_document_index {
for Clay.Element(
Clay.Layout(sidebar_button_layout),
Clay.Rectangle(.{
color = .{120, 120, 120, 255},
cornerRadius = .{8, 8, 8, 8},
})
) {
Clay.Text(document.title, Clay.TextConfig(.{
fontId = FONT_ID_BODY_16,
fontSize = 20,
textColor = COLOR_WHITE,
}));
}
} else {
id := tprint("Parnets %", it_index);
is_hovered := Clay.PointerOver(Clay.GetElementId(id));
if is_hovered && Raylib.IsMouseButtonPressed(0) {
selected_document_index = it_index;
}
for Clay.Element(
Clay.ID(id)
) {
for Clay.Element(
Clay.Layout(sidebar_button_layout),
ifx is_hovered then Clay.Rectangle(.{
color = .{120, 120, 120, 120},
cornerRadius = .{8, 8, 8, 8},
}) else .{}
) {
Clay.Text(document.title, Clay.TextConfig(.{
fontId = FONT_ID_BODY_16,
fontSize = 20,
textColor = COLOR_WHITE
}));
}
}
}
}
}
for Clay.Element(
Clay.ID("MainContent"),
Clay.Rectangle(content_background_config),
Clay.Scroll(.{vertical = true}),
Clay.Layout(.{
layoutDirection = .TOP_TO_BOTTOM,
childGap = 16,
padding = .{16, 16},
sizing = layout_expand,
}),
) {
selected_document := documents[selected_document_index];
Clay.Text(selected_document.title, Clay.TextConfig(.{
fontId = FONT_ID_BODY_16,
fontSize = 24,
textColor = COLOR_WHITE,
}));
Clay.Text(selected_document.contents, Clay.TextConfig(.{
fontId = FONT_ID_BODY_16,
fontSize = 24,
textColor = COLOR_WHITE
}));
}
}
}
render_commands := Clay.EndLayout();
@ -134,6 +297,7 @@ main :: () {
Raylib.ClearBackground(Raylib.BLACK);
clay_raylib_render(render_commands);
Raylib.EndDrawing();
}
reset_temporary_storage();
}
}

View File

@ -1,21 +0,0 @@
#import "Basic";
test :: () -> bool #must #expand {
print("one\n");
`defer print("two\n");
return true;
}
main :: () {
print("ichi\n");
if test() {
print("ni\n");
if test() {
print("san\n");
}
}
print("yon\n");
}

View File

@ -2,11 +2,15 @@ AT_COMPILE_TIME :: true;
SOURCE_PATH :: "source";
// These have custom declaration in module.jai
DECLARATIONS_TO_OMIT :: string.[
// These have custom declaration in module.jai
"Clay_Vector2",
"Clay__ElementConfigType",
"Clay__AlignClay__ElementConfigType",
// These are not supported yet
"Clay_OnHover",
"Clay_Hovered",
];
#if AT_COMPILE_TIME {

View File

@ -34,13 +34,19 @@ TypedConfig :: struct {
}
make_string :: (str: string) -> String {
return .{cast(u64, str.count), str.data};
clay_string := String.{cast(u64, str.count), str.data};
return clay_string;
}
// The way of handling this is inspired by the odin bindings
UI :: (configs: ..TypedConfig, $children: Code = #code {}, $call := #caller_code) {
global_counter := 0;
for_expansion :: (configs_array: InternalElementConfigArray, body: Code, _: For_Flags) #expand {
// Jai forces the definition of these
`it_index := 0;
`it := 0;
_OpenElement();
for config : configs {
for config : configs_array.configs {
if config.type == {
case .ID;
_AttachId(config.id);
@ -56,35 +62,14 @@ UI :: (configs: ..TypedConfig, $children: Code = #code {}, $call := #caller_code
}
_ElementPostConfiguration();
#insert,scope(call) children;
#insert body;
_CloseElement();
}
// Not sure yet wich of these two methods is better
// Idealy there should be a way to mimic the style of how it's done in C
// ElementScope :: (configs: ..TypedConfig) #expand {
// _OpenElement();
// for config : configs {
// if config.type == {
// case .ID;
// _AttachId(config.id);
// case .LAYOUT;
// _AttachLayoutConfig(cast(*LayoutConfig, config.config));
// case;
// // config.config is a *void, it stores the address of the pointer that is stored in the union
// // as ElementConfigUnion is a union of structs. We can't cast pointers directly to structs,
// // we first cast the address of the *void and then dereference it.
// // Maybe there's a cast modifier to avoid this, but I don't know it (no_check and trunc didn't work).
// _AttachElementConfig(cast(*ElementConfigUnion, *config.config).*, config.type);
// }
// }
// _ElementPostConfiguration();
// `defer _CloseElement();
// }
Element :: (configs: ..TypedConfig) -> InternalElementConfigArray #expand {
return .{configs};
}
ID :: (label: string, index: u32 = 0) -> TypedConfig {
return .{type = .ID, id = _HashString(make_string(label), index, 0)};
@ -101,6 +86,14 @@ Rectangle :: (config: RectangleElementConfig) -> TypedConfig {
};
}
Floating :: (config: FloatingElementConfig) -> TypedConfig {
return .{type = .FLOATING_CONTAINER, config = _StoreFloatingElementConfig(config)};
}
Scroll :: (config: ScrollElementConfig) -> TypedConfig {
return .{type = .SCROLL_CONTAINER, config = _StoreScrollElementConfig(config)};
}
Text :: (text: string, config: *TextElementConfig) {
_OpenTextElement(make_string(text), config);
}
@ -121,12 +114,23 @@ GetElementId :: (str: string) -> ElementId {
return GetElementId(make_string(str));
}
// OnHover :: (onHoverFunction: #type (elementId: ElementId, pointerData: PointerData, userData: s64) -> void #c_call, userData: s64) -> TypedConfig {
// OnHover(onHoverFunction, userData);
// return TypedConfig.{
// type = .NONE,
// };
// }
#scope_module
Math :: #import "Math";
Compiler :: #import "Compiler";
ProgramPrint :: #import "Program_Print";
InternalElementConfigArray :: struct {
configs: [] TypedConfig;
}
#if OS == .WINDOWS {
#load "windows.jai";
} else {

View File

@ -1,7 +1,7 @@
//
// This file was auto-generated using the following command:
//
// jai generate.jai - -compile
// jai ./generate.jai - -compile
//
@ -551,8 +551,7 @@ 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";
Hovered :: () -> bool #foreign clay "Clay_Hovered";
OnHover :: (onHoverFunction: #type (elementId: ElementId, pointerData: PointerData, userData: s64) -> void #c_call, userData: s64) -> void #foreign clay "Clay_OnHover";
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";