Compare commits

...

9 Commits

Author SHA1 Message Date
tomat
8066eda535
Merge d0d1e01a3f into 5a328da308 2025-02-10 21:59:18 +00:00
Nic Barker
5a328da308 [Bindings/Odin] Switch error enum to correct size 2025-02-11 10:51:10 +13:00
Harrison Lambeth
3030390038
Define CLAY_IMPLEMENTATION in Jetbrains IDE (#236)
Some checks are pending
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) Waiting to run
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Waiting to run
2025-02-11 10:11:42 +13:00
Nic Barker
92582f66d8 [DebugTools] Fix a bug with display of border widths in debug tools 2025-02-11 10:11:15 +13:00
Nic Barker
65d2122dd6 [Core] Fix a bug where floating containers with anonymous IDs could conflict 2025-02-11 10:09:17 +13:00
Stephen T
d0d1e01a3f
Remove README for SDL3 renderer since it's no longer needed. 2025-02-06 19:51:41 -06:00
Stephen T
23ee491e37
Merge branch 'main' of https://github.com/steviegt6/clay into feature/sdl3-image-rendering
Fix merge issues on feature/sdl3-image-rendering branch.
Add support for scissor handling.
2025-02-06 19:51:17 -06:00
Stephen T
ccb57787ce
Remove image rendering from missing features of SDL3. 2025-01-31 03:02:52 -06:00
Stephen T
25e13b8bdb
Implement SDL3 image rendering with SDL_image. 2025-01-31 03:02:33 -06:00
13 changed files with 66 additions and 14 deletions

View File

