Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ jobs:
- name: Generate documentation
run: ./docsparser

- name: Setup Emscripten SDK
uses: mymindstorm/setup-emsdk@v14
with:
version: 'latest'
actions-cache-folder: 'emsdk-cache'

- name: Build samples for web
run: |
emcmake cmake -B build_web -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build_web
timeout-minutes: 30

- name: Generate sample pages
run: |
chmod +x tools/generate_sample_pages.rb
./tools/generate_sample_pages.rb build_web docs https://github.com/RandyGaul/cute_framework

- name: Set up Python runtime
uses: actions/setup-python@v5
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ build*/
docs/*/*.md
docs/api_reference.md
!docs/topics/*.md
docs/samples/play/
site/
.cache
.DS_Store
Expand Down
1 change: 0 additions & 1 deletion docs/samples.md

This file was deleted.

44 changes: 44 additions & 0 deletions docs/stylesheets/cute.css
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,47 @@
[data-md-color-scheme="slate"] {
--md-hue: var(--cute-primary-hue);
}

/* Sample iframe container */
.sample-container {
margin: 2em 0;
border-radius: 0.5rem;
overflow: hidden;
background: #000;
box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.2);
min-width: 1024px;
min-height: 768px;
}

.sample-iframe {
width: 100%;
height: 768px;
min-height: 768px;
border: none;
display: block;
}

.sample-controls {
display: flex;
gap: 1rem;
margin: 1rem 0 2rem 0;
flex-wrap: wrap;
}

/* Responsive sizing */
@media screen and (max-width: 1024px) {
.sample-container {
min-width: 100%;
}
.sample-iframe {
height: 600px;
min-height: 600px;
}
}

