mirror of
https://github.com/nicbarker/clay.git
synced 2026-04-02 17:34:16 +00:00
[Core] Transition API (#579)
This commit is contained in:
parent
40350e593a
commit
ee192f48c5
13 changed files with 2454 additions and 1077 deletions
|
|
@ -33,6 +33,7 @@ endif ()
|
|||
if(CLAY_INCLUDE_ALL_EXAMPLES OR CLAY_INCLUDE_RAYLIB_EXAMPLES)
|
||||
add_subdirectory("examples/raylib-multi-context")
|
||||
add_subdirectory("examples/raylib-sidebar-scrolling-container")
|
||||
add_subdirectory("examples/raylib-transitions")
|
||||
endif ()
|
||||
if(CLAY_INCLUDE_ALL_EXAMPLES OR CLAY_INCLUDE_SDL2_EXAMPLES)
|
||||
add_subdirectory("examples/SDL2-video-demo")
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ int main(void) {
|
|||
// Moved into a separate function for brevity.
|
||||
Layout();
|
||||
|
||||
Clay_RenderCommandArray commands = Clay_EndLayout();
|
||||
Clay_RenderCommandArray commands = Clay_EndLayout(0);
|
||||
// Pass our layout to the cairo backend
|
||||
Clay_Cairo_Render(commands, fonts);
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ void LandingPageMobile() {
|
|||
void FeatureBlocksDesktop() {
|
||||
CLAY(CLAY_ID("FeatureBlocksOuter"), { .layout = { .sizing = { CLAY_SIZING_GROW(0) } } }) {
|
||||
CLAY(CLAY_ID("FeatureBlocksInner"), { .layout = { .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = { .y = CLAY_ALIGN_Y_CENTER } }, .border = { .width = { .betweenChildren = 2 }, .color = COLOR_RED } }) {
|
||||
Clay_TextElementConfig *textConfig = CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_RED });
|
||||
Clay_TextElementConfig textConfig = CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_RED });
|
||||
CLAY(CLAY_ID("HFileBoxOuter"), { .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_PERCENT(0.5f) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {50, 50, 32, 32}, .childGap = 8 } }) {
|
||||
CLAY(CLAY_ID("HFileIncludeOuter"), { .layout = { .padding = {8, 4} }, .backgroundColor = COLOR_RED, .cornerRadius = CLAY_CORNER_RADIUS(8) }) {
|
||||
CLAY_TEXT(CLAY_STRING("#include clay.h"), CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_LIGHT }));
|
||||
|
|
@ -129,7 +129,7 @@ void FeatureBlocksDesktop() {
|
|||
|
||||
void FeatureBlocksMobile() {
|
||||
CLAY(CLAY_ID("FeatureBlocksInner"), { .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0) } }, .border = { .width = { .betweenChildren = 2 }, .color = COLOR_RED } }) {
|
||||
Clay_TextElementConfig *textConfig = CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_RED });
|
||||
Clay_TextElementConfig textConfig = CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_RED });
|
||||
CLAY(CLAY_ID("HFileBoxOuter"), { .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0) }, .childAlignment = {0, CLAY_ALIGN_Y_CENTER}, .padding = {16, 16, 32, 32}, .childGap = 8 } }) {
|
||||
CLAY(CLAY_ID("HFileIncludeOuter"), { .layout = { .padding = {8, 4} }, .backgroundColor = COLOR_RED, .cornerRadius = CLAY_CORNER_RADIUS(8) }) {
|
||||
CLAY_TEXT(CLAY_STRING("#include clay.h"), CLAY_TEXT_CONFIG({ .fontSize = 24, .fontId = FONT_ID_BODY_24, .textColor = COLOR_LIGHT }));
|
||||
|
|
@ -342,7 +342,7 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
|
|||
Clay_BeginLayout();
|
||||
CLAY(CLAY_ID("OuterContainer"), { .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0) } }, .backgroundColor = COLOR_LIGHT }) {
|
||||
CLAY(CLAY_ID("Header"), { .layout = { .sizing = { CLAY_SIZING_GROW(0), CLAY_SIZING_FIXED(50) }, .childAlignment = { 0, CLAY_ALIGN_Y_CENTER }, .childGap = 16, .padding = { 32, 32 } } }) {
|
||||
CLAY_TEXT(CLAY_STRING("Clay"), &headerTextConfig);
|
||||
CLAY_TEXT(CLAY_STRING("Clay"), headerTextConfig);
|
||||
CLAY(CLAY_ID("Spacer"), { .layout = { .sizing = { .width = CLAY_SIZING_GROW(0) } } }) {}
|
||||
if (!mobileScreen) {
|
||||
CLAY(CLAY_ID("LinkExamplesOuter"), { .layout = { .padding = {8, 8} } }) {
|
||||
|
|
@ -426,7 +426,7 @@ Clay_RenderCommandArray CreateLayout(bool mobileScreen, float lerpValue) {
|
|||
.cornerRadius = CLAY_CORNER_RADIUS(5)
|
||||
}) {}
|
||||
}
|
||||
return Clay_EndLayout();
|
||||
return Clay_EndLayout(0);
|
||||
}
|
||||
|
||||
bool debugModeEnabled = false;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ int main(void) {
|
|||
CLAY_AUTO_ID({ .layout = layoutElement, .backgroundColor = {255,255,255,0} }) {
|
||||
CLAY_TEXT(CLAY_STRING(""), CLAY_TEXT_CONFIG({ .fontId = 0 }));
|
||||
}
|
||||
Clay_EndLayout();
|
||||
Clay_EndLayout(0);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
38
examples/raylib-transitions/CMakeLists.txt
Normal file
38
examples/raylib-transitions/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
cmake_minimum_required(VERSION 3.27)
|
||||
project(clay_examples_raylib_transitions C)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
# Adding Raylib
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_QUIET FALSE)
|
||||
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples
|
||||
set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # don't build the supplied example games
|
||||
|
||||
FetchContent_Declare(
|
||||
raylib
|
||||
GIT_REPOSITORY "https://github.com/raysan5/raylib.git"
|
||||
GIT_TAG "5.5"
|
||||
GIT_PROGRESS TRUE
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(raylib)
|
||||
|
||||
add_executable(clay_examples_raylib_transitions main.c)
|
||||
|
||||
target_compile_options(clay_examples_raylib_transitions PUBLIC)
|
||||
target_include_directories(clay_examples_raylib_transitions PUBLIC .)
|
||||
|
||||
target_link_libraries(clay_examples_raylib_transitions PUBLIC raylib)
|
||||
if(MSVC)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET clay_examples_raylib_transitions POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/resources
|
||||
${CMAKE_CURRENT_BINARY_DIR}/resources)
|
||||
422
examples/raylib-transitions/main.c
Normal file
422
examples/raylib-transitions/main.c
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
#define CLAY_IMPLEMENTATION
|
||||
#include "../../clay.h"
|
||||
#include "../../renderers/raylib/clay_renderer_raylib.c"
|
||||
|
||||
const uint32_t FONT_ID_BODY_24 = 0;
|
||||
const uint32_t FONT_ID_BODY_16 = 1;
|
||||
#define COLOR_ORANGE (Clay_Color) {225, 138, 50, 255}
|
||||
#define COLOR_BLUE (Clay_Color) {111, 173, 162, 255}
|
||||
|
||||
Texture2D profilePicture;
|
||||
#define RAYLIB_VECTOR2_TO_CLAY_VECTOR2(vector) (Clay_Vector2) { .x = vector.x, .y = vector.y }
|
||||
|
||||
Clay_String profileText = CLAY_STRING_CONST("Profile Page one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen");
|
||||
Clay_TextElementConfig headerTextConfig = { .fontId = 1, .letterSpacing = 5, .fontSize = 16, .textColor = {0,0,0,255} };
|
||||
|
||||
void HandleHeaderButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, intptr_t userData) {
|
||||
if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
|
||||
// Do some click handling
|
||||
}
|
||||
}
|
||||
|
||||
Clay_ElementDeclaration HeaderButtonStyle(bool hovered) {
|
||||
return (Clay_ElementDeclaration) {
|
||||
.layout = {.padding = {16, 16, 8, 8}},
|
||||
.backgroundColor = hovered ? COLOR_ORANGE : COLOR_BLUE,
|
||||
};
|
||||
}
|
||||
|
||||
// Examples of re-usable "Components"
|
||||
void RenderHeaderButton(Clay_String text) {
|
||||
CLAY_AUTO_ID(HeaderButtonStyle(Clay_Hovered())) {
|
||||
CLAY_TEXT(text, CLAY_TEXT_CONFIG(headerTextConfig));
|
||||
}
|
||||
}
|
||||
|
||||
Clay_LayoutConfig dropdownTextItemLayout = { .padding = {8, 8, 4, 4} };
|
||||
Clay_TextElementConfig dropdownTextElementConfig = { .fontSize = 24, .textColor = {255,255,255,255} };
|
||||
|
||||
void RenderDropdownTextItem(int index) {
|
||||
CLAY_AUTO_ID({ .layout = dropdownTextItemLayout, .backgroundColor = {180, 180, 180, 255} }) {
|
||||
CLAY_TEXT(CLAY_STRING("I'm a text field in a scroll container."), dropdownTextElementConfig);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
Clay_Color color;
|
||||
const char* stringId;
|
||||
} SortableBox;
|
||||
|
||||
int maxCount = 30;
|
||||
int cellCount = 30;
|
||||
char* charData;
|
||||
SortableBox colors[100] = {};
|
||||
|
||||
bool blueColor = 0;
|
||||
|
||||
#define GG { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }
|
||||
|
||||
#define cWHITE { 255, 255, 255, 255 }
|
||||
|
||||
typedef struct {
|
||||
int value;
|
||||
} Test;
|
||||
|
||||
typedef struct {
|
||||
void* memory;
|
||||
uintptr_t offset;
|
||||
} Arena;
|
||||
|
||||
Arena frameArena = {};
|
||||
|
||||
bool Clay_EaseOut(Clay_TransitionCallbackArguments arguments) {
|
||||
float ratio = 1;
|
||||
if (arguments.duration > 0) {
|
||||
ratio = arguments.elapsedTime / arguments.duration;
|
||||
}
|
||||
float lerpAmount = (1 - powf(1 - CLAY__MIN(ratio, 1.f), 3.0f));
|
||||
if (arguments.properties & CLAY_TRANSITION_PROPERTY_X) {
|
||||
arguments.current->boundingBox.x = Lerp(arguments.initial.boundingBox.x, arguments.target.boundingBox.x, lerpAmount);
|
||||
}
|
||||
if (arguments.properties & CLAY_TRANSITION_PROPERTY_Y) {
|
||||
arguments.current->boundingBox.y = Lerp(arguments.initial.boundingBox.y, arguments.target.boundingBox.y, lerpAmount);
|
||||
}
|
||||
if (arguments.properties & CLAY_TRANSITION_PROPERTY_WIDTH) {
|
||||
arguments.current->boundingBox.width = Lerp(arguments.initial.boundingBox.width, arguments.target.boundingBox.width, lerpAmount);
|
||||
}
|
||||
if (arguments.properties & CLAY_TRANSITION_PROPERTY_HEIGHT) {
|
||||
arguments.current->boundingBox.height = Lerp(arguments.initial.boundingBox.height, arguments.target.boundingBox.height, lerpAmount);
|
||||
}
|
||||
if (arguments.properties & CLAY_TRANSITION_PROPERTY_BACKGROUND_COLOR) {
|
||||
arguments.current->backgroundColor = CLAY__INIT(Clay_Color) {
|
||||
.r = Lerp(arguments.initial.backgroundColor.r, arguments.target.backgroundColor.r, lerpAmount),
|
||||
.g = Lerp(arguments.initial.backgroundColor.g, arguments.target.backgroundColor.g, lerpAmount),
|
||||
.b = Lerp(arguments.initial.backgroundColor.b, arguments.target.backgroundColor.b, lerpAmount),
|
||||
.a = Lerp(arguments.initial.backgroundColor.a, arguments.target.backgroundColor.a, lerpAmount),
|
||||
};
|
||||
}
|
||||
if (arguments.properties & CLAY_TRANSITION_PROPERTY_OVERLAY_COLOR) {
|
||||
arguments.current->overlayColor = CLAY__INIT(Clay_Color) {
|
||||
.r = Lerp(arguments.initial.overlayColor.r, arguments.target.overlayColor.r, lerpAmount),
|
||||
.g = Lerp(arguments.initial.overlayColor.g, arguments.target.overlayColor.g, lerpAmount),
|
||||
.b = Lerp(arguments.initial.overlayColor.b, arguments.target.overlayColor.b, lerpAmount),
|
||||
.a = Lerp(arguments.initial.overlayColor.a, arguments.target.overlayColor.a, lerpAmount),
|
||||
};
|
||||
}
|
||||
if (arguments.properties & CLAY_TRANSITION_PROPERTY_BORDER_COLOR) {
|
||||
arguments.current->borderColor = CLAY__INIT(Clay_Color) {
|
||||
.r = Lerp(arguments.initial.borderColor.r, arguments.target.borderColor.r, lerpAmount),
|
||||
.g = Lerp(arguments.initial.borderColor.g, arguments.target.borderColor.g, lerpAmount),
|
||||
.b = Lerp(arguments.initial.borderColor.b, arguments.target.borderColor.b, lerpAmount),
|
||||
.a = Lerp(arguments.initial.borderColor.a, arguments.target.borderColor.a, lerpAmount),
|
||||
};
|
||||
}
|
||||
if (arguments.properties & CLAY_TRANSITION_PROPERTY_BORDER_WIDTH) {
|
||||
arguments.current->borderWidth = CLAY__INIT(Clay_BorderWidth) {
|
||||
.left = Lerp(arguments.initial.borderWidth.left, arguments.target.borderWidth.left, lerpAmount),
|
||||
.right = Lerp(arguments.initial.borderWidth.right, arguments.target.borderWidth.right, lerpAmount),
|
||||
.top = Lerp(arguments.initial.borderWidth.top, arguments.target.borderWidth.top, lerpAmount),
|
||||
.bottom = Lerp(arguments.initial.borderWidth.bottom, arguments.target.borderWidth.bottom, lerpAmount),
|
||||
.betweenChildren = Lerp(arguments.initial.borderWidth.betweenChildren, arguments.target.borderWidth.betweenChildren, lerpAmount),
|
||||
};
|
||||
}
|
||||
return ratio >= 1;
|
||||
}
|
||||
|
||||
Clay_TransitionData EnterExitSlideUp(Clay_TransitionData initialState, Clay_TransitionProperty properties) {
|
||||
Clay_TransitionData targetState = initialState;
|
||||
if (properties & CLAY_TRANSITION_PROPERTY_Y) {
|
||||
targetState.boundingBox.y += 20;
|
||||
}
|
||||
if (properties & CLAY_TRANSITION_PROPERTY_OVERLAY_COLOR) {
|
||||
targetState.overlayColor = (Clay_Color) { 255, 255, 255, 255 };
|
||||
}
|
||||
return targetState;
|
||||
}
|
||||
// Swaps two elements in an array
|
||||
void swap(SortableBox *a, SortableBox *b) {
|
||||
SortableBox temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
}
|
||||
|
||||
void shuffle(SortableBox *array, size_t n) {
|
||||
if (n <= 1) return;
|
||||
|
||||
for (size_t i = n - 1; i > 0; i--) {
|
||||
size_t j = rand() % (i + 1);
|
||||
swap(&array[i], &array[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void add(SortableBox *array, int32_t length, int32_t index, SortableBox toAdd) {
|
||||
for (int i = length; i > index; --i) {
|
||||
array[i] = array[i - 1];
|
||||
}
|
||||
array[index] = toAdd;
|
||||
}
|
||||
|
||||
void HandleRandomiseButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, void *userData) {
|
||||
if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
|
||||
shuffle(colors, cellCount);
|
||||
}
|
||||
}
|
||||
|
||||
void HandlePinkButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, void *userData) {
|
||||
if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
|
||||
for (int i = 0; i < cellCount; i++) {
|
||||
int index = colors[i].id;
|
||||
colors[i] = (SortableBox) {
|
||||
.id = index,
|
||||
.color = { 255 - index, 255 - index * 4, 255 - index * 2, 255 },
|
||||
.stringId = colors[i].stringId
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleNewButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, void *userData) {
|
||||
if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
|
||||
int32_t randomIndex = rand() % (cellCount + 1);
|
||||
int32_t newId = maxCount;
|
||||
snprintf(&charData[newId * 3], 3, "%02d", newId);
|
||||
|
||||
add(colors, maxCount, randomIndex, (SortableBox) {
|
||||
.id = newId,
|
||||
.color = { 255 - newId, 255 - newId * 4, 255 - newId * 2, 255 },
|
||||
.stringId = &charData[newId * 3]
|
||||
});
|
||||
|
||||
cellCount++;
|
||||
maxCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleBlueButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, void *userData) {
|
||||
if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
|
||||
for (int i = 0; i < cellCount; i++) {
|
||||
int index = colors[i].id;
|
||||
colors[i] = (SortableBox) {
|
||||
.id = index,
|
||||
.color = { 255 - index * 4, 255 - index * 2, 255 - index, 255 },
|
||||
.stringId = colors[i].stringId
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleCellButtonInteraction(Clay_ElementId elementId, Clay_PointerData pointerData, void *userData) {
|
||||
if (pointerData.state == CLAY_POINTER_DATA_PRESSED_THIS_FRAME) {
|
||||
for (int i = (uintptr_t)userData; i < cellCount; i++) {
|
||||
colors[i] = colors[i + 1];
|
||||
}
|
||||
cellCount = CLAY__MAX(cellCount - 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Clay_RenderCommandArray CreateLayout(void) {
|
||||
frameArena.offset = 0;
|
||||
Clay_BeginLayout();
|
||||
CLAY(CLAY_ID("OuterContainer"), { .layout = { .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) }, .padding = { 16, 16, 16, 16 }, .childGap = 12 }, .backgroundColor = cWHITE }) {
|
||||
CLAY_AUTO_ID({ .layout.sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIXED(60) }, .layout.padding.left = 16, .layout.childGap = 16, .layout.childAlignment.y = CLAY_ALIGN_Y_CENTER, .cornerRadius = { 12, 12, 12, 12 }, .backgroundColor = {174, 143, 204, 255 } }) {
|
||||
CLAY(CLAY_ID("ShuffleButton"), {
|
||||
.backgroundColor = Clay_Hovered() ? (Clay_Color){ 154, 123, 184, 255 } : (Clay_Color){ },
|
||||
.layout.padding = { 16, 16, 8, 8 },
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(6),
|
||||
.border = { .color = cWHITE, .width = CLAY_BORDER_OUTSIDE(2) },
|
||||
}) {
|
||||
Clay_OnHover(HandleRandomiseButtonInteraction, 0);
|
||||
CLAY_TEXT(CLAY_STRING("Randomise"), CLAY_TEXT_CONFIG({ .fontSize = 20, .textColor = cWHITE }));
|
||||
}
|
||||
CLAY(CLAY_ID("bluebutton"), {
|
||||
.backgroundColor = Clay_Hovered() ? (Clay_Color){ 154, 123, 184, 255 } : (Clay_Color){ },
|
||||
.layout.padding = { 16, 16, 8, 8 },
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(6),
|
||||
.border = { .color = cWHITE, .width = CLAY_BORDER_OUTSIDE(2) },
|
||||
}) {
|
||||
Clay_OnHover(HandleBlueButtonInteraction, 0);
|
||||
CLAY_TEXT(CLAY_STRING("Blue"), CLAY_TEXT_CONFIG({ .fontSize = 20, .textColor = cWHITE }));
|
||||
}
|
||||
CLAY(CLAY_ID("PinkButton"), {
|
||||
.backgroundColor = Clay_Hovered() ? (Clay_Color){ 154, 123, 184, 255 } : (Clay_Color){ },
|
||||
.layout.padding = { 16, 16, 8, 8 },
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(6),
|
||||
.border = { .color = cWHITE, .width = CLAY_BORDER_OUTSIDE(2) },
|
||||
}) {
|
||||
Clay_OnHover(HandlePinkButtonInteraction, 0);
|
||||
CLAY_TEXT(CLAY_STRING("Pink"), CLAY_TEXT_CONFIG({ .fontSize = 20, .textColor = cWHITE }));
|
||||
}
|
||||
CLAY(CLAY_ID("AddButton"), {
|
||||
.backgroundColor = Clay_Hovered() ? (Clay_Color){ 154, 123, 184, 255 } : (Clay_Color){ },
|
||||
.layout.padding = { 16, 16, 8, 8 },
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(6),
|
||||
.border = { .color = cWHITE, .width = CLAY_BORDER_OUTSIDE(2) },
|
||||
}) {
|
||||
Clay_OnHover(HandleNewButtonInteraction, 0);
|
||||
CLAY_TEXT(CLAY_STRING("Add Box"), CLAY_TEXT_CONFIG({ .fontSize = 20, .textColor = cWHITE }));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Clay_ElementId rowId = CLAY_IDI("row", i);
|
||||
Clay_ElementData rowData = Clay_GetElementData(rowId);
|
||||
CLAY(rowId, { .layout.childGap = 12, .layout.sizing = GG }) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
int index = i * 6 + j;
|
||||
if (index >= cellCount) {
|
||||
break;
|
||||
}
|
||||
Clay_Color boxColor = colors[index].color;
|
||||
Clay_Color darker = { boxColor.r * 0.9, boxColor.g * 0.9, boxColor.b * 0.9, 255 };
|
||||
CLAY(CLAY_IDI("box", colors[index].id), {
|
||||
.layout.sizing = {CLAY_SIZING_GROW(), CLAY_SIZING_GROW() },
|
||||
.layout.childAlignment = { CLAY_ALIGN_X_CENTER, CLAY_ALIGN_Y_CENTER },
|
||||
.backgroundColor = boxColor,
|
||||
.overlayColor = Clay_Hovered() ? (Clay_Color) { 140, 140, 140, 80 } : (Clay_Color) { 255, 255, 255, 0 },
|
||||
.cornerRadius = {12, 12, 12, 12},
|
||||
.border = { darker, CLAY_BORDER_OUTSIDE(3) },
|
||||
.transition = {
|
||||
.handler = Clay_EaseOut,
|
||||
.duration = Clay_Hovered() && Clay_GetPointerState().state != CLAY_POINTER_DATA_PRESSED_THIS_FRAME ? 0.f : 0.5f,
|
||||
.properties = CLAY_TRANSITION_PROPERTY_WIDTH | CLAY_TRANSITION_PROPERTY_POSITION | CLAY_TRANSITION_PROPERTY_OVERLAY_COLOR | CLAY_TRANSITION_PROPERTY_BACKGROUND_COLOR,
|
||||
.enter = { .setInitialState = EnterExitSlideUp },
|
||||
.exit = { .setFinalState = EnterExitSlideUp },
|
||||
}
|
||||
}) {
|
||||
Clay_OnHover(HandleCellButtonInteraction, (void*)(uint64_t)index);
|
||||
CLAY_TEXT(((Clay_String) { .length = 2, .chars = colors[index].stringId, .isStaticallyAllocated = true }), CLAY_TEXT_CONFIG({
|
||||
.fontSize = 32,
|
||||
.textColor = colors[index].id > 29 ? (Clay_Color) {255, 255, 255, 255} : (Clay_Color) {154, 123, 184, 255 }
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Clay_EndLayout(GetFrameTime());
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Clay_Vector2 clickOrigin;
|
||||
Clay_Vector2 positionOrigin;
|
||||
bool mouseDown;
|
||||
} ScrollbarData;
|
||||
|
||||
ScrollbarData scrollbarData = {0};
|
||||
|
||||
bool debugEnabled = false;
|
||||
|
||||
void UpdateDrawFrame(Font* fonts)
|
||||
{
|
||||
Vector2 mouseWheelDelta = GetMouseWheelMoveV();
|
||||
float mouseWheelX = mouseWheelDelta.x;
|
||||
float mouseWheelY = mouseWheelDelta.y;
|
||||
|
||||
if (IsKeyPressed(KEY_D)) {
|
||||
debugEnabled = !debugEnabled;
|
||||
Clay_SetDebugModeEnabled(debugEnabled);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
// Handle scroll containers
|
||||
Clay_Vector2 mousePosition = RAYLIB_VECTOR2_TO_CLAY_VECTOR2(GetMousePosition());
|
||||
Clay_SetPointerState(mousePosition, IsMouseButtonDown(0) && !scrollbarData.mouseDown);
|
||||
Clay_SetLayoutDimensions((Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() });
|
||||
if (!IsMouseButtonDown(0)) {
|
||||
scrollbarData.mouseDown = false;
|
||||
}
|
||||
|
||||
if (IsMouseButtonDown(0) && !scrollbarData.mouseDown && Clay_PointerOver(Clay__HashString(CLAY_STRING("ScrollBar"), 0))) {
|
||||
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay__HashString(CLAY_STRING("MainContent"), 0));
|
||||
scrollbarData.clickOrigin = mousePosition;
|
||||
scrollbarData.positionOrigin = *scrollContainerData.scrollPosition;
|
||||
scrollbarData.mouseDown = true;
|
||||
} else if (scrollbarData.mouseDown) {
|
||||
Clay_ScrollContainerData scrollContainerData = Clay_GetScrollContainerData(Clay__HashString(CLAY_STRING("MainContent"), 0));
|
||||
if (scrollContainerData.contentDimensions.height > 0) {
|
||||
Clay_Vector2 ratio = (Clay_Vector2) {
|
||||
scrollContainerData.contentDimensions.width / scrollContainerData.scrollContainerDimensions.width,
|
||||
scrollContainerData.contentDimensions.height / scrollContainerData.scrollContainerDimensions.height,
|
||||
};
|
||||
if (scrollContainerData.config.vertical) {
|
||||
scrollContainerData.scrollPosition->y = scrollbarData.positionOrigin.y + (scrollbarData.clickOrigin.y - mousePosition.y) * ratio.y;
|
||||
}
|
||||
if (scrollContainerData.config.horizontal) {
|
||||
scrollContainerData.scrollPosition->x = scrollbarData.positionOrigin.x + (scrollbarData.clickOrigin.x - mousePosition.x) * ratio.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Clay_UpdateScrollContainers(true, (Clay_Vector2) {mouseWheelX, mouseWheelY}, GetFrameTime());
|
||||
// Generate the auto layout for rendering
|
||||
double currentTime = GetTime();
|
||||
Clay_RenderCommandArray renderCommands = CreateLayout();
|
||||
printf("layout time: %f microseconds\n", (GetTime() - currentTime) * 1000 * 1000);
|
||||
// RENDERING ---------------------------------
|
||||
// currentTime = GetTime();
|
||||
BeginDrawing();
|
||||
ClearBackground(BLACK);
|
||||
Clay_Raylib_Render(renderCommands, fonts);
|
||||
EndDrawing();
|
||||
// printf("render time: %f ms\n", (GetTime() - currentTime) * 1000);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
bool reinitializeClay = false;
|
||||
|
||||
void HandleClayErrors(Clay_ErrorData errorData) {
|
||||
printf("%s\n", errorData.errorText.chars);
|
||||
if (errorData.errorType == CLAY_ERROR_TYPE_ELEMENTS_CAPACITY_EXCEEDED) {
|
||||
reinitializeClay = true;
|
||||
Clay_SetMaxElementCount(Clay_GetMaxElementCount() * 2);
|
||||
} else if (errorData.errorType == CLAY_ERROR_TYPE_TEXT_MEASUREMENT_CAPACITY_EXCEEDED) {
|
||||
reinitializeClay = true;
|
||||
Clay_SetMaxMeasureTextCacheWordCount(Clay_GetMaxMeasureTextCacheWordCount() * 2);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
uint64_t totalMemorySize = Clay_MinMemorySize();
|
||||
Clay_Arena clayMemory = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
|
||||
Clay_Context *context = Clay_Initialize(clayMemory, (Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() }, (Clay_ErrorHandler) { HandleClayErrors, 0 });
|
||||
Clay_Raylib_Initialize(1024, 768, "Clay - Raylib Renderer Example", FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE | FLAG_MSAA_4X_HINT);
|
||||
profilePicture = LoadTexture("resources/profile-picture.png");
|
||||
|
||||
Font fonts[2];
|
||||
fonts[FONT_ID_BODY_24] = LoadFontEx("resources/Roboto-Regular.ttf", 48, 0, 400);
|
||||
SetTextureFilter(fonts[FONT_ID_BODY_24].texture, TEXTURE_FILTER_BILINEAR);
|
||||
fonts[FONT_ID_BODY_16] = LoadFontEx("resources/Roboto-Regular.ttf", 32, 0, 400);
|
||||
SetTextureFilter(fonts[FONT_ID_BODY_16].texture, TEXTURE_FILTER_BILINEAR);
|
||||
Clay_SetMeasureTextFunction(Raylib_MeasureText, fonts);
|
||||
|
||||
frameArena = (Arena) {.memory = malloc(1024) };
|
||||
|
||||
charData = (char*)malloc(100 * 3);
|
||||
|
||||
for (int i = 0; i < cellCount; i++) {
|
||||
snprintf(&charData[i * 3], 3, "%02d", i);
|
||||
colors[i] = (SortableBox) {
|
||||
.id = i,
|
||||
.color = { 255 - i, 255 - i * 4, 255 - i * 2, 255 },
|
||||
.stringId = &charData[i * 3],
|
||||
};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
if (reinitializeClay) {
|
||||
Clay_SetMaxElementCount(8192);
|
||||
totalMemorySize = Clay_MinMemorySize();
|
||||
clayMemory = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
|
||||
Clay_Initialize(clayMemory, (Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() }, (Clay_ErrorHandler) { HandleClayErrors, 0 });
|
||||
reinitializeClay = false;
|
||||
}
|
||||
UpdateDrawFrame(fonts);
|
||||
}
|
||||
Clay_Raylib_Close();
|
||||
return 0;
|
||||
}
|
||||
BIN
examples/raylib-transitions/resources/Roboto-Regular.ttf
Normal file
BIN
examples/raylib-transitions/resources/Roboto-Regular.ttf
Normal file
Binary file not shown.
|
|
@ -256,7 +256,7 @@ Clay_RenderCommandArray ClayVideoDemo_CreateLayout(ClayVideoDemo_Data *data) {
|
|||
}
|
||||
}
|
||||
|
||||
Clay_RenderCommandArray renderCommands = Clay_EndLayout();
|
||||
Clay_RenderCommandArray renderCommands = Clay_EndLayout(0);
|
||||
for (int32_t i = 0; i < renderCommands.length; i++) {
|
||||
Clay_RenderCommandArray_Get(&renderCommands, i)->boundingBox.y += data->yOffset;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ Clay_RenderCommandArray CornerRadiusTest(){
|
|||
}
|
||||
}
|
||||
}
|
||||
return Clay_EndLayout();
|
||||
return Clay_EndLayout(0);
|
||||
}
|
||||
|
||||
static void frame() {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,54 @@ typedef struct
|
|||
} customData;
|
||||
} CustomLayoutElement;
|
||||
|
||||
const char* overlayShaderCode = "#version 330\n"
|
||||
"\n"
|
||||
"in vec2 fragTexCoord;\n"
|
||||
"in vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D texture0;\n"
|
||||
"uniform vec4 overlayColor;\n"
|
||||
"\n"
|
||||
"out vec4 finalColor;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 texelColor = texture(texture0, fragTexCoord) * fragColor;\n"
|
||||
"\n"
|
||||
" vec3 blendedRGB = mix(texelColor.rgb, overlayColor.rgb, overlayColor.a);\n"
|
||||
"\n"
|
||||
" finalColor = vec4(blendedRGB, texelColor.a);\n"
|
||||
"}";
|
||||
|
||||
Shader overlayShader;
|
||||
int colorLoc;
|
||||
bool overlayEnabled = false;
|
||||
|
||||
void InitOverlay() {
|
||||
overlayShader = LoadShaderFromMemory(0, overlayShaderCode);
|
||||
colorLoc = GetShaderLocation(overlayShader, "overlayColor");
|
||||
}
|
||||
|
||||
void SetColorOverlay(Color color) {
|
||||
overlayEnabled = true;
|
||||
float colorFloat[4] = {
|
||||
(float)color.r/255.0f,
|
||||
(float)color.g/255.0f,
|
||||
(float)color.b/255.0f,
|
||||
(float)color.a/255.0f,
|
||||
};
|
||||
|
||||
SetShaderValue(overlayShader, colorLoc, colorFloat, SHADER_UNIFORM_VEC4);
|
||||
BeginShaderMode(overlayShader);
|
||||
}
|
||||
|
||||
void DisableColorOverlay() {
|
||||
if (overlayEnabled) {
|
||||
EndShaderMode();
|
||||
overlayEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get a ray trace from the screen position (i.e mouse) within a specific section of the screen
|
||||
Ray GetScreenToWorldPointWithZDistance(Vector2 position, Camera camera, int screenWidth, int screenHeight, float zDistance)
|
||||
{
|
||||
|
|
@ -127,6 +175,7 @@ static inline Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_Tex
|
|||
void Clay_Raylib_Initialize(int width, int height, const char *title, unsigned int flags) {
|
||||
SetConfigFlags(flags);
|
||||
InitWindow(width, height, title);
|
||||
InitOverlay();
|
||||
// EnableEventWaiting();
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +199,7 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands, Font* fonts)
|
|||
for (int j = 0; j < renderCommands.length; j++)
|
||||
{
|
||||
Clay_RenderCommand *renderCommand = Clay_RenderCommandArray_Get(&renderCommands, j);
|
||||
Clay_BoundingBox boundingBox = {roundf(renderCommand->boundingBox.x), roundf(renderCommand->boundingBox.y), roundf(renderCommand->boundingBox.width), roundf(renderCommand->boundingBox.height)};
|
||||
Clay_BoundingBox boundingBox = {renderCommand->boundingBox.x, renderCommand->boundingBox.y, renderCommand->boundingBox.width, renderCommand->boundingBox.height};
|
||||
switch (renderCommand->commandType)
|
||||
{
|
||||
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
||||
|
|
@ -196,6 +245,13 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands, Font* fonts)
|
|||
EndScissorMode();
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_OVERLAY_COLOR_START: {
|
||||
SetColorOverlay(CLAY_COLOR_TO_RAYLIB_COLOR(renderCommand->renderData.overlayColor.color));
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_OVERLAY_COLOR_END: {
|
||||
DisableColorOverlay();
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
|
||||
Clay_RectangleRenderData *config = &renderCommand->renderData.rectangle;
|
||||
if (config->cornerRadius.topLeft > 0) {
|
||||
|
|
@ -210,19 +266,19 @@ void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands, Font* fonts)
|
|||
Clay_BorderRenderData *config = &renderCommand->renderData.border;
|
||||
// Left border
|
||||
if (config->width.left > 0) {
|
||||
DrawRectangle((int)roundf(boundingBox.x), (int)roundf(boundingBox.y + config->cornerRadius.topLeft), (int)config->width.left, (int)roundf(boundingBox.height - config->cornerRadius.topLeft - config->cornerRadius.bottomLeft), CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
DrawRectangleV((Vector2) { boundingBox.x, boundingBox.y + config->cornerRadius.topLeft }, (Vector2) { config->width.left, boundingBox.height - config->cornerRadius.topLeft - config->cornerRadius.bottomLeft }, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
}
|
||||
// Right border
|
||||
if (config->width.right > 0) {
|
||||
DrawRectangle((int)roundf(boundingBox.x + boundingBox.width - config->width.right), (int)roundf(boundingBox.y + config->cornerRadius.topRight), (int)config->width.right, (int)roundf(boundingBox.height - config->cornerRadius.topRight - config->cornerRadius.bottomRight), CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
DrawRectangleV((Vector2) { boundingBox.x + boundingBox.width - config->width.right, boundingBox.y + config->cornerRadius.topRight }, (Vector2) { config->width.right, boundingBox.height - config->cornerRadius.topRight - config->cornerRadius.bottomRight }, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
}
|
||||
// Top border
|
||||
if (config->width.top > 0) {
|
||||
DrawRectangle((int)roundf(boundingBox.x + config->cornerRadius.topLeft), (int)roundf(boundingBox.y), (int)roundf(boundingBox.width - config->cornerRadius.topLeft - config->cornerRadius.topRight), (int)config->width.top, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
DrawRectangleV((Vector2) { boundingBox.x + config->cornerRadius.topLeft, boundingBox.y }, (Vector2) { boundingBox.width - config->cornerRadius.topLeft - config->cornerRadius.topRight, (int)config->width.top }, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
}
|
||||
// Bottom border
|
||||
if (config->width.bottom > 0) {
|
||||
DrawRectangle((int)roundf(boundingBox.x + config->cornerRadius.bottomLeft), (int)roundf(boundingBox.y + boundingBox.height - config->width.bottom), (int)roundf(boundingBox.width - config->cornerRadius.bottomLeft - config->cornerRadius.bottomRight), (int)config->width.bottom, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
DrawRectangleV((Vector2) { boundingBox.x + config->cornerRadius.bottomLeft, boundingBox.y + boundingBox.height - config->width.bottom }, (Vector2) { boundingBox.width - config->cornerRadius.bottomLeft - config->cornerRadius.bottomRight, (int)config->width.bottom }, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
}
|
||||
if (config->cornerRadius.topLeft > 0) {
|
||||
DrawRing((Vector2) { roundf(boundingBox.x + config->cornerRadius.topLeft), roundf(boundingBox.y + config->cornerRadius.topLeft) }, roundf(config->cornerRadius.topLeft - config->width.top), config->cornerRadius.topLeft, 180, 270, 10, CLAY_COLOR_TO_RAYLIB_COLOR(config->color));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue