Compare commits

..

9 Commits

Author SHA1 Message Date
AICDG
cc07dcf3af
Merge 356724ed20 into afba9f0de6 2025-01-13 10:11:04 +00:00
AICDG
356724ed20
Merge branch 'main' into main 2025-01-13 18:10:59 +08:00
Harrison Lambeth
afba9f0de6
Add a function to reset text measurement cache (#181)
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Waiting to run
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Failing after 14s
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Failing after 14s
2025-01-13 19:26:46 +13:00
Nic Barker
3a4455aa83
Fix text wrapping handling with explicit newline characters (#192)
Co-authored-by: Ryzee119 <wendland@live.com.au>
2025-01-13 19:23:28 +13:00
Nic Barker
208c7cb3a0 Fix incorrect border between children after 2nd element
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Waiting to run
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Failing after 12s
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Failing after 11s
2025-01-12 19:16:09 +13:00
Nic Barker
c2c445e455 Fix broken ifdef on MSVC
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Waiting to run
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Failing after 12s
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Failing after 13s
2025-01-12 10:49:00 +13:00
Nic Barker
9e7595b873 Fixed a bug where minMemorySize could cause a memory overwrite
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Waiting to run
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Failing after 12s
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Failing after 11s
2025-01-11 21:37:21 +13:00
Nic Barker
32d1a31dfe Fix uint64 usage for wasm 2025-01-11 21:35:45 +13:00
Nic Barker
b2b50724e2 Fix bug in html renderer debug tools 2025-01-11 20:45:20 +13:00
3 changed files with 64 additions and 17 deletions

View File

@ -173,9 +173,12 @@ For help starting out or to discuss clay, considering joining [the discord serve
- [Clay_MinMemorySize](#clay_minmemorysize)
- [Clay_CreateArenaWithCapacityAndMemory](#clay_createarenawithcapacityandmemory)
- [Clay_SetMeasureTextFunction](#clay_setmeasuretextfunction)
- [Clay_ResetMeasureTextCache](#clau_resetmeasuretextcache)
- [Clay_SetMaxElementCount](clay_setmaxelementcount)
- [Clay_SetMaxMeasureTextCacheWordCount](#clay_setmaxmeasuretextcachewordcount)
- [Clay_Initialize](#clay_initialize)
- [Clay_GetCurrentContext](#clay_getcurrentcontext)
- [Clay_SetCurrentContext](#clay_setcurrentcontext)
- [Clay_SetLayoutDimensions](#clay_setlayoutdimensions)
- [Clay_SetPointerState](#clay_setpointerstate)
- [Clay_UpdateScrollContainers](#clay_updatescrollcontainers)
@ -575,6 +578,14 @@ Takes a pointer to a function that can be used to measure the `width, height` di
---
### Clay_ResetMeasureTextCache
`void Clay_ResetMeasureTextCache(void)`
Clay caches measurements from the provided MeasureTextFunction, and this will be sufficient for the majority of use-cases. However, if the measurements can depend on external factors that clay does not know about, like DPI changes, then the cached values may be incorrect. When one of these external factors changes, Clay_ResetMeasureTextCache can be called to force clay to recalculate all string measurements in the next frame.
---
### Clay_SetMaxElementCount
`void Clay_SetMaxElementCount(uint32_t maxElementCount)`
@ -603,12 +614,16 @@ Initializes the internal memory mapping, sets the internal dimensions for layout
Reference: [Clay_Arena](#clay_createarenawithcapacityandmemory), [Clay_ErrorHandler](#clay_errorhandler), [Clay_SetCurrentContext](#clay_setcurrentcontext)
---
### Clay_SetCurrentContext
`void Clay_SetCurrentContext(Clay_Context* context)`
Sets the context that subsequent clay commands will operate on. You can get this reference from [Clay_Initialize](#clay_initialize) or [Clay_GetCurrentContext](#clay_getcurrentcontext). See [Running more than one Clay instance](#running-more-than-one-clay-instance).
---
### Clay_GetCurrentContext
`Clay_Context* Clay_GetCurrentContext()`

66
clay.h
View File

@ -399,7 +399,7 @@ CLAY__TYPEDEF(Clay_Border, struct {
Clay_Color color;
});
CLAY__TYPEDEF(Clay_BorderElementConfig, struct {
struct Clay_BorderElementConfig {
Clay_Border left;
Clay_Border right;
Clay_Border top;
@ -409,7 +409,8 @@ CLAY__TYPEDEF(Clay_BorderElementConfig, struct {
#ifdef CLAY_EXTEND_CONFIG_BORDER
CLAY_EXTEND_CONFIG_BORDER
#endif
});
};
CLAY__TYPEDEF(Clay_BorderElementConfig, struct Clay_BorderElementConfig);
CLAY__TYPEDEF(Clay_ElementConfigUnion, union {
Clay_RectangleElementConfig *rectangleElementConfig;
@ -524,6 +525,7 @@ int32_t Clay_GetMaxElementCount(void);
void Clay_SetMaxElementCount(int32_t maxElementCount);
int32_t Clay_GetMaxMeasureTextCacheWordCount(void);
void Clay_SetMaxMeasureTextCacheWordCount(int32_t maxMeasureTextCacheWordCount);
void Clay_ResetMeasureTextCache(void);
// Internal API functions required by macros
void Clay__OpenElement(void);
@ -1212,6 +1214,7 @@ Clay__MeasuredWord *Clay__MeasuredWordArray_Add(Clay__MeasuredWordArray *array,
CLAY__TYPEDEF(Clay__MeasureTextCacheItem, struct {
Clay_Dimensions unwrappedDimensions;
int32_t measuredWordsStartIndex;
bool containsNewlines;
// Hash map data
uint32_t id;
int32_t nextIndex;
@ -1390,7 +1393,7 @@ struct Clay_Context {
bool externalScrollHandlingEnabled;
uint32_t debugSelectedElementId;
uint32_t generation;
uint64_t arenaResetOffset;
uintptr_t arenaResetOffset;
Clay_Arena internalArena;
// Layout Elements / Render Commands
Clay_LayoutElementArray layoutElements;
@ -1677,6 +1680,7 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
int32_t start = 0;
int32_t end = 0;
float lineWidth = 0;
float measuredWidth = 0;
float measuredHeight = 0;
float spaceWidth = Clay__MeasureText(&CLAY__SPACECHAR, config).width;
@ -1698,18 +1702,22 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
int32_t length = end - start;
Clay_String word = { .length = length, .chars = &text->chars[start] };
Clay_Dimensions dimensions = Clay__MeasureText(&word, config);
measuredHeight = CLAY__MAX(measuredHeight, dimensions.height);
if (current == ' ') {
dimensions.width += spaceWidth;
previousWord = Clay__AddMeasuredWord(CLAY__INIT(Clay__MeasuredWord) { .startOffset = start, .length = length + 1, .width = dimensions.width, .next = -1 }, previousWord);
lineWidth += dimensions.width;
}
if (current == '\n') {
if (length > 1) {
if (length > 0) {
previousWord = Clay__AddMeasuredWord(CLAY__INIT(Clay__MeasuredWord) { .startOffset = start, .length = length, .width = dimensions.width, .next = -1 }, previousWord);
}
previousWord = Clay__AddMeasuredWord(CLAY__INIT(Clay__MeasuredWord) { .startOffset = end + 1, .length = 0, .width = 0, .next = -1 }, previousWord);
lineWidth += dimensions.width;
measuredWidth = CLAY__MAX(lineWidth, measuredWidth);
measured->containsNewlines = true;
lineWidth = 0;
}
measuredWidth += dimensions.width;
measuredHeight = dimensions.height;
start = end + 1;
}
end++;
@ -1718,9 +1726,11 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
Clay_String lastWord = { .length = end - start, .chars = &text->chars[start] };
Clay_Dimensions dimensions = Clay__MeasureText(&lastWord, config);
Clay__AddMeasuredWord(CLAY__INIT(Clay__MeasuredWord) { .startOffset = start, .length = end - start, .width = dimensions.width, .next = -1 }, previousWord);
measuredWidth += dimensions.width;
measuredHeight = dimensions.height;
lineWidth += dimensions.width;
measuredHeight = CLAY__MAX(measuredHeight, dimensions.height);
}
measuredWidth = CLAY__MAX(lineWidth, measuredWidth);
measured->measuredWordsStartIndex = tempWord.next;
measured->unwrappedDimensions.width = measuredWidth;
measured->unwrappedDimensions.height = measuredHeight;
@ -2102,6 +2112,9 @@ void Clay__CompressChildrenAlongAxis(bool xAxis, float totalSizeToDistribute, Cl
float targetSize = 0;
for (int32_t i = 0; i < resizableContainerBuffer.length; ++i) {
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_Get(&resizableContainerBuffer, i));
if (!xAxis && Clay__ElementHasConfig(childElement, CLAY__ELEMENT_CONFIG_TYPE_IMAGE)) {
continue;
}
float childSize = xAxis ? childElement->dimensions.width : childElement->dimensions.height;
if ((childSize - largestSize) < 0.1 && (childSize - largestSize) > -0.1) {
Clay__int32_tArray_Add(&largestContainers, Clay__int32_tArray_Get(&resizableContainerBuffer, i));
@ -2363,7 +2376,7 @@ void Clay__CalculateFinalLayout() {
float lineHeight = textConfig->lineHeight > 0 ? (float)textConfig->lineHeight : textElementData->preferredDimensions.height;
int32_t lineLengthChars = 0;
int32_t lineStartOffset = 0;
if (textElementData->preferredDimensions.width <= containerElement->dimensions.width) {
if (!measureTextCacheItem->containsNewlines && textElementData->preferredDimensions.width <= containerElement->dimensions.width) {
Clay__WrappedTextLineArray_Add(&context->wrappedTextLines, CLAY__INIT(Clay__WrappedTextLine) { containerElement->dimensions, textElementData->text });
textElementData->wrappedLines.length++;
continue;
@ -2471,9 +2484,9 @@ void Clay__CalculateFinalLayout() {
while (sortMax > 0) { // todo dumb bubble sort
for (int32_t i = 0; i < sortMax; ++i) {
Clay__LayoutElementTreeRoot current = *Clay__LayoutElementTreeRootArray_Get(&context->layoutElementTreeRoots, i);
Clay__LayoutElementTreeRoot *next = Clay__LayoutElementTreeRootArray_Get(&context->layoutElementTreeRoots, i + 1);
if (next->zIndex < current.zIndex) {
Clay__LayoutElementTreeRootArray_Set(&context->layoutElementTreeRoots, i, *next);
Clay__LayoutElementTreeRoot next = *Clay__LayoutElementTreeRootArray_Get(&context->layoutElementTreeRoots, i + 1);
if (next.zIndex < current.zIndex) {
Clay__LayoutElementTreeRootArray_Set(&context->layoutElementTreeRoots, i, next);
Clay__LayoutElementTreeRootArray_Set(&context->layoutElementTreeRoots, i + 1, current);
}
}
@ -2800,7 +2813,8 @@ void Clay__CalculateFinalLayout() {
Clay__AddRenderCommand(renderCommand);
if (borderConfig->betweenChildren.width > 0 && borderConfig->betweenChildren.color.a > 0) {
Clay_RectangleElementConfig *rectangleConfig = Clay__StoreRectangleElementConfig(CLAY__INIT(Clay_RectangleElementConfig) {.color = borderConfig->betweenChildren.color});
Clay_Vector2 borderOffset = { (float)layoutConfig->padding.x, (float)layoutConfig->padding.y };
float halfGap = layoutConfig->childGap / 2;
Clay_Vector2 borderOffset = { (float)layoutConfig->padding.x - halfGap, (float)layoutConfig->padding.y - halfGap };
if (layoutConfig->layoutDirection == CLAY_LEFT_TO_RIGHT) {
for (int32_t i = 0; i < currentElement->childrenOrTextContent.children.length; ++i) {
Clay_LayoutElement *childElement = Clay_LayoutElementArray_Get(&context->layoutElements, currentElement->childrenOrTextContent.children.elements[i]);
@ -2812,7 +2826,7 @@ void Clay__CalculateFinalLayout() {
.commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE,
});
}
borderOffset.x += (childElement->dimensions.width + (float)layoutConfig->childGap / 2);
borderOffset.x += (childElement->dimensions.width + (float)layoutConfig->childGap);
}
} else {
for (int32_t i = 0; i < currentElement->childrenOrTextContent.children.length; ++i) {
@ -2825,7 +2839,7 @@ void Clay__CalculateFinalLayout() {
.commandType = CLAY_RENDER_COMMAND_TYPE_RECTANGLE,
});
}
borderOffset.y += (childElement->dimensions.height + (float)layoutConfig->childGap / 2);
borderOffset.y += (childElement->dimensions.height + (float)layoutConfig->childGap);
}
}
}
@ -3222,16 +3236,19 @@ void Clay__RenderDebugView() {
Clay_TextElementConfig *infoTitleConfig = CLAY_TEXT_CONFIG({ .textColor = CLAY__DEBUGVIEW_COLOR_3, .fontSize = 16, .wrapMode = CLAY_TEXT_WRAP_NONE });
Clay_ElementId scrollId = Clay__HashString(CLAY_STRING("Clay__DebugViewOuterScrollPane"), 0, 0);
float scrollYOffset = 0;
bool pointerInDebugView = context->pointerInfo.position.y < context->layoutDimensions.height - 300;
for (int32_t i = 0; i < context->scrollContainerDatas.length; ++i) {
Clay__ScrollContainerDataInternal *scrollContainerData = Clay__ScrollContainerDataInternalArray_Get(&context->scrollContainerDatas, i);
if (scrollContainerData->elementId == scrollId.id) {
if (!context->externalScrollHandlingEnabled) {
scrollYOffset = scrollContainerData->scrollPosition.y;
} else {
pointerInDebugView = context->pointerInfo.position.y + scrollContainerData->scrollPosition.y < context->layoutDimensions.height - 300;
}
break;
}
}
int32_t highlightedRow = context->pointerInfo.position.y < context->layoutDimensions.height - 300
int32_t highlightedRow = pointerInDebugView
? (int32_t)((context->pointerInfo.position.y - scrollYOffset) / (float)CLAY__DEBUGVIEW_ROW_HEIGHT) - 1
: -1;
if (context->pointerInfo.position.x < context->layoutDimensions.width - (float)Clay__debugViewWidth) {
@ -3609,7 +3626,7 @@ uint32_t Clay_MinMemorySize(void) {
.maxMeasureTextCacheWordCount = Clay__defaultMaxMeasureTextWordCacheCount,
.internalArena = {
.capacity = SIZE_MAX,
.memory = (char*)&fakeContext,
.memory = NULL,
}
};
Clay_Context* currentContext = Clay_GetCurrentContext();
@ -4035,6 +4052,21 @@ void Clay_SetMaxMeasureTextCacheWordCount(int32_t maxMeasureTextCacheWordCount)
}
}
CLAY_WASM_EXPORT("Clay_ResetMeasureTextCache")
void Clay_ResetMeasureTextCache(void) {
Clay_Context* context = Clay_GetCurrentContext();
context->measureTextHashMapInternal.length = 0;
context->measureTextHashMapInternalFreeList.length = 0;
context->measureTextHashMap.length = 0;
context->measuredWords.length = 0;
context->measuredWordsFreeList.length = 0;
for (int32_t i = 0; i < context->measureTextHashMap.capacity; ++i) {
context->measureTextHashMap.internalArray[i] = 0;
}
context->measureTextHashMapInternal.length = 1; // Reserve the 0 value to mean "no next element"
}
#endif // CLAY_IMPLEMENTATION
/*