@media screen and (max-width: 768px) {
.sample-iframe {
height: 480px;
min-height: 480px;
}
}
1 change: 1 addition & 0 deletions include/cute_file_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ struct CF_Directory
static CF_INLINE Array<CF_Path> enumerate(const char* virtual_path) {
Array<CF_Path> files;
const char** paths = fs_enumerate_directory(virtual_path);
if (!paths) return files;
const char** paths_ptr = paths;
while (*paths) {
const char* file = *paths++;
Expand Down
47 changes: 46 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ not_in_nav: |
/input/*.md
/json/*.md
/list/*.md
/map/*.md
/math/*.md
/multithreading/*.md
/net/*.md
Expand Down Expand Up @@ -118,7 +119,51 @@ nav:
- Strings: topics/strings.md
- Virtual File System: topics/virtual_file_system.md
- HTTPS: topics/web.md
- Samples: samples.md
- Samples:
- samples/index.md

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep sample nav pages available in-tree

This nav block now references samples/*.md pages that are not present in a fresh checkout (there is no docs/samples/ content committed), so docs builds depend on running the web-sample generation pipeline first. That makes mkdocs build/serve fail for normal local docs workflows and any automation that expects source pages to exist before generation.

Useful? React with 👍 / 👎.

- basic_camera: samples/basic_camera.md
- basicindexedrendering: samples/basicindexedrendering.md
- basicinput: samples/basicinput.md
- basicinstancing: samples/basicinstancing.md
- basicshapes: samples/basicshapes.md
- basicsprite: samples/basicsprite.md
- clay: samples/clay.md
- clay_ui_animations: samples/clay_ui_animations.md
- draw_to_texture: samples/draw_to_texture.md
- easysprite: samples/easysprite.md
- fetch_image: samples/fetch_image.md
- fluid_sim: samples/fluid_sim.md
- font_debug: samples/font_debug.md
- hello_triangle: samples/hello_triangle.md
- ime: samples/ime.md
- imgui: samples/imgui.md
- imgui_texture: samples/imgui_texture.md
- import_spritesheet: samples/import_spritesheet.md
- input_binding: samples/input_binding.md
- joypad: samples/joypad.md
- metaballs: samples/metaballs.md
- nine_slice: samples/nine_slice.md
- noise: samples/noise.md
- outline_stencil: samples/outline_stencil.md
- pivot: samples/pivot.md
- platformer: samples/platformer.md
- polygon: samples/polygon.md
- rainbow_liquid: samples/rainbow_liquid.md
- recolor: samples/recolor.md
- scissor: samples/scissor.md
- scratch: samples/scratch.md
- screen_shatter: samples/screen_shatter.md
- shallow_water: samples/shallow_water.md
- spaceshooter: samples/spaceshooter.md
- sprite_shatter: samples/sprite_shatter.md
- sprite_slice: samples/sprite_slice.md
- stencil_pie_chart: samples/stencil_pie_chart.md
- textdrawing: samples/textdrawing.md
- timestep: samples/timestep.md
- waves: samples/waves.md
- window: samples/window.md
- windowevents: samples/windowevents.md
- windowresizing: samples/windowresizing.md
- Made with CF: made_with_cf.md
- Community / Ask for Help: community_ask_for_help.md
- API Reference: api_reference.md
Expand Down
112 changes: 89 additions & 23 deletions samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,45 @@ function(add_sample TARGET_NAME SOURCE_FILE)
endif()
endfunction()

# Helper function to add shader compilation custom commands
# Usage: add_shader(SHADER_SOURCE TYPE VARNAME [OUTPUT_HEADER])
# SHADER_SOURCE: Path to .shd file relative to samples dir (e.g., "metaballs.shd" or "waves_data/waves.shd")
# TYPE: Shader type (draw, vertex, fragment, compute)
# VARNAME: Variable name for the bytecode struct
# OUTPUT_HEADER: Optional output header path; defaults to SHADER_SOURCE with .shd replaced by _shd.h
function(add_shader SHADER_SOURCE TYPE VARNAME)
# Determine output header path
if (ARGC GREATER 3)
set(OUTPUT_HEADER ${ARGV3})
else()
string(REGEX REPLACE "\\.shd$" "_shd.h" OUTPUT_HEADER "${SHADER_SOURCE}")
endif()

add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${OUTPUT_HEADER}
COMMAND cute-shaderc
-type=${TYPE}
-varname=${VARNAME}
-oheader=${CMAKE_CURRENT_SOURCE_DIR}/${OUTPUT_HEADER}
${CMAKE_CURRENT_SOURCE_DIR}/${SHADER_SOURCE}
DEPENDS ${SHADER_SOURCE}
DEPENDS cute-shaderc
)
endfunction()

# Helper function to copy .shd files to build output for runtime shader compilation
function(add_sample_shader TARGET_NAME SHADER_FILE)
add_custom_command(TARGET ${TARGET_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${SHADER_FILE}
$<TARGET_FILE_DIR:${TARGET_NAME}>/${SHADER_FILE}
)
if (EMSCRIPTEN)
target_link_options(${TARGET_NAME} PRIVATE
"SHELL:--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/${SHADER_FILE}@/${SHADER_FILE}")
endif()
endfunction()

add_sample(easysprite easy_sprite.c)
add_sample(basicserialization basic_serialization.c)
add_sample(imgui imgui.c)
Expand Down Expand Up @@ -82,38 +121,54 @@ add_sample(9_slice 9_slice.c)
add_sample(basic_camera basic_camera.c)
add_sample(imgui_texture imgui_texture.c)
add_sample(input_binding input_binding.c)
add_sample(compute compute.c)
add_sample(galaxy galaxy.c)
add_sample(hrc hrc.c)
if (NOT EMSCRIPTEN)
add_sample(compute compute.c)
add_sample(galaxy galaxy.c)
add_sample(hrc hrc.c)
endif()

# Data directories are now copied wholesale for affected samples (see below)

# Pre-compile shaders for certain samples.
if (CF_CUTE_SHADERC)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/spaceshooter_data/flash_shd.h
COMMAND cute-shaderc
-type=draw
-varname=s_flash_shd_bytecode
-oheader=${CMAKE_CURRENT_SOURCE_DIR}/spaceshooter_data/flash_shd.h
${CMAKE_CURRENT_SOURCE_DIR}/spaceshooter_data/flash.shd
DEPENDS spaceshooter_data/flash.shd
DEPENDS cute-shaderc
)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/waves_data/waves_shd.h
COMMAND cute-shaderc
-type=draw
-varname=s_waves_shd_bytecode
-oheader=${CMAKE_CURRENT_SOURCE_DIR}/waves_data/waves_shd.h
${CMAKE_CURRENT_SOURCE_DIR}/waves_data/waves.shd
DEPENDS waves_data/waves.shd
DEPENDS cute-shaderc
)
# Draw shaders
add_shader(spaceshooter_data/flash.shd draw s_flash_shd_bytecode)
add_shader(waves_data/waves.shd draw s_waves_shd_bytecode)
add_shader(metaballs_data/metaballs.shd draw metaballs metaballs_data/metaballs_shd.h)
add_shader(shallow_water_data/shallow_water.shd draw s_shallow_water_shd_bytecode)
add_shader(recolor_data/recolor.shd draw s_recolor_shd_bytecode recolor_data/recolor_shd.h)
add_shader(fluid_sim_data/fluid_sim.shd draw s_fluid_sim_shd_bytecode fluid_sim_data/fluid_sim_shd.h)
add_shader(screen_shatter_data/screen_shatter.shd draw s_screen_shatter_shd_bytecode screen_shatter_data/screen_shatter_shd.h)
add_shader(sprite_shatter_data/sprite_shatter.shd draw s_sprite_shatter_shd_bytecode sprite_shatter_data/sprite_shatter_shd.h)
add_shader(sprite_slice_data/sprite_slice.shd draw s_sprite_slice_shd_bytecode sprite_slice_data/sprite_slice_shd.h)

# Low-level shaders (vertex/fragment)
add_shader(hello_triangle_data/hello_triangle_vs.shd vertex s_hello_triangle_vs_bytecode hello_triangle_data/hello_triangle_vs_shd.h)
add_shader(hello_triangle_data/hello_triangle_fs.shd fragment s_hello_triangle_fs_bytecode hello_triangle_data/hello_triangle_fs_shd.h)
add_shader(basic_instancing_data/basic_instancing_vs.shd vertex s_basic_instancing_vs_bytecode basic_instancing_data/basic_instancing_vs_shd.h)
add_shader(basic_instancing_data/basic_instancing_fs.shd fragment s_basic_instancing_fs_bytecode basic_instancing_data/basic_instancing_fs_shd.h)
add_shader(basic_indexed_rendering_data/basic_indexed_rendering_vs.shd vertex s_basic_indexed_rendering_vs_bytecode basic_indexed_rendering_data/basic_indexed_rendering_vs_shd.h)
add_shader(basic_indexed_rendering_data/basic_indexed_rendering_fs.shd fragment s_basic_indexed_rendering_fs_bytecode basic_indexed_rendering_data/basic_indexed_rendering_fs_shd.h)
endif()

# Ensure that sample data is included in web build
if (EMSCRIPTEN)
target_link_options(waves PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/waves_data@/waves_data")
target_link_options(spaceshooter PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/spaceshooter_data@/spaceshooter_data")
target_link_options(shallow_water PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/shallow_water_data@/shallow_water_data")
target_link_options(import_spritesheet PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/import_spritesheet_data@/import_spritesheet_data")
target_link_options(pivot PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/pivot_data@/pivot_data")
target_link_options(9_slice PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/9_slice_data@/9_slice_data")
target_link_options(scratch PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/../assets/CF_Logo_Pixel.png@/app_icon.png")
target_link_options(recolor PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/recolor_data@/recolor_data")
target_link_options(fluid_sim PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/fluid_sim_data@/fluid_sim_data")
target_link_options(metaballs PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/metaballs_data@/metaballs_data")
target_link_options(screen_shatter PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/screen_shatter_data@/screen_shatter_data")
target_link_options(sprite_shatter PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/sprite_shatter_data@/sprite_shatter_data")
target_link_options(sprite_slice PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/sprite_slice_data@/sprite_slice_data")
target_link_options(hello_triangle PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/hello_triangle_data@/hello_triangle_data")
target_link_options(basicinstancing PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/basic_instancing_data@/basic_instancing_data")
target_link_options(basicindexedrendering PRIVATE --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/basic_indexed_rendering_data@/basic_indexed_rendering_data")
endif ()

# Copy over some folders for certain samples.
Expand All @@ -124,4 +179,15 @@ add_custom_command(TARGET import_spritesheet PRE_BUILD COMMAND ${CMAKE_COMMAND}
add_custom_command(TARGET pivot PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/pivot_data $<TARGET_FILE_DIR:pivot>/pivot_data)
add_custom_command(TARGET scratch PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/../assets/CF_Logo_Pixel.png $<TARGET_FILE_DIR:scratch>/app_icon.png)
add_custom_command(TARGET 9_slice PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/9_slice_data $<TARGET_FILE_DIR:9_slice>/9_slice_data)
add_custom_command(TARGET recolor PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/recolor_data $<TARGET_FILE_DIR:recolor>/recolor_data)
add_custom_command(TARGET fluid_sim PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/fluid_sim_data $<TARGET_FILE_DIR:fluid_sim>/fluid_sim_data)
add_custom_command(TARGET metaballs PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/metaballs_data $<TARGET_FILE_DIR:metaballs>/metaballs_data)
add_custom_command(TARGET screen_shatter PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/screen_shatter_data $<TARGET_FILE_DIR:screen_shatter>/screen_shatter_data)
add_custom_command(TARGET sprite_shatter PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/sprite_shatter_data $<TARGET_FILE_DIR:sprite_shatter>/sprite_shatter_data)
add_custom_command(TARGET sprite_slice PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/sprite_slice_data $<TARGET_FILE_DIR:sprite_slice>/sprite_slice_data)
add_custom_command(TARGET hello_triangle PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/hello_triangle_data $<TARGET_FILE_DIR:hello_triangle>/hello_triangle_data)
add_custom_command(TARGET basicinstancing PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/basic_instancing_data $<TARGET_FILE_DIR:basicinstancing>/basic_instancing_data)
add_custom_command(TARGET basicindexedrendering PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/basic_indexed_rendering_data $<TARGET_FILE_DIR:basicindexedrendering>/basic_indexed_rendering_data)
if(NOT EMSCRIPTEN)
add_custom_command(TARGET hrc PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/hrc_data $<TARGET_FILE_DIR:hrc>/hrc_data)
endif()
39 changes: 19 additions & 20 deletions samples/basic_indexed_rendering.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,26 @@ typedef struct Vertex
CF_Pixel color;
} Vertex;

const char* s_tri_vs =
"layout (location = 0) in vec2 in_pos;\n"
"layout (location = 1) in vec4 in_col;\n"
"\n"
"layout (location = 0) out vec4 v_col;\n"
"\n"
"void main()\n"
"{\n"
" v_col = in_col;\n"
" gl_Position = vec4(in_pos, 0, 1);\n"
"}\n";
#ifndef CF_RUNTIME_SHADER_COMPILATION
#include "basic_indexed_rendering_data/basic_indexed_rendering_vs_shd.h"
#include "basic_indexed_rendering_data/basic_indexed_rendering_fs_shd.h"
#endif

const char* s_tri_fs =
"layout(location = 0) in vec4 v_col;\n"
"layout(location = 0) out vec4 result;\n"
"\n"
"void main()\n"
"{\n"
" result = v_col;\n"
"}\n";
void mount_content_directory_as(const char* dir)
{
const char* path = cf_fs_get_base_directory();
path = cf_path_normalize(path);
path = cf_string_append(path, "/basic_indexed_rendering_data");
cf_fs_mount(path, dir, false);
cf_string_free(path);
}

int main(int argc, char* argv[])
{
CF_Result result = cf_make_app("Indexed Mesh", 0, 0, 0, 640, 480, CF_APP_OPTIONS_WINDOW_POS_CENTERED_BIT | CF_APP_OPTIONS_RESIZABLE_BIT, argv[0]);
if (cf_is_error(result)) return -1;
mount_content_directory_as("/");
cf_shader_directory("/");

// Define a square with two triangles (4 vertices, 6 indices).
Vertex verts[4];
Expand Down Expand Up @@ -58,7 +53,11 @@ int main(int argc, char* argv[])
cf_mesh_update_index_data(mesh, indices, 6);

CF_Material material = cf_make_material();
CF_Shader shader = cf_make_shader_from_source(s_tri_vs, s_tri_fs);
#ifdef CF_RUNTIME_SHADER_COMPILATION
CF_Shader shader = cf_make_shader("basic_indexed_rendering_vs.shd", "basic_indexed_rendering_fs.shd");
#else
CF_Shader shader = cf_make_shader_from_bytecode(s_basic_indexed_rendering_vs_bytecode, s_basic_indexed_rendering_fs_bytecode);
#endif

while (cf_app_is_running()) {
cf_app_update(NULL);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
layout(location = 0) in vec4 v_col;
layout(location = 0) out vec4 result;

void main()
{
result = v_col;
}
Loading