Compare commits

...

5 Commits

Author SHA1 Message Date
Harrison Lambeth
0ea0643a36
Merge b97bf246c8 into dcd6feda86 2025-02-08 16:24:11 +08:00
Nic Barker
dcd6feda86 [Bindings/Odin] Add support for Clay_Hovered() to Odin bindings
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
2025-02-08 18:54:15 +13:00
Dan Korostelev
b4102400ff
[Bindings/Odin] Add get/set current context method to Odin bindings (#252) 2025-02-08 18:51:55 +13:00
Harrison Lambeth
b97bf246c8 Fix some things that broke after rebasing 2025-01-29 19:21:31 -07:00
Harrison Lambeth
3f39223eb4 Clay_GetElementIdsAtPoint 2025-01-29 19:07:45 -07:00
3 changed files with 69 additions and 1 deletions

View File

@ -339,6 +339,8 @@ ErrorHandler :: struct {
userData: rawptr userData: rawptr
} }
Context :: struct {} // opaque structure, only use as a pointer
@(link_prefix = "Clay_", default_calling_convention = "c") @(link_prefix = "Clay_", default_calling_convention = "c")
foreign Clay { foreign Clay {
MinMemorySize :: proc() -> u32 --- MinMemorySize :: proc() -> u32 ---
@ -349,12 +351,15 @@ foreign Clay {
SetLayoutDimensions :: proc(dimensions: Dimensions) --- SetLayoutDimensions :: proc(dimensions: Dimensions) ---
BeginLayout :: proc() --- BeginLayout :: proc() ---
EndLayout :: proc() -> ClayArray(RenderCommand) --- EndLayout :: proc() -> ClayArray(RenderCommand) ---
Hovered :: proc() -> bool ---
PointerOver :: proc(id: ElementId) -> bool --- PointerOver :: proc(id: ElementId) -> bool ---
GetElementId :: proc(id: String) -> ElementId --- GetElementId :: proc(id: String) -> ElementId ---
GetScrollContainerData :: proc(id: ElementId) -> ScrollContainerData --- GetScrollContainerData :: proc(id: ElementId) -> ScrollContainerData ---
SetMeasureTextFunction :: proc(measureTextFunction: proc "c" (text: StringSlice, config: ^TextElementConfig, userData: uintptr) -> Dimensions, userData: uintptr) --- SetMeasureTextFunction :: proc(measureTextFunction: proc "c" (text: StringSlice, config: ^TextElementConfig, userData: uintptr) -> Dimensions, userData: uintptr) ---
RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: i32) -> ^RenderCommand --- RenderCommandArray_Get :: proc(array: ^ClayArray(RenderCommand), index: i32) -> ^RenderCommand ---
SetDebugModeEnabled :: proc(enabled: bool) --- SetDebugModeEnabled :: proc(enabled: bool) ---
GetCurrentContext :: proc() -> ^Context ---
SetCurrentContext :: proc(ctx: ^Context) ---
} }
@(link_prefix = "Clay_", default_calling_convention = "c", private) @(link_prefix = "Clay_", default_calling_convention = "c", private)

View File

@ -438,7 +438,7 @@ createLayout :: proc(lerpValue: f32) -> clay.ClayArray(clay.RenderCommand) {
id = clay.ID("LinkGithubOuter"), id = clay.ID("LinkGithubOuter"),
layout = { padding = { 16, 16, 6, 6 } }, layout = { padding = { 16, 16, 6, 6 } },
border = border2pxRed, border = border2pxRed,
backgroundColor = clay.PointerOver(clay.GetElementId(clay.MakeString("LinkGithubOuter"))) ? COLOR_LIGHT_HOVER : COLOR_LIGHT, backgroundColor = clay.Hovered() ? COLOR_LIGHT_HOVER : COLOR_LIGHT,
cornerRadius = clay.CornerRadiusAll(10) cornerRadius = clay.CornerRadiusAll(10)
}) { }) {
clay.Text("Github", clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = {61, 26, 5, 255}})) clay.Text("Github", clay.TextConfig({fontId = FONT_ID_BODY_24, fontSize = 24, textColor = {61, 26, 5, 255}}))

63
clay.h
View File

