mirror of
https://github.com/nicbarker/clay.git
synced 2025-04-15 10:48:04 +00:00
Merge b0fe41186c
into a093730da2
This commit is contained in:
commit
5459548a24
@ -9,6 +9,7 @@ add_subdirectory("examples/raylib-sidebar-scrolling-container")
|
||||
# add_subdirectory("examples/cairo-pdf-rendering") Some issue with github actions populating cairo, disable for now
|
||||
if(NOT MSVC)
|
||||
add_subdirectory("examples/clay-official-website")
|
||||
add_subdirectory("examples/terminal-example")
|
||||
endif()
|
||||
add_subdirectory("examples/introducing-clay-video-demo")
|
||||
add_subdirectory("examples/SDL2-video-demo")
|
||||
|
12
examples/terminal-example/CMakeLists.txt
Normal file
12
examples/terminal-example/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
project(clay_examples_terminal C)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
add_executable(clay_examples_terminal main.c)
|
||||
|
||||
target_compile_options(clay_examples_terminal PUBLIC)
|
||||
target_include_directories(clay_examples_terminal PUBLIC .)
|
||||
|
||||
target_link_libraries(clay_examples_terminal PUBLIC ${CURSES_LIBRARY})
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Werror -DCLAY_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
|
57
examples/terminal-example/main.c
Normal file
57
examples/terminal-example/main.c
Normal file
@ -0,0 +1,57 @@
|
||||
// Must be defined in one file, _before_ #include "clay.h"
|
||||
#define CLAY_IMPLEMENTATION
|
||||
|
||||
#include <unistd.h>
|
||||
#include "../../clay.h"
|
||||
#include "../../renderers/terminal/clay_renderer_terminal.c"
|
||||
|
||||
const Clay_Color COLOR_LIGHT = (Clay_Color) {224, 215, 210, 255};
|
||||
const Clay_Color COLOR_RED = (Clay_Color) {168, 66, 28, 255};
|
||||
const Clay_Color COLOR_ORANGE = (Clay_Color) {225, 138, 50, 255};
|
||||
|
||||
// An example function to begin the "root" of your layout tree
|
||||
Clay_RenderCommandArray CreateLayout() {
|
||||
Clay_BeginLayout();
|
||||
|
||||
CLAY(CLAY_ID("OuterContainer"),
|
||||
CLAY_LAYOUT({.layoutDirection = CLAY_LEFT_TO_RIGHT, .sizing = {CLAY_SIZING_GROW(), CLAY_SIZING_GROW()}, }),
|
||||
CLAY_RECTANGLE({ .color = {0,0,0,255} })) {
|
||||
CLAY(CLAY_ID("SideBar"),
|
||||
CLAY_LAYOUT({.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = {.width = CLAY_SIZING_PERCENT(
|
||||
0.5), .height = CLAY_SIZING_PERCENT(1)}}),
|
||||
CLAY_RECTANGLE({.color = (Clay_Color) {255, 255, 255, 255}})
|
||||
) {
|
||||
}
|
||||
CLAY(CLAY_ID("OtherSideBar"),
|
||||
CLAY_LAYOUT({.layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = {.width = CLAY_SIZING_PERCENT(
|
||||
0.5), .height = CLAY_SIZING_PERCENT(1)}}),
|
||||
CLAY_RECTANGLE({ .color = {0,0, 0, 255 }})
|
||||
) {
|
||||
// TODO font size is wrong, only one is allowed, but I don't know which it is
|
||||
CLAY_TEXT(CLAY_STRING("0123456789 0123456 78901 234567 89012 34567 8901234567890 123456789"),
|
||||
CLAY_TEXT_CONFIG({ .fontId = 0, .fontSize = 24, .textColor = {255,255,255,255} }));
|
||||
}
|
||||
}
|
||||
|
||||
return Clay_EndLayout();
|
||||
}
|
||||
|
||||
int main() {
|
||||
const int width = 80;
|
||||
const int height = 24;
|
||||
|
||||
uint64_t totalMemorySize = Clay_MinMemorySize();
|
||||
Clay_Arena arena = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
|
||||
Clay_Initialize(arena, (Clay_Dimensions) { .width = (float) width, .height = (float) height }); // TODO this is wrong, but I have no idea what the actual size of the terminal is in pixels
|
||||
// Tell clay how to measure text
|
||||
Clay_SetMeasureTextFunction(Console_MeasureText);
|
||||
|
||||
while(true) {
|
||||
Clay_RenderCommandArray layout = CreateLayout();
|
||||
|
||||
Clay_Console_Render(layout, width, height);
|
||||
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
190
renderers/terminal/clay_renderer_terminal.c
Normal file
190
renderers/terminal/clay_renderer_terminal.c
Normal file
@ -0,0 +1,190 @@
|
||||
#include "stdint.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "math.h"
|
||||
#ifdef CLAY_OVERFLOW_TRAP
|
||||
#include "signal.h"
|
||||
#endif
|
||||
|
||||
static inline void Console_MoveCursor(int x, int y) {
|
||||
printf("\033[%d;%dH", y+1, x+1);
|
||||
}
|
||||
|
||||
bool Clay_PointIsInsideRect(Clay_Vector2 point, Clay_BoundingBox rect) {
|
||||
// TODO this function is a copy of Clay__PointIsInsideRect but that one is internal, I don't know if we want
|
||||
// TODO to expose Clay__PointIsInsideRect
|
||||
return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
||||
}
|
||||
|
||||
static inline void Console_DrawRectangle(int x0, int y0, int width, int height, Clay_Color color,
|
||||
Clay_BoundingBox scissorBox) {
|
||||
if (color.r < 127 || color.g < 127 || color.b < 127 || color.a < 127) {
|
||||
// For now there are only two colors,
|
||||
return;
|
||||
}
|
||||
|
||||
for (int y = y0; y < height; y++) {
|
||||
for (int x = x0; x < width; x++) {
|
||||
if(!Clay_PointIsInsideRect((Clay_Vector2) { .x = x, .y = y }, scissorBox)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Console_MoveCursor(x, y);
|
||||
// TODO there are only two colors actually drawn, the background and white
|
||||
if (color.r < 127 || color.g < 127 || color.b < 127 || color.a < 127) {
|
||||
printf(" ");
|
||||
} else {
|
||||
printf("▪");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline Clay_Dimensions Console_MeasureText(Clay_String *text, Clay_TextElementConfig *config) {
|
||||
Clay_Dimensions textSize = { 0 };
|
||||
|
||||
// TODO this function is very wrong, it measures in characters, I have no idea what is the size in pixels
|
||||
|
||||
float maxTextWidth = 0.0f;
|
||||
float lineTextWidth = 0;
|
||||
|
||||
float textHeight = 1;
|
||||
|
||||
for (int i = 0; i < text->length; ++i)
|
||||
{
|
||||
if (text->chars[i] == '\n') {
|
||||
maxTextWidth = maxTextWidth > lineTextWidth ? maxTextWidth : lineTextWidth;
|
||||
lineTextWidth = 0;
|
||||
textHeight++;
|
||||
continue;
|
||||
}
|
||||
lineTextWidth++;
|
||||
}
|
||||
|
||||
maxTextWidth = maxTextWidth > lineTextWidth ? maxTextWidth : lineTextWidth;
|
||||
|
||||
textSize.width = maxTextWidth;
|
||||
textSize.height = textHeight;
|
||||
|
||||
return textSize;
|
||||
}
|
||||
|
||||
void Clay_Raylib_Initialize(int width, int height, const char *title, unsigned int flags) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
void Clay_Console_Render(Clay_RenderCommandArray renderCommands, int width, int height)
|
||||
{
|
||||
printf("\033[H\033[J"); // Clear
|
||||
|
||||
const Clay_BoundingBox fullWindow = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = (float) width,
|
||||
.height = (float) height,
|
||||
};
|
||||
|
||||
Clay_BoundingBox scissorBox = fullWindow;
|
||||
|
||||
for (int j = 0; j < renderCommands.length; j++)
|
||||
{
|
||||
Clay_RenderCommand *renderCommand = Clay_RenderCommandArray_Get(&renderCommands, j);
|
||||
Clay_BoundingBox boundingBox = renderCommand->boundingBox;
|
||||
switch (renderCommand->commandType)
|
||||
{
|
||||
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
||||
Clay_String text = renderCommand->text;
|
||||
int y = 0;
|
||||
for (int x = 0; x < text.length; x++) {
|
||||
if(text.chars[x] == '\n') {
|
||||
y++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int cursorX = (int) boundingBox.x + x;
|
||||
int cursorY = (int) boundingBox.y + y;
|
||||
if(!Clay_PointIsInsideRect((Clay_Vector2) { .x = cursorX, .y = cursorY }, scissorBox)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Console_MoveCursor(cursorX, cursorY);
|
||||
printf("%c", text.chars[x]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START: {
|
||||
scissorBox = boundingBox;
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END: {
|
||||
scissorBox = fullWindow;
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
|
||||
Clay_RectangleElementConfig *config = renderCommand->config.rectangleElementConfig;
|
||||
Console_DrawRectangle(
|
||||
(int)boundingBox.x,
|
||||
(int)boundingBox.y,
|
||||
(int)boundingBox.width,
|
||||
(int)boundingBox.height,
|
||||
config->color,
|
||||
scissorBox);
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_BORDER: {
|
||||
Clay_BorderElementConfig *config = renderCommand->config.borderElementConfig;
|
||||
// Left border
|
||||
if (config->left.width > 0) {
|
||||
Console_DrawRectangle(
|
||||
(int)(boundingBox.x),
|
||||
(int)(boundingBox.y + config->cornerRadius.topLeft),
|
||||
(int)config->left.width,
|
||||
(int)(boundingBox.height - config->cornerRadius.topLeft - config->cornerRadius.bottomLeft),
|
||||
config->left.color,
|
||||
scissorBox);
|
||||
}
|
||||
// Right border
|
||||
if (config->right.width > 0) {
|
||||
Console_DrawRectangle(
|
||||
(int)(boundingBox.x + boundingBox.width - config->right.width),
|
||||
(int)(boundingBox.y + config->cornerRadius.topRight),
|
||||
(int)config->right.width,
|
||||
(int)(boundingBox.height - config->cornerRadius.topRight - config->cornerRadius.bottomRight),
|
||||
config->right.color,
|
||||
scissorBox);
|
||||
}
|
||||
// Top border
|
||||
if (config->top.width > 0) {
|
||||
Console_DrawRectangle(
|
||||
(int)(boundingBox.x + config->cornerRadius.topLeft),
|
||||
(int)(boundingBox.y),
|
||||
(int)(boundingBox.width - config->cornerRadius.topLeft - config->cornerRadius.topRight),
|
||||
(int)config->top.width,
|
||||
config->top.color,
|
||||
scissorBox);
|
||||
}
|
||||
// Bottom border
|
||||
if (config->bottom.width > 0) {
|
||||
Console_DrawRectangle(
|
||||
(int)(boundingBox.x + config->cornerRadius.bottomLeft),
|
||||
(int)(boundingBox.y + boundingBox.height - config->bottom.width),
|
||||
(int)(boundingBox.width - config->cornerRadius.bottomLeft - config->cornerRadius.bottomRight),
|
||||
(int)config->bottom.width,
|
||||
config->bottom.color,
|
||||
scissorBox);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
printf("Error: unhandled render command.");
|
||||
#ifdef CLAY_OVERFLOW_TRAP
|
||||
raise(SIGTRAP);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console_MoveCursor(-1, -1); // TODO make the user not be able to write
|
||||
}
|
Loading…
Reference in New Issue
Block a user