Compare commits

...

5 commits

Author SHA1 Message Date
Ambareesh Shyam Sundar 3da3e693ad
Merge 3f2aceecd2 into fd97d8179e 2025-10-25 16:15:10 +00:00
Daniel Mayovskiy fd97d8179e
[Renderers/termbox] fixed horizontal text culling bug (#525)
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Has been cancelled
Odin Bindings Update / check_changes (push) Has been cancelled
Odin Bindings Update / build (macos-latest) (push) Has been cancelled
Odin Bindings Update / build (ubuntu-latest) (push) Has been cancelled
Odin Bindings Update / commit (push) Has been cancelled
2025-10-23 12:58:39 +11:00
Daniel Mayovskiy 7216815536
Fixed termbox2 demo build, added scroll functionality (#523) 2025-10-23 12:57:11 +11:00
Thomas Anderson 83129995f7
[Examples/official-website] updated paths in build.sh 2025-10-23 12:56:20 +11:00
Ambareesh Shyam Sundar 3f2aceecd2 Add scissor data stack to fix nested clip elements displaying incorrectly 2025-08-11 15:09:04 -07:00
5 changed files with 93 additions and 9 deletions

65
clay.h
View file

@ -1228,6 +1228,13 @@ typedef struct {
CLAY__ARRAY_DEFINE(Clay__LayoutElementTreeRoot, Clay__LayoutElementTreeRootArray) CLAY__ARRAY_DEFINE(Clay__LayoutElementTreeRoot, Clay__LayoutElementTreeRootArray)
typedef struct Clay__ScissorData {
Clay_BoundingBox boundingBox;
uint32_t id;
} Clay__ScissorData;
CLAY__ARRAY_DEFINE(Clay__ScissorData, Clay__ScissorDataArray)
struct Clay_Context { struct Clay_Context {
int32_t maxElementCount; int32_t maxElementCount;
int32_t maxMeasureTextCacheWordCount; int32_t maxMeasureTextCacheWordCount;
@ -1283,6 +1290,7 @@ struct Clay_Context {
Clay__MeasuredWordArray measuredWords; Clay__MeasuredWordArray measuredWords;
Clay__int32_tArray measuredWordsFreeList; Clay__int32_tArray measuredWordsFreeList;
Clay__int32_tArray openClipElementStack; Clay__int32_tArray openClipElementStack;
Clay__ScissorDataArray scissorDataStack;
Clay_ElementIdArray pointerOverIds; Clay_ElementIdArray pointerOverIds;
Clay__ScrollContainerDataInternalArray scrollContainerDatas; Clay__ScrollContainerDataInternalArray scrollContainerDatas;
Clay__boolArray treeNodeVisited; Clay__boolArray treeNodeVisited;
@ -2214,6 +2222,7 @@ void Clay__InitializeEphemeralMemory(Clay_Context* context) {
context->treeNodeVisited = Clay__boolArray_Allocate_Arena(maxElementCount, arena); context->treeNodeVisited = Clay__boolArray_Allocate_Arena(maxElementCount, arena);
context->treeNodeVisited.length = context->treeNodeVisited.capacity; // This array is accessed directly rather than behaving as a list context->treeNodeVisited.length = context->treeNodeVisited.capacity; // This array is accessed directly rather than behaving as a list
context->openClipElementStack = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena); context->openClipElementStack = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
context->scissorDataStack = Clay__ScissorDataArray_Allocate_Arena(maxElementCount, arena);
context->reusableElementIndexBuffer = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena); context->reusableElementIndexBuffer = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
context->layoutElementClipElementIds = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena); context->layoutElementClipElementIds = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
context->dynamicStringData = Clay__charArray_Allocate_Arena(maxElementCount, arena); context->dynamicStringData = Clay__charArray_Allocate_Arena(maxElementCount, arena);
@ -2528,6 +2537,27 @@ bool Clay__ElementIsOffscreen(Clay_BoundingBox *boundingBox) {
(boundingBox->y + boundingBox->height < 0); (boundingBox->y + boundingBox->height < 0);
} }
Clay_BoundingBox Clay__ClipBoundingBox(Clay_BoundingBox outer, Clay_BoundingBox inner) {
float x = CLAY__MAX(outer.x, inner.x);
float y = CLAY__MAX(outer.y, inner.y);
float width = CLAY__MAX(
CLAY__MIN(outer.x + outer.width, inner.x + inner.width) - x,
0
);
float height = CLAY__MAX(
CLAY__MIN(outer.y + outer.height, inner.y + inner.height) - y,
0
);
return (Clay_BoundingBox) {
.x = x,
.y = y,
.width = width,
.height = height,
};
}
void Clay__CalculateFinalLayout(void) { void Clay__CalculateFinalLayout(void) {
Clay_Context* context = Clay_GetCurrentContext(); Clay_Context* context = Clay_GetCurrentContext();
// Calculate sizing along the X axis // Calculate sizing along the X axis
@ -2858,6 +2888,26 @@ void Clay__CalculateFinalLayout(void) {
.vertical = elementConfig->config.clipElementConfig->vertical, .vertical = elementConfig->config.clipElementConfig->vertical,
} }
}; };
if (!offscreen) {
Clay_BoundingBox scissorBoundingBox = renderCommand.boundingBox;
if (context->scissorDataStack.length > 0) {
scissorBoundingBox = Clay__ClipBoundingBox(
Clay__ScissorDataArray_GetValue(
&context->scissorDataStack,
context->scissorDataStack.length - 1
).boundingBox,
scissorBoundingBox
);
}
Clay__ScissorData scissorData = {
.boundingBox = scissorBoundingBox,
.id = renderCommand.id,
};
Clay__ScissorDataArray_Add(&context->scissorDataStack, scissorData);
renderCommand.boundingBox = scissorBoundingBox;
}
break; break;
} }
case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: { case CLAY__ELEMENT_CONFIG_TYPE_IMAGE: {
@ -3002,7 +3052,8 @@ void Clay__CalculateFinalLayout(void) {
bool closeClipElement = false; bool closeClipElement = false;
Clay_ClipElementConfig *clipConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig; Clay_ClipElementConfig *clipConfig = Clay__FindElementConfigWithType(currentElement, CLAY__ELEMENT_CONFIG_TYPE_CLIP).clipElementConfig;
if (clipConfig) { if (clipConfig) {
closeClipElement = true; Clay_LayoutElementHashMapItem *currentElementData = Clay__GetHashMapItem(currentElement->id);
closeClipElement = !Clay__ElementIsOffscreen(&currentElementData->boundingBox);
for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) { for (int32_t i = 0; i < context->scrollContainerDatas.length; i++) {
Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i); Clay__ScrollContainerDataInternal *mapping = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i);
if (mapping->layoutElement == currentElement) { if (mapping->layoutElement == currentElement) {
@ -3080,6 +3131,18 @@ void Clay__CalculateFinalLayout(void) {
.id = Clay__HashNumber(currentElement->id, rootElement->childrenOrTextContent.children.length + 11).id, .id = Clay__HashNumber(currentElement->id, rootElement->childrenOrTextContent.children.length + 11).id,
.commandType = CLAY_RENDER_COMMAND_TYPE_SCISSOR_END, .commandType = CLAY_RENDER_COMMAND_TYPE_SCISSOR_END,
}); });
context->scissorDataStack.length--;
if (context->scissorDataStack.length > 0) {
Clay__ScissorData prevScissorData = Clay__ScissorDataArray_GetValue(
&context->scissorDataStack,
context->scissorDataStack.length - 1
);
Clay__AddRenderCommand(CLAY__INIT(Clay_RenderCommand) {
.id = prevScissorData.id,
.commandType = CLAY_RENDER_COMMAND_TYPE_SCISSOR_START,
.boundingBox = prevScissorData.boundingBox,
});
}
} }
dfsBuffer.length--; dfsBuffer.length--;

View file

@ -15,5 +15,5 @@ mkdir -p build/clay \
-Wl,--initial-memory=6553600 \ -Wl,--initial-memory=6553600 \
-o build/clay/index.wasm \ -o build/clay/index.wasm \
main.c \ main.c \
&& cp index.html build/clay/index.html && cp -r fonts/ build/clay/fonts \ && cp index.html build/index.html && cp -r fonts/ build/clay/fonts \
&& cp index.html build/clay/index.html && cp -r images/ build/clay/images && cp -r images/ build/clay/images

View file

@ -8,7 +8,7 @@ set(FETCHCONTENT_QUIET FALSE)
FetchContent_Declare( FetchContent_Declare(
termbox2 termbox2
GIT_REPOSITORY "https://github.com/termbox/termbox2.git" GIT_REPOSITORY "https://github.com/termbox/termbox2.git"
GIT_TAG "9c9281a9a4c971a2be57f8645e828ec99fd555e8" GIT_TAG "ffd159c2a6106dd5eef338a6702ad15d4d4aa809"
GIT_PROGRESS TRUE GIT_PROGRESS TRUE
GIT_SHALLOW TRUE GIT_SHALLOW TRUE
) )
@ -17,7 +17,7 @@ FetchContent_MakeAvailable(termbox2)
FetchContent_Declare( FetchContent_Declare(
stb stb
GIT_REPOSITORY "https://github.com/nothings/stb.git" GIT_REPOSITORY "https://github.com/nothings/stb.git"
GIT_TAG "f58f558c120e9b32c217290b80bad1a0729fbb2c" GIT_TAG "fede005abaf93d9d7f3a679d1999b2db341b360f"
GIT_PROGRESS TRUE GIT_PROGRESS TRUE
GIT_SHALLOW TRUE GIT_SHALLOW TRUE
) )

View file

@ -90,7 +90,7 @@ void component_text_pair(const char *key, const char *value)
void component_termbox_settings(void) void component_termbox_settings(void)
{ {
CLAY_AUTO_ID({ CLAY(CLAY_ID("Termbox Settings"), {
.floating = { .floating = {
.attachTo = CLAY_ATTACH_TO_PARENT, .attachTo = CLAY_ATTACH_TO_PARENT,
.zIndex = 1, .zIndex = 1,
@ -509,13 +509,18 @@ Clay_RenderCommandArray CreateLayout(clay_tb_image *image1, clay_tb_image *image
{ {
Clay_BeginLayout(); Clay_BeginLayout();
CLAY_AUTO_ID({ CLAY_AUTO_ID({
.clip = {
.vertical = false,
.horizontal = true,
.childOffset = Clay_GetScrollOffset(),
},
.layout = { .layout = {
.sizing = { .sizing = {
.width = CLAY_SIZING_GROW(), .width = CLAY_SIZING_GROW(),
.height = CLAY_SIZING_GROW() .height = CLAY_SIZING_GROW()
}, },
.childAlignment = { .childAlignment = {
.x = CLAY_ALIGN_X_CENTER, .x = CLAY_ALIGN_X_LEFT,
.y = CLAY_ALIGN_Y_CENTER .y = CLAY_ALIGN_Y_CENTER
}, },
.childGap = 64 .childGap = 64
@ -714,12 +719,12 @@ void handle_termbox_events(void)
break; break;
} }
case TB_KEY_MOUSE_WHEEL_UP: { case TB_KEY_MOUSE_WHEEL_UP: {
Clay_Vector2 scrollDelta = { 0, 1 * Clay_Termbox_Cell_Height() }; Clay_Vector2 scrollDelta = { 0.5 * Clay_Termbox_Cell_Width(), 0 };
Clay_UpdateScrollContainers(false, scrollDelta, 1); Clay_UpdateScrollContainers(false, scrollDelta, 1);
break; break;
} }
case TB_KEY_MOUSE_WHEEL_DOWN: { case TB_KEY_MOUSE_WHEEL_DOWN: {
Clay_Vector2 scrollDelta = { 0, -1 * Clay_Termbox_Cell_Height() }; Clay_Vector2 scrollDelta = { -0.5 * Clay_Termbox_Cell_Width(), 0 };
Clay_UpdateScrollContainers(false, scrollDelta, 1); Clay_UpdateScrollContainers(false, scrollDelta, 1);
break; break;
} }

View file

@ -3,6 +3,8 @@
Copyright (c) 2025 Mivirl Copyright (c) 2025 Mivirl
altered by Godje (Sep 2025)
This software is provided 'as-is', without any express or implied warranty. This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the In no event will the authors be held liable for any damages arising from the
use of this software. use of this software.
@ -1616,6 +1618,20 @@ void Clay_Termbox_Render(Clay_RenderCommandArray commands)
Clay_StringSlice *text = &render_data.stringContents; Clay_StringSlice *text = &render_data.stringContents;
int32_t i = 0; int32_t i = 0;
// culling text characters that are outside of the layout
int h_clip = 0 - cell_box.x;
while(h_clip > 0 && i < text->length){
uint32_t ch = ' ';
int codepoint_length = tb_utf8_char_to_unicode(&ch, text->chars + i);
if (0 > codepoint_length) {
clay_tb_assert(false, "Invalid utf8");
}
i += codepoint_length;
h_clip -= 1;
}
// printing the rest of the characters
for (int y = box_begin_y; y < box_end_y; ++y) { for (int y = box_begin_y; y < box_end_y; ++y) {
for (int x = box_begin_x; x < box_end_x;) { for (int x = box_begin_x; x < box_end_x;) {
uint32_t ch = ' '; uint32_t ch = ' ';