@ -534,6 +534,12 @@ typedef struct {
void *userData; void *userData;
} Clay_ErrorHandler; } Clay_ErrorHandler;
typedef struct
{
int32_t length;
const Clay_ElementId *results;
} Clay_PointQueryResult;
// Function Forward Declarations --------------------------------- // Function Forward Declarations ---------------------------------
// Public API functions --- // Public API functions ---
uint32_t Clay_MinMemorySize(void); uint32_t Clay_MinMemorySize(void);
@ -565,6 +571,7 @@ void Clay_SetMaxElementCount(int32_t maxElementCount);
int32_t Clay_GetMaxMeasureTextCacheWordCount(void); int32_t Clay_GetMaxMeasureTextCacheWordCount(void);
void Clay_SetMaxMeasureTextCacheWordCount(int32_t maxMeasureTextCacheWordCount); void Clay_SetMaxMeasureTextCacheWordCount(int32_t maxMeasureTextCacheWordCount);
void Clay_ResetMeasureTextCache(void); void Clay_ResetMeasureTextCache(void);
Clay_PointQueryResult Clay_GetElementIdsAtPoint(Clay_Vector2 point);
// Internal API functions required by macros // Internal API functions required by macros
void Clay__OpenElement(void); void Clay__OpenElement(void);
@ -906,6 +913,8 @@ struct Clay_Context {
Clay__boolArray treeNodeVisited; Clay__boolArray treeNodeVisited;
Clay__charArray dynamicStringData; Clay__charArray dynamicStringData;
Clay__DebugElementDataArray debugElementData; Clay__DebugElementDataArray debugElementData;
// Point querying
Clay__ElementIdArray pointQueryIds;
}; };
Clay_Context* Clay__Context_Allocate_Arena(Clay_Arena *arena) { Clay_Context* Clay__Context_Allocate_Arena(Clay_Arena *arena) {
@ -1655,6 +1664,7 @@ void Clay__InitializePersistentMemory(Clay_Context* context) {
context->measureTextHashMap = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena); context->measureTextHashMap = Clay__int32_tArray_Allocate_Arena(maxElementCount, arena);
context->measuredWords = Clay__MeasuredWordArray_Allocate_Arena(maxMeasureTextCacheWordCount, arena); context->measuredWords = Clay__MeasuredWordArray_Allocate_Arena(maxMeasureTextCacheWordCount, arena);
context->pointerOverIds = Clay__ElementIdArray_Allocate_Arena(maxElementCount, arena); context->pointerOverIds = Clay__ElementIdArray_Allocate_Arena(maxElementCount, arena);
context->pointQueryIds = Clay__ElementIdArray_Allocate_Arena(maxElementCount, arena);
context->debugElementData = Clay__DebugElementDataArray_Allocate_Arena(maxElementCount, arena); context->debugElementData = Clay__DebugElementDataArray_Allocate_Arena(maxElementCount, arena);
context->arenaResetOffset = arena->nextAllocation; context->arenaResetOffset = arena->nextAllocation;
} }
@ -3333,6 +3343,59 @@ void Clay_SetPointerState(Clay_Vector2 position, bool isPointerDown) {
} }
} }
CLAY_WASM_EXPORT("Clay_GetElementIdsAtPoint")
Clay_PointQueryResult Clay_GetElementIdsAtPoint(Clay_Vector2 position) {
Clay_Context* context = Clay_GetCurrentContext();
if (context->booleanWarnings.maxElementsExceeded) {
return CLAY__INIT(Clay_PointQueryResult) { 0, NULL };
}
context->pointQueryIds.length = 0;
Clay__int32_tArray dfsBuffer = context->layoutElementChildrenBuffer;
for (int32_t rootIndex = context->layoutElementTreeRoots.length - 1; rootIndex >= 0; --rootIndex) {
dfsBuffer.length = 0;
Clay__LayoutElementTreeRoot *root = Clay__LayoutElementTreeRootArray_Get(&context->layoutElementTreeRoots, rootIndex);
Clay__int32_tArray_Add(&dfsBuffer, (int32_t)root->layoutElementIndex);
context->treeNodeVisited.internalArray[0] = false;
bool found = false;
while (dfsBuffer.length > 0) {
if (context->treeNodeVisited.internalArray[dfsBuffer.length - 1]) {
dfsBuffer.length--;
continue;
}
context->treeNodeVisited.internalArray[dfsBuffer.length - 1] = true;
Clay_LayoutElement *currentElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&dfsBuffer, (int)dfsBuffer.length - 1));
Clay_LayoutElementHashMapItem *mapItem = Clay__GetHashMapItem(currentElement->id); // TODO think of a way around this, maybe the fact that it's essentially a binary tree limits the cost, but the worst case is not great
Clay_BoundingBox elementBox = mapItem->boundingBox;
elementBox.x -= root->pointerOffset.x;
elementBox.y -= root->pointerOffset.y;
if (mapItem) {
if ((Clay__PointIsInsideRect(position, elementBox))) {
Clay__ElementIdArray_Add(&context->pointQueryIds, mapItem->elementId);
found = true;
}
if (Clay__ElementHasConfig(currentElement, CLAY__ELEMENT_CONFIG_TYPE_TEXT)) {
dfsBuffer.length--;
continue;
}
for (int32_t i = currentElement->childrenOrTextContent.children.length - 1; i >= 0; --i) {
Clay__int32_tArray_Add(&dfsBuffer, currentElement->childrenOrTextContent.children.elements[i]);
context->treeNodeVisited.internalArray[dfsBuffer.length - 1] = false; // TODO needs to be ranged checked
}
} else {
dfsBuffer.length--;
}
}
Clay_LayoutElement *rootElement = Clay_LayoutElementArray_Get(&context->layoutElements, root->layoutElementIndex);
if (found && Clay__ElementHasConfig(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER) &&
Clay__FindElementConfigWithType(rootElement, CLAY__ELEMENT_CONFIG_TYPE_FLOATING_CONTAINER).floatingElementConfig->pointerCaptureMode == CLAY_POINTER_CAPTURE_MODE_CAPTURE) {
break;
}
}
return CLAY__INIT(Clay_PointQueryResult) { context->pointQueryIds.length, context->pointQueryIds.internalArray };
}
CLAY_WASM_EXPORT("Clay_Initialize") CLAY_WASM_EXPORT("Clay_Initialize")
Clay_Context* Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler) { Clay_Context* Clay_Initialize(Clay_Arena arena, Clay_Dimensions layoutDimensions, Clay_ErrorHandler errorHandler) {
Clay_Context *context = Clay__Context_Allocate_Arena(&arena); Clay_Context *context = Clay__Context_Allocate_Arena(&arena);