@ -317,7 +317,7 @@ ElementDeclaration :: struct {
userData: rawptr userData: rawptr
} }
ErrorType :: enum { ErrorType :: enum EnumBackingType {
TextMeasurementFunctionNotProvided, TextMeasurementFunctionNotProvided,
ArenaCapacityExceeded, ArenaCapacityExceeded,
ElementsCapacityExceeded, ElementsCapacityExceeded,

Binary file not shown.

Binary file not shown.

Binary file not shown.

31
clay.h
View File

@ -21,6 +21,11 @@
#include <arm_neon.h> #include <arm_neon.h>
#endif #endif
#ifdef __JETBRAINS_IDE__
// Help jetbrains IDEs like CLion and Rider with intellisense & debugging
#define CLAY_IMPLEMENTATION
#endif
// ----------------------------------------- // -----------------------------------------
// HEADER DECLARATIONS --------------------- // HEADER DECLARATIONS ---------------------
// ----------------------------------------- // -----------------------------------------
@ -1274,13 +1279,14 @@ Clay_LayoutElementHashMapItem *Clay__GetHashMapItem(uint32_t id) {
return &Clay_LayoutElementHashMapItem_DEFAULT; return &Clay_LayoutElementHashMapItem_DEFAULT;
} }
void Clay__GenerateIdForAnonymousElement(Clay_LayoutElement *openLayoutElement) { Clay_ElementId Clay__GenerateIdForAnonymousElement(Clay_LayoutElement *openLayoutElement) {
Clay_Context* context = Clay_GetCurrentContext(); Clay_Context* context = Clay_GetCurrentContext();
Clay_LayoutElement *parentElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 2)); Clay_LayoutElement *parentElement = Clay_LayoutElementArray_Get(&context->layoutElements, Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 2));
Clay_ElementId elementId = Clay__HashNumber(parentElement->childrenOrTextContent.children.length, parentElement->id); Clay_ElementId elementId = Clay__HashNumber(parentElement->childrenOrTextContent.children.length, parentElement->id);
openLayoutElement->id = elementId.id; openLayoutElement->id = elementId.id;
Clay__AddHashMapItem(elementId, openLayoutElement, 0); Clay__AddHashMapItem(elementId, openLayoutElement, 0);
Clay__StringArray_Add(&context->layoutElementIdStrings, elementId.stringId); Clay__StringArray_Add(&context->layoutElementIdStrings, elementId.stringId);
return elementId;
} }
bool Clay__ElementHasConfig(Clay_LayoutElement *layoutElement, Clay__ElementConfigType type) { bool Clay__ElementHasConfig(Clay_LayoutElement *layoutElement, Clay__ElementConfigType type) {
@ -1515,11 +1521,8 @@ void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) {
.errorText = CLAY_STRING("An element was configured with CLAY_SIZING_PERCENT, but the provided percentage value was over 1.0. Clay expects a value between 0 and 1, i.e. 20% is 0.2."), .errorText = CLAY_STRING("An element was configured with CLAY_SIZING_PERCENT, but the provided percentage value was over 1.0. Clay expects a value between 0 and 1, i.e. 20% is 0.2."),
.userData = context->errorHandler.userData }); .userData = context->errorHandler.userData });
} }
if (declaration.id.id != 0) {
Clay__AttachId(declaration.id); Clay_ElementId openLayoutElementId = declaration.id;
} else if (openLayoutElement->id == 0) {
Clay__GenerateIdForAnonymousElement(openLayoutElement);
}
openLayoutElement->elementConfigs.internalArray = &context->elementConfigs.internalArray[context->elementConfigs.length]; openLayoutElement->elementConfigs.internalArray = &context->elementConfigs.internalArray[context->elementConfigs.length];
Clay_SharedElementConfig *sharedConfig = NULL; Clay_SharedElementConfig *sharedConfig = NULL;
@ -1572,6 +1575,9 @@ void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) {
} else if (declaration.floating.attachTo == CLAY_ATTACH_TO_ROOT) { } else if (declaration.floating.attachTo == CLAY_ATTACH_TO_ROOT) {
floatingConfig.parentId = Clay__HashString(CLAY_STRING("Clay__RootContainer"), 0, 0).id; floatingConfig.parentId = Clay__HashString(CLAY_STRING("Clay__RootContainer"), 0, 0).id;
} }
if (!openLayoutElementId.id) {
openLayoutElementId = Clay__HashString(CLAY_STRING("Clay__FloatingContainer"), context->layoutElementTreeRoots.length, 0);
}
Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) { Clay__LayoutElementTreeRootArray_Add(&context->layoutElementTreeRoots, CLAY__INIT(Clay__LayoutElementTreeRoot) {
.layoutElementIndex = Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 1), .layoutElementIndex = Clay__int32_tArray_GetValue(&context->openLayoutElementStack, context->openLayoutElementStack.length - 1),
.parentId = floatingConfig.parentId, .parentId = floatingConfig.parentId,
@ -1584,6 +1590,13 @@ void Clay__ConfigureOpenElement(const Clay_ElementDeclaration declaration) {
if (declaration.custom.customData) { if (declaration.custom.customData) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .customElementConfig = Clay__StoreCustomElementConfig(declaration.custom) }, CLAY__ELEMENT_CONFIG_TYPE_CUSTOM); Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .customElementConfig = Clay__StoreCustomElementConfig(declaration.custom) }, CLAY__ELEMENT_CONFIG_TYPE_CUSTOM);
} }
if (openLayoutElementId.id != 0) {
Clay__AttachId(openLayoutElementId);
} else if (openLayoutElement->id == 0) {
openLayoutElementId = Clay__GenerateIdForAnonymousElement(openLayoutElement);
}
if (declaration.scroll.horizontal | declaration.scroll.vertical) { if (declaration.scroll.horizontal | declaration.scroll.vertical) {
Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .scrollElementConfig = Clay__StoreScrollElementConfig(declaration.scroll) }, CLAY__ELEMENT_CONFIG_TYPE_SCROLL); Clay__AttachElementConfig(CLAY__INIT(Clay_ElementConfigUnion) { .scrollElementConfig = Clay__StoreScrollElementConfig(declaration.scroll) }, CLAY__ELEMENT_CONFIG_TYPE_SCROLL);
Clay__int32_tArray_Add(&context->openClipElementStack, (int)openLayoutElement->id); Clay__int32_tArray_Add(&context->openClipElementStack, (int)openLayoutElement->id);
@ -3107,11 +3120,11 @@ void Clay__RenderDebugView(void) {
CLAY({{0}}) { CLAY({{0}}) {
CLAY_TEXT(CLAY_STRING("{ left: "), infoTextConfig); CLAY_TEXT(CLAY_STRING("{ left: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.left), infoTextConfig); CLAY_TEXT(Clay__IntToString(borderConfig->width.left), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ right: "), infoTextConfig); CLAY_TEXT(CLAY_STRING(", right: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.right), infoTextConfig); CLAY_TEXT(Clay__IntToString(borderConfig->width.right), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ top: "), infoTextConfig); CLAY_TEXT(CLAY_STRING(", top: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.top), infoTextConfig); CLAY_TEXT(Clay__IntToString(borderConfig->width.top), infoTextConfig);
CLAY_TEXT(CLAY_STRING("{ bottom: "), infoTextConfig); CLAY_TEXT(CLAY_STRING(", bottom: "), infoTextConfig);
CLAY_TEXT(Clay__IntToString(borderConfig->width.bottom), infoTextConfig); CLAY_TEXT(Clay__IntToString(borderConfig->width.bottom), infoTextConfig);
CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig); CLAY_TEXT(CLAY_STRING(" }"), infoTextConfig);
} }

View File

@ -34,11 +34,24 @@ message(STATUS "Using SDL_ttf via FetchContent")
FetchContent_MakeAvailable(SDL_ttf) FetchContent_MakeAvailable(SDL_ttf)
set_property(DIRECTORY "${sdl_ttf_SOURCE_DIR}" PROPERTY EXCLUDE_FROM_ALL TRUE) set_property(DIRECTORY "${sdl_ttf_SOURCE_DIR}" PROPERTY EXCLUDE_FROM_ALL TRUE)
# Download SDL_image
FetchContent_Declare(
SDL_image
GIT_REPOSITORY "https://github.com/libsdl-org/SDL_image.git"
GIT_TAG main # Slightly risky to use main branch, but it's the only one available
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
message(STATUS "Using SDL_image via FetchContent")
FetchContent_MakeAvailable(SDL_image)
set_property(DIRECTORY "${SDL_image_SOURCE_DIR}" PROPERTY EXCLUDE_FROM_ALL TRUE)
# Example executable # Example executable
add_executable(${PROJECT_NAME} main.c) add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} PRIVATE target_link_libraries(${PROJECT_NAME} PRIVATE
SDL3::SDL3 SDL3::SDL3
SDL3_ttf::SDL3_ttf SDL3_ttf::SDL3_ttf
SDL3_image::SDL3_image
) )
add_custom_command( add_custom_command(

View File

@ -23,6 +23,8 @@ typedef struct app_state {
ClayVideoDemo_Data demoData; ClayVideoDemo_Data demoData;
} AppState; } AppState;
SDL_Surface *sample_image;
static inline Clay_Dimensions SDL_MeasureText(Clay_StringSlice text, Clay_TextElementConfig *config, void *userData) static inline Clay_Dimensions SDL_MeasureText(Clay_StringSlice text, Clay_TextElementConfig *config, void *userData)
{ {
TTF_Font *font = gFonts[config->fontId]; TTF_Font *font = gFonts[config->fontId];
@ -68,6 +70,8 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
gFonts[FONT_ID] = font; gFonts[FONT_ID] = font;
sample_image = IMG_Load("resources/sample.png");
/* Initialize Clay */ /* Initialize Clay */
uint64_t totalMemorySize = Clay_MinMemorySize(); uint64_t totalMemorySize = Clay_MinMemorySize();
Clay_Arena clayMemory = (Clay_Arena) { Clay_Arena clayMemory = (Clay_Arena) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 B

View File

@ -1,4 +0,0 @@
Please note, the SDL3 renderer is not 100% feature complete. It is currently missing:
- Images
- Scroll / Scissor handling

View File

@ -2,6 +2,7 @@
#include <SDL3/SDL_main.h> #include <SDL3/SDL_main.h>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <SDL3_ttf/SDL_ttf.h> #include <SDL3_ttf/SDL_ttf.h>
#include <SDL3_image/SDL_image.h>
/* This needs to be global because the "MeasureText" callback doesn't have a /* This needs to be global because the "MeasureText" callback doesn't have a
* user data parameter */ * user data parameter */
@ -137,6 +138,8 @@ static void SDL_RenderArc(SDL_Renderer *renderer, const SDL_FPoint center, const
} }
} }
SDL_Rect currentClippingRectangle;
static void SDL_RenderClayCommands(SDL_Renderer *renderer, Clay_RenderCommandArray *rcommands) static void SDL_RenderClayCommands(SDL_Renderer *renderer, Clay_RenderCommandArray *rcommands)
{ {
for (size_t i = 0; i < rcommands->length; i++) { for (size_t i = 0; i < rcommands->length; i++) {
@ -232,6 +235,29 @@ static void SDL_RenderClayCommands(SDL_Renderer *renderer, Clay_RenderCommandArr
} }
} break; } break;
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START: {
Clay_BoundingBox boundingBox = rcmd->boundingBox;
currentClippingRectangle = (SDL_Rect) {
.x = boundingBox.x,
.y = boundingBox.y,
.w = boundingBox.width,
.h = boundingBox.height,
};
SDL_SetRenderClipRect(renderer, &currentClippingRectangle);
break;
}
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END: {
SDL_SetRenderClipRect(renderer, NULL);
break;
}
case CLAY_RENDER_COMMAND_TYPE_IMAGE: {
Clay_ImageRenderData *config = &rcmd->renderData.image;
const SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, config->imageData);
const SDL_FRect dest = { rect.x, rect.y, rect.w, rect.h };
SDL_RenderTexture(renderer, texture, NULL, &dest);
break;
}
default: default:
SDL_Log("Unknown render command type: %d", rcmd->commandType); SDL_Log("Unknown render command type: %d", rcmd->commandType);
} }