update SDL3 from 3.2.20 to 3.4.2

This commit is contained in:
Sven Balzer
2026-04-01 18:25:03 +02:00
parent 1daf4d79f1
commit 05b19704f8
1626 changed files with 124218 additions and 191491 deletions
+51 -74
View File
@@ -16,13 +16,6 @@ else()
endif()
set(HAVE_EXAMPLES_LINK_SHARED "${SDL_EXAMPLES_LINK_SHARED}" PARENT_SCOPE)
# CMake incorrectly detects opengl32.lib being present on MSVC ARM64
if(NOT (MSVC AND SDL_CPU_ARM64))
# Prefer GLVND, if present
set(OpenGL_GL_PREFERENCE GLVND)
find_package(OpenGL)
endif()
set(SDL_EXAMPLE_EXECUTABLES)
if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
@@ -38,7 +31,7 @@ if(NOT CMAKE_VERSION VERSION_LESS 3.20)
set(example_bin_dir "${example_bin_dir}$<$<BOOL:${is_multi_config}>:/$<CONFIG>>")
endif()
file(GLOB RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.bmp ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.wav ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.hex)
file(GLOB RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.png ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.wav ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.hex)
set(RESOURCE_FILE_NAMES)
set(RESOURCE_FILES_BINDIR)
@@ -64,17 +57,12 @@ macro(add_sdl_example_executable TARGET)
if(NOT AST_SOURCES)
message(FATAL_ERROR "add_sdl_example_executable needs at least one source")
endif()
set(EXTRA_SOURCES "")
if(AST_DATAFILES)
list(APPEND EXTRA_SOURCES ${DATAFILES})
endif()
if(ANDROID)
add_library(${TARGET} SHARED ${AST_SOURCES} ${EXTRA_SOURCES})
add_library(${TARGET} SHARED ${AST_SOURCES} ${AST_DATAFILES})
else()
add_executable(${TARGET} ${AST_SOURCES} ${EXTRA_SOURCES})
add_executable(${TARGET} ${AST_SOURCES} ${AST_DATAFILES})
endif()
SDL_AddCommonCompilerFlags(${TARGET})
target_include_directories(${TARGET} PRIVATE "${SDL3_SOURCE_DIR}/src/video/khronos")
target_link_libraries(${TARGET} PRIVATE SDL3::${sdl_name_component})
list(APPEND SDL_EXAMPLE_EXECUTABLES ${TARGET})
@@ -85,13 +73,9 @@ macro(add_sdl_example_executable TARGET)
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${AST_DATAFILES} $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
else()
elseif(NOT APPLE AND NOT N3DS)
add_dependencies(${TARGET} copy-sdl-example-resources)
endif()
if(APPLE)
# Make sure resource files get installed into macOS/iOS .app bundles.
set_target_properties(${TARGET} PROPERTIES RESOURCE "${AST_DATAFILES}")
endif()
if(EMSCRIPTEN)
foreach(res IN LISTS AST_DATAFILES)
get_filename_component(res_name "${res}" NAME)
@@ -101,24 +85,45 @@ macro(add_sdl_example_executable TARGET)
set_property(TARGET ${TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES "$<TARGET_FILE_DIR:${TARGET}>/$<JOIN:${AST_DATAFILES},$<SEMICOLON>$<TARGET_FILE_DIR:${TARGET}>/>")
endif()
if(WINDOWS)
if(APPLE)
# Set Apple App ID / Bundle ID. This is needed to launch apps on some Apple
# platforms (iOS, for example).
set_target_properties(${TARGET} PROPERTIES
RESOURCES "${AST_DATAFILES}"
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_GUI_IDENTIFIER "org.libsdl.${TARGET}"
MACOSX_BUNDLE_BUNDLE_VERSION "${SDL3_VERSION}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${SDL3_VERSION}"
)
set_property(SOURCE ${AST_DATAFILES} PROPERTY MACOSX_PACKAGE_LOCATION "Resources")
elseif(WINDOWS)
# CET support was added in VS 16.7
if(MSVC_VERSION GREATER 1926 AND CMAKE_GENERATOR_PLATFORM MATCHES "Win32|x64")
set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -CETCOMPAT")
endif()
elseif(PSP)
target_link_libraries(${TARGET} PRIVATE GL)
elseif(EMSCRIPTEN)
set_property(TARGET ${TARGET} PROPERTY SUFFIX ".html")
target_link_options(${TARGET} PRIVATE -sALLOW_MEMORY_GROWTH=1)
elseif(N3DS)
set(ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/romfs/${TARGET}")
file(MAKE_DIRECTORY "${ROMFS_DIR}")
file(COPY ${AST_DATAFILES} DESTINATION "${ROMFS_DIR}")
ctr_generate_smdh("${TARGET}.smdh"
NAME "SDL-${TARGET}"
DESCRIPTION "SDL3 example application"
AUTHOR "SDL3 Contributors"
ICON "${CMAKE_CURRENT_SOURCE_DIR}/../test/n3ds/logo48x48.png"
)
ctr_create_3dsx(
${TARGET}
ROMFS "${ROMFS_DIR}"
SMDH "${TARGET}.smdh"
)
elseif(NGAGE)
string(MD5 TARGET_MD5 "${TARGET}")
string(SUBSTRING "${TARGET_MD5}" 0 8 TARGET_MD5_8)
target_link_options(${TARGET} PRIVATE "SHELL:-s UID3=0x${TARGET_MD5_8}")
endif()
if(OPENGL_FOUND)
target_compile_definitions(${TARGET} PRIVATE HAVE_OPENGL)
endif()
# FIXME: only add "${SDL3_BINARY_DIR}/include-config-$<LOWER_CASE:$<CONFIG>>" + include paths of external dependencies
target_include_directories(${TARGET} PRIVATE "$<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>")
endmacro()
add_sdl_example_executable(renderer-clear SOURCES renderer/01-clear/clear.c)
@@ -126,25 +131,31 @@ add_sdl_example_executable(renderer-primitives SOURCES renderer/02-primitives/pr
add_sdl_example_executable(renderer-lines SOURCES renderer/03-lines/lines.c)
add_sdl_example_executable(renderer-points SOURCES renderer/04-points/points.c)
add_sdl_example_executable(renderer-rectangles SOURCES renderer/05-rectangles/rectangles.c)
add_sdl_example_executable(renderer-textures SOURCES renderer/06-textures/textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-textures SOURCES renderer/06-textures/textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(renderer-streaming-textures SOURCES renderer/07-streaming-textures/streaming-textures.c)
add_sdl_example_executable(renderer-rotating-textures SOURCES renderer/08-rotating-textures/rotating-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-scaling-textures SOURCES renderer/09-scaling-textures/scaling-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-geometry SOURCES renderer/10-geometry/geometry.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-color-mods SOURCES renderer/11-color-mods/color-mods.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-viewport SOURCES renderer/14-viewport/viewport.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-cliprect SOURCES renderer/15-cliprect/cliprect.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-read-pixels SOURCES renderer/17-read-pixels/read-pixels.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp)
add_sdl_example_executable(renderer-rotating-textures SOURCES renderer/08-rotating-textures/rotating-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(renderer-scaling-textures SOURCES renderer/09-scaling-textures/scaling-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(renderer-geometry SOURCES renderer/10-geometry/geometry.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(renderer-color-mods SOURCES renderer/11-color-mods/color-mods.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(renderer-viewport SOURCES renderer/14-viewport/viewport.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(renderer-cliprect SOURCES renderer/15-cliprect/cliprect.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(renderer-read-pixels SOURCES renderer/17-read-pixels/read-pixels.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(renderer-debug-text SOURCES renderer/18-debug-text/debug-text.c)
add_sdl_example_executable(renderer-affine-textures SOURCES renderer/19-affine-textures/affine-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png)
add_sdl_example_executable(audio-simple-playback SOURCES audio/01-simple-playback/simple-playback.c)
add_sdl_example_executable(audio-simple-playback-callback SOURCES audio/02-simple-playback-callback/simple-playback-callback.c)
add_sdl_example_executable(audio-load-wav SOURCES audio/03-load-wav/load-wav.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.wav)
add_sdl_example_executable(audio-multiple-streams SOURCES audio/04-multiple-streams/multiple-streams.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.wav ${CMAKE_CURRENT_SOURCE_DIR}/../test/sword.wav)
add_sdl_example_executable(audio-planar-data SOURCES audio/05-planar-data/planar-data.c)
add_sdl_example_executable(input-joystick-polling SOURCES input/01-joystick-polling/joystick-polling.c)
add_sdl_example_executable(input-joystick-events SOURCES input/02-joystick-events/joystick-events.c)
add_sdl_example_executable(input-gamepad-polling SOURCES input/03-gamepad-polling/gamepad-polling.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/gamepad_front.png)
add_sdl_example_executable(input-gamepad-events SOURCES input/04-gamepad-events/gamepad-events.c)
add_sdl_example_executable(camera-read-and-draw SOURCES camera/01-read-and-draw/read-and-draw.c)
add_sdl_example_executable(pen-drawing-lines SOURCES pen/01-drawing-lines/drawing-lines.c)
add_sdl_example_executable(asyncio-load-bitmaps SOURCES asyncio/01-load-bitmaps/load-bitmaps.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp ${CMAKE_CURRENT_SOURCE_DIR}/../test/gamepad_front.bmp ${CMAKE_CURRENT_SOURCE_DIR}/../test/speaker.bmp ${CMAKE_CURRENT_SOURCE_DIR}/../test/icon2x.bmp)
add_sdl_example_executable(asyncio-load-bitmaps SOURCES asyncio/01-load-bitmaps/load-bitmaps.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.png ${CMAKE_CURRENT_SOURCE_DIR}/../test/gamepad_front.png ${CMAKE_CURRENT_SOURCE_DIR}/../test/speaker.png ${CMAKE_CURRENT_SOURCE_DIR}/../test/icon2x.png)
add_sdl_example_executable(misc-power SOURCES misc/01-power/power.c)
add_sdl_example_executable(misc-clipboard SOURCES misc/02-clipboard/clipboard.c)
add_sdl_example_executable(demo-snake SOURCES demo/01-snake/snake.c)
add_sdl_example_executable(demo-woodeneye-008 SOURCES demo/02-woodeneye-008/woodeneye-008.c)
add_sdl_example_executable(demo-infinite-monkeys SOURCES demo/03-infinite-monkeys/infinite-monkeys.c)
@@ -154,7 +165,7 @@ add_sdl_example_executable(demo-bytepusher SOURCES demo/04-bytepusher/bytepusher
# - Add a new example in examples/
# - Run python VisualC/examples/generate.py
# - Take note of the newly generated .vcxproj files
# - Modify the .vcxproj files if necessary (adding content such as BMP or WAV files)
# - Modify the .vcxproj files if necessary (adding content such as PNG or WAV files)
# - Open VisualC/SDL.sln in Visual Studio or JetBrains Rider
# - Locate the appropriate folder in the Solution Explorer
# - Add the newly generated projects: Right click -> Add -> Existing project...
@@ -175,28 +186,6 @@ if(PSP)
endforeach()
endif()
if(N3DS)
set(ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/romfs")
file(MAKE_DIRECTORY "${ROMFS_DIR}")
file(COPY ${RESOURCE_FILES} DESTINATION "${ROMFS_DIR}")
foreach(APP ${SDL_EXAMPLE_EXECUTABLES})
get_target_property(TARGET_BINARY_DIR ${APP} BINARY_DIR)
set(SMDH_FILE "${TARGET_BINARY_DIR}/${APP}.smdh")
ctr_generate_smdh("${SMDH_FILE}"
NAME "SDL-${APP}"
DESCRIPTION "SDL3 Test suite"
AUTHOR "SDL3 Contributors"
ICON "${CMAKE_CURRENT_SOURCE_DIR}/../test/n3ds/logo48x48.png"
)
ctr_create_3dsx(
${APP}
ROMFS "${ROMFS_DIR}"
SMDH "${SMDH_FILE}"
)
endforeach()
endif()
if(RISCOS)
set(SDL_EXAMPLE_EXECUTABLES_AIF)
foreach(APP ${SDL_EXAMPLE_EXECUTABLES})
@@ -211,18 +200,6 @@ if(RISCOS)
endforeach()
endif()
# Set Apple App ID / Bundle ID. This is needed to launch apps on some Apple
# platforms (iOS, for example).
if(APPLE)
foreach(CURRENT_TARGET ${SDL_EXAMPLE_EXECUTABLES})
set_target_properties("${CURRENT_TARGET}" PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER "org.libsdl.${CURRENT_TARGET}"
MACOSX_BUNDLE_BUNDLE_VERSION "${SDL3_VERSION}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${SDL3_VERSION}"
)
endforeach()
endif()
if(SDL_INSTALL_EXAMPLES)
if(RISCOS)
install(
+27
View File
@@ -65,3 +65,30 @@ If writing new examples, this is the skeleton code we start from, to keep
everything consistent. You can ignore it.
## How are the thumbnails/onmouseover media created?
(Since I have to figure this out every time.)
This is how Ryan is doing it currently.
- `rm -f frame*.png`
- Temporarily add `#include "../../save-rendering-to-bitmaps.h"` after any SDL
includes in the example program.
- Launch the example app, interact with it, let it run for a few seconds, quit.
- This will dump a "frameX.png" file for each frame rendered.
- Make a video in webp format from the bitmaps (this assumes the bitmaps were
stored at 60fps, you might have to tweak).
```bash
ffmpeg -framerate 60 -pattern_type glob -i 'frame*.png' -loop 0 -quality 40 -r 10 -frames:v 40 onmouseover.webp
```
You might need to start in the middle of the video, or mess with quality or
number of frames to generate, ymmv.
- Pick a frame for the thumbnail, make it a .png, and run that png through
pngquant for massive file size reduction without any obvious loss in quality:
```bash
convert frame00000.png cvt.png ; pngquant cvt.png --output thumbnail.png ; rm -f cvt.png
```
@@ -14,7 +14,7 @@ static SDL_Renderer *renderer = NULL;
static SDL_AsyncIOQueue *queue = NULL;
#define TOTAL_TEXTURES 4
static const char * const bmps[TOTAL_TEXTURES] = { "sample.bmp", "gamepad_front.bmp", "speaker.bmp", "icon2x.bmp" };
static const char * const pngs[TOTAL_TEXTURES] = { "sample.png", "gamepad_front.png", "speaker.png", "icon2x.png" };
static SDL_Texture *textures[TOTAL_TEXTURES];
static const SDL_FRect texture_rects[TOTAL_TEXTURES] = {
{ 116, 156, 408, 167 },
@@ -33,10 +33,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/asyncio/load-bitmaps", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/asyncio/load-bitmaps", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
queue = SDL_CreateAsyncIOQueue();
if (!queue) {
@@ -44,12 +45,12 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
/* Load some .bmp files asynchronously from wherever the app is being run from, put them in the same queue. */
for (i = 0; i < SDL_arraysize(bmps); i++) {
/* Load some .png files asynchronously from wherever the app is being run from, put them in the same queue. */
for (i = 0; i < SDL_arraysize(pngs); i++) {
char *path = NULL;
SDL_asprintf(&path, "%s%s", SDL_GetBasePath(), bmps[i]); /* allocate a string of the full file path */
SDL_asprintf(&path, "%s%s", SDL_GetBasePath(), pngs[i]); /* allocate a string of the full file path */
/* you _should) check for failure, but we'll just go on without files here. */
SDL_LoadFileAsync(path, queue, (void *) bmps[i]); /* attach the filename as app-specific data, so we can see it later. */
SDL_LoadFileAsync(path, queue, (void *) pngs[i]); /* attach the filename as app-specific data, so we can see it later. */
SDL_free(path);
}
@@ -72,18 +73,18 @@ SDL_AppResult SDL_AppIterate(void *appstate)
SDL_AsyncIOOutcome outcome;
int i;
if (SDL_GetAsyncIOResult(queue, &outcome)) { /* a .bmp file load has finished? */
if (SDL_GetAsyncIOResult(queue, &outcome)) { /* a .png file load has finished? */
if (outcome.result == SDL_ASYNCIO_COMPLETE) {
/* this might be _any_ of the bmps; they might finish loading in any order. */
for (i = 0; i < SDL_arraysize(bmps); i++) {
/* this might be _any_ of the pngs; they might finish loading in any order. */
for (i = 0; i < SDL_arraysize(pngs); i++) {
/* this doesn't need a strcmp because we gave the pointer from this array to SDL_LoadFileAsync */
if (outcome.userdata == bmps[i]) {
if (outcome.userdata == pngs[i]) {
break;
}
}
if (i < SDL_arraysize(bmps)) { /* (just in case.) */
SDL_Surface *surface = SDL_LoadBMP_IO(SDL_IOFromConstMem(outcome.buffer, (size_t) outcome.bytes_transferred), true);
if (i < SDL_arraysize(pngs)) { /* (just in case.) */
SDL_Surface *surface = SDL_LoadPNG_IO(SDL_IOFromConstMem(outcome.buffer, (size_t) outcome.bytes_transferred), true);
if (surface) { /* the renderer is not multithreaded, so create the texture here once the data loads. */
textures[i] = SDL_CreateTextureFromSurface(renderer, surface);
if (!textures[i]) {
@@ -29,10 +29,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
}
/* we don't _need_ a window for audio-only things but it's good policy to have one. */
if (!SDL_CreateWindowAndRenderer("examples/audio/simple-playback", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/audio/simple-playback", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* We're just playing a single thing here, so we'll use the simplified option.
We are always going to feed audio in as mono, float32 data at 8000Hz.
@@ -63,10 +63,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
}
/* we don't _need_ a window for audio-only things but it's good policy to have one. */
if (!SDL_CreateWindowAndRenderer("examples/audio/simple-playback-callback", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/audio/simple-playback-callback", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* We're just playing a single thing here, so we'll use the simplified option.
We are always going to feed audio in as mono, float32 data at 8000Hz.
@@ -39,10 +39,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
}
/* we don't _need_ a window for audio-only things but it's good policy to have one. */
if (!SDL_CreateWindowAndRenderer("examples/audio/load-wav", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/audio/load-wav", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Load the .wav file from wherever the app is being run from. */
SDL_asprintf(&wav_path, "%ssample.wav", SDL_GetBasePath()); /* allocate a string of the full file path */
@@ -1,5 +1,5 @@
If you're running this in a web browser, you need to click the window before you'll hear anything!
This example code loads two .wav files, puts them an audio streams and binds
This example code loads two .wav files, puts them in audio streams and binds
them for playback, repeating both sounds on loop. This shows several streams
mixing into a single playback device.
@@ -1,5 +1,5 @@
/*
* This example code loads two .wav files, puts them an audio streams and
* This example code loads two .wav files, puts them in audio streams and
* binds them for playback, repeating both sounds on loop. This shows several
* streams mixing into a single playback device.
*
@@ -65,10 +65,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/audio/multiple-streams", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/audio/multiple-streams", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* open the default audio device in whatever format it prefers; our audio streams will adjust to it. */
audio_device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
@@ -0,0 +1,7 @@
This example code draws two clickable buttons. Each causes a sound to play,
fed to either the left or right audio channel through separate (planar)
arrays.
Planar audio can feed both channels at the same time from different arrays,
as well, but this example only uses one channel at a time for clarity. A
NULL array will supply silence for that channel.
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@@ -0,0 +1,368 @@
/*
* This example code draws two clickable buttons. Each causes a sound to play,
* fed to either the left or right audio channel through separate ("planar")
* arrays.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_AudioStream *stream = NULL;
/* location of buttons on the screen. */
static const SDL_FRect rect_left_button = { 100, 170, 100, 100 };
static const SDL_FRect rect_right_button = { 440, 170, 100, 100 };
/* -1 if we're currently playing left, 1 if playing right, 0 if not playing. */
static int playing_sound = 0;
/* Raw audio data. These arrays are at the end of the source file. */
static const Uint8 left[1870];
static const Uint8 right[1777];
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
const SDL_AudioSpec spec = { SDL_AUDIO_U8, 2, 4000 }; /* Uint8 data, stereo, 4000Hz. */
SDL_SetAppMetadata("Example Audio Planar Data", "1.0", "com.example.audio-planar-data");
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/audio/planar-data", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL);
if (!stream) {
SDL_Log("Couldn't open audio device stream: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_ResumeAudioStreamDevice(stream); /* SDL_OpenAudioDeviceStream starts the device paused. Resume it! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
SDL_ConvertEventToRenderCoordinates(renderer, event);
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
} else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (playing_sound == 0) { /* nothing currently playing? */
const SDL_FPoint point = { event->button.x, event->button.y };
if (SDL_PointInRectFloat(&point, &rect_left_button)) { /* clicked left button? */
const Uint8 *planes[] = { left, NULL }; /* specify NULL to say "this specific channel is silent" */
SDL_PutAudioStreamPlanarData(stream, (const void * const *) planes, -1, SDL_arraysize(left));
SDL_FlushAudioStream(stream); /* that's all we're playing until it completes. */
playing_sound = -1; /* left is playing */
} else if (SDL_PointInRectFloat(&point, &rect_right_button)) { /* clicked right button? */
const Uint8 *planes[] = { NULL, right }; /* specify NULL to say "this specific channel is silent" */
SDL_PutAudioStreamPlanarData(stream, (const void * const *) planes, -1, SDL_arraysize(right));
SDL_FlushAudioStream(stream); /* that's all we're playing until it completes. */
playing_sound = 1; /* right is playing */
}
}
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
static void render_button(const SDL_FRect *rect, const char *str, int button_value)
{
float x, y;
if (playing_sound == button_value) {
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); /* green while playing */
} else {
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); /* blue while not playing */
}
SDL_RenderFillRect(renderer, rect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
x = rect->x + ((rect->w - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * SDL_strlen(str))) / 2.0f);
y = rect->y + ((rect->h - SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) / 2.0f);
SDL_RenderDebugText(renderer, x, y, str);
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
if (playing_sound) {
if (SDL_GetAudioStreamQueued(stream) == 0) { /* sound is done? We can play a new sound now. */
playing_sound = 0;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
render_button(&rect_left_button, "LEFT", -1);
render_button(&rect_right_button, "RIGHT", 1);
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyAudioStream(stream);
/* SDL will clean up the window/renderer for us. */
}
/* This is the audio data, as raw PCM samples (Uint8, 1 channel, 4000Hz) packed into C byte arrays for convenience. */
static const Uint8 left[1870] = {
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x80, 0x81, 0x82, 0x82,
0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, 0x7d,
0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x85, 0x84,
0x84, 0x83, 0x81, 0x7f, 0x7d, 0x7c, 0x7a, 0x7a, 0x7a, 0x77, 0x77, 0x77, 0x76, 0x76, 0x76, 0x77,
0x78, 0x7d, 0x82, 0x89, 0x8e, 0x92, 0x95, 0x95, 0x91, 0x8b, 0x84, 0x7d, 0x77, 0x73, 0x72, 0x72,
0x74, 0x75, 0x75, 0x75, 0x76, 0x74, 0x73, 0x73, 0x74, 0x79, 0x81, 0x89, 0x8f, 0x96, 0x9b, 0x9c,
0x98, 0x91, 0x88, 0x7e, 0x77, 0x74, 0x73, 0x74, 0x77, 0x7b, 0x7c, 0x7a, 0x77, 0x73, 0x6d, 0x69,
0x68, 0x6a, 0x73, 0x7f, 0x87, 0x8e, 0x99, 0xa1, 0x9e, 0x97, 0x90, 0x86, 0x7c, 0x76, 0x77, 0x7b,
0x80, 0x89, 0x91, 0x93, 0x91, 0x8e, 0x87, 0x7c, 0x71, 0x6b, 0x65, 0x60, 0x5d, 0x5f, 0x60, 0x61,
0x6b, 0x7b, 0x84, 0x8d, 0xa0, 0xae, 0xae, 0xa8, 0xa1, 0x94, 0x81, 0x73, 0x6f, 0x70, 0x74, 0x7e,
0x8d, 0x95, 0x97, 0x98, 0x92, 0x83, 0x72, 0x69, 0x61, 0x5a, 0x56, 0x59, 0x5d, 0x5f, 0x65, 0x75,
0x82, 0x87, 0x95, 0xaa, 0xb4, 0xb0, 0xaa, 0xa0, 0x8d, 0x77, 0x6c, 0x6c, 0x6d, 0x72, 0x81, 0x91,
0x98, 0x9a, 0x9a, 0x8f, 0x7a, 0x6a, 0x61, 0x58, 0x4f, 0x50, 0x57, 0x5b, 0x61, 0x74, 0x85, 0x8a,
0x96, 0xab, 0xb4, 0xae, 0xa5, 0x9c, 0x88, 0x71, 0x67, 0x69, 0x6c, 0x73, 0x85, 0x96, 0x9d, 0xa1,
0xa3, 0x96, 0x7f, 0x6e, 0x63, 0x56, 0x4c, 0x4d, 0x52, 0x53, 0x58, 0x6b, 0x80, 0x86, 0x92, 0xaa,
0xb8, 0xb4, 0xac, 0xa5, 0x90, 0x75, 0x69, 0x6a, 0x6c, 0x73, 0x86, 0x98, 0x9c, 0xa2, 0xa7, 0x99,
0x7f, 0x6e, 0x61, 0x54, 0x4c, 0x4b, 0x4d, 0x4f, 0x54, 0x66, 0x7c, 0x85, 0x90, 0xa9, 0xbc, 0xba,
0xb4, 0xac, 0x95, 0x78, 0x69, 0x67, 0x67, 0x71, 0x86, 0x99, 0x9d, 0xa4, 0xab, 0x9b, 0x7f, 0x6e,
0x5f, 0x50, 0x4b, 0x4e, 0x4e, 0x4e, 0x54, 0x60, 0x77, 0x86, 0x8e, 0xa4, 0xbb, 0xbf, 0xb9, 0xb3,
0x9e, 0x7d, 0x68, 0x65, 0x63, 0x6b, 0x84, 0x9a, 0x9d, 0xa3, 0xb0, 0x9f, 0x83, 0x71, 0x5f, 0x4d,
0x4c, 0x51, 0x51, 0x51, 0x56, 0x5a, 0x64, 0x7d, 0x90, 0x99, 0xad, 0xc3, 0xc2, 0xb5, 0xaa, 0x92,
0x71, 0x62, 0x65, 0x6a, 0x78, 0x92, 0xa2, 0xa1, 0xa7, 0xa8, 0x91, 0x78, 0x66, 0x55, 0x4a, 0x50,
0x54, 0x50, 0x50, 0x58, 0x5a, 0x65, 0x8b, 0x9b, 0x9b, 0xb7, 0xc9, 0xb3, 0xa6, 0xa2, 0x7d, 0x5a,
0x66, 0x6f, 0x70, 0x94, 0xa2, 0x90, 0x9b, 0xa5, 0x8f, 0x82, 0x77, 0x5c, 0x58, 0x60, 0x50, 0x46,
0x56, 0x49, 0x3a, 0x54, 0x97, 0xbe, 0xa9, 0xb0, 0xad, 0x91, 0xa7, 0xb3, 0x83, 0x6f, 0x6c, 0x5b,
0x71, 0x91, 0x9c, 0xac, 0x98, 0x78, 0x8a, 0xa6, 0xad, 0x9e, 0x72, 0x4d, 0x4e, 0x4f, 0x4e, 0x4a,
0x48, 0x46, 0x42, 0x4e, 0x99, 0xd5, 0xae, 0xb0, 0xb1, 0x8a, 0xb3, 0xbd, 0x82, 0x6b, 0x53, 0x56,
0x8b, 0x97, 0xa7, 0xaf, 0x74, 0x6b, 0x92, 0xaf, 0xc1, 0x8f, 0x55, 0x47, 0x4e, 0x60, 0x5e, 0x45,
0x4a, 0x4f, 0x3a, 0x44, 0x9f, 0xdf, 0xac, 0xa8, 0x93, 0x79, 0xbf, 0xc3, 0x92, 0x67, 0x36, 0x5a,
0x90, 0x9b, 0xb6, 0xa1, 0x6b, 0x68, 0x8d, 0xc3, 0xca, 0x83, 0x4f, 0x3d, 0x53, 0x72, 0x63, 0x46,
0x44, 0x55, 0x4f, 0x4c, 0x78, 0xcb, 0xbb, 0x93, 0x99, 0x79, 0xad, 0xd0, 0x9f, 0x70, 0x37, 0x4f,
0x90, 0x9e, 0xaf, 0x94, 0x73, 0x71, 0x89, 0xc0, 0xc0, 0x8f, 0x5b, 0x45, 0x62, 0x79, 0x6f, 0x5b,
0x46, 0x56, 0x54, 0x53, 0x59, 0x90, 0xd8, 0x95, 0x8c, 0x8c, 0x88, 0xd6, 0xb8, 0x83, 0x4c, 0x2f,
0x80, 0xa2, 0xaa, 0x9c, 0x69, 0x74, 0x80, 0xb0, 0xc6, 0x99, 0x78, 0x54, 0x69, 0x80, 0x7c, 0x69,
0x4b, 0x4e, 0x57, 0x4e, 0x4c, 0x5f, 0xae, 0xc3, 0x82, 0x86, 0x83, 0xac, 0xd9, 0xa3, 0x6a, 0x31,
0x50, 0xa0, 0xad, 0xa6, 0x6d, 0x59, 0x7f, 0x9e, 0xc8, 0xaf, 0x81, 0x74, 0x70, 0x8b, 0x83, 0x76,
0x58, 0x50, 0x56, 0x59, 0x58, 0x49, 0x62, 0x7c, 0xce, 0x99, 0x71, 0x9c, 0x8d, 0xd4, 0xb1, 0x6c,
0x4f, 0x37, 0x95, 0xab, 0x9b, 0x7f, 0x4b, 0x82, 0xa2, 0xba, 0xb5, 0x7b, 0x7d, 0x7d, 0x8d, 0x8b,
0x71, 0x62, 0x54, 0x5b, 0x4e, 0x5d, 0x4c, 0x5e, 0x57, 0x9c, 0xd4, 0x67, 0x94, 0x83, 0xa2, 0xd8,
0x83, 0x70, 0x2e, 0x59, 0xb5, 0x9d, 0xa1, 0x51, 0x55, 0x97, 0xad, 0xcb, 0x86, 0x77, 0x78, 0x95,
0xa1, 0x76, 0x6d, 0x58, 0x67, 0x5b, 0x4f, 0x66, 0x55, 0x67, 0x4e, 0x67, 0xd9, 0x88, 0x89, 0x86,
0x6f, 0xcd, 0x9b, 0x89, 0x4e, 0x39, 0x9f, 0xa0, 0xa9, 0x7a, 0x47, 0x88, 0x99, 0xbe, 0xac, 0x6b,
0x88, 0x87, 0xaf, 0x9a, 0x67, 0x71, 0x63, 0x74, 0x62, 0x55, 0x5c, 0x5e, 0x65, 0x5c, 0x54, 0xb1,
0xb0, 0x79, 0x8d, 0x6f, 0xac, 0xb7, 0x8e, 0x73, 0x44, 0x7b, 0xa1, 0x99, 0x90, 0x5a, 0x70, 0x97,
0xa0, 0xb4, 0x89, 0x83, 0x8e, 0x96, 0xa3, 0x7e, 0x6f, 0x6c, 0x6a, 0x6b, 0x5b, 0x5a, 0x61, 0x5e,
0x5d, 0x63, 0x66, 0xa0, 0xa6, 0x7c, 0x8d, 0x83, 0xa4, 0xad, 0x88, 0x7b, 0x58, 0x75, 0x95, 0x91,
0x92, 0x70, 0x75, 0x93, 0x9c, 0xab, 0x92, 0x84, 0x8d, 0x91, 0x96, 0x81, 0x70, 0x6b, 0x6c, 0x68,
0x62, 0x59, 0x5e, 0x69, 0x5a, 0x5a, 0x68, 0x5f, 0xa2, 0xb0, 0x6d, 0x87, 0x7e, 0xa0, 0xba, 0x89,
0x78, 0x53, 0x73, 0xa6, 0x9b, 0x95, 0x6c, 0x65, 0x8e, 0x9a, 0xab, 0x97, 0x7b, 0x85, 0x8e, 0x9a,
0x91, 0x71, 0x6b, 0x68, 0x65, 0x6e, 0x58, 0x5d, 0x70, 0x5d, 0x6d, 0x67, 0x5e, 0x80, 0x78, 0x94,
0x98, 0x7c, 0x96, 0x90, 0xa1, 0xa5, 0x82, 0x7f, 0x70, 0x7e, 0x94, 0x87, 0x87, 0x80, 0x88, 0x92,
0x8e, 0x96, 0x8c, 0x89, 0x84, 0x73, 0x72, 0x6f, 0x71, 0x6d, 0x5e, 0x61, 0x6a, 0x70, 0x77, 0x6f,
0x6d, 0x79, 0x76, 0x7f, 0x77, 0x75, 0x7e, 0x90, 0xa8, 0x8c, 0x85, 0x98, 0x9b, 0xa7, 0x93, 0x79,
0x78, 0x79, 0x91, 0x94, 0x87, 0x86, 0x85, 0x86, 0x8b, 0x89, 0x82, 0x7c, 0x74, 0x6d, 0x6c, 0x75,
0x75, 0x6f, 0x64, 0x69, 0x74, 0x7e, 0x83, 0x76, 0x75, 0x85, 0x8a, 0x89, 0x88, 0x78, 0x81, 0x88,
0x83, 0x85, 0x7e, 0x80, 0x88, 0x89, 0x8c, 0x8d, 0x8a, 0x8b, 0x88, 0x88, 0x89, 0x85, 0x81, 0x81,
0x7e, 0x7c, 0x7c, 0x77, 0x7d, 0x76, 0x6f, 0x7d, 0x7f, 0x78, 0x73, 0x76, 0x83, 0x84, 0x80, 0x7f,
0x82, 0x86, 0x80, 0x81, 0x83, 0x81, 0x81, 0x7e, 0x7d, 0x7b, 0x83, 0x8b, 0x85, 0x7a, 0x76, 0x83,
0x87, 0x82, 0x7d, 0x76, 0x7b, 0x80, 0x83, 0x81, 0x7a, 0x79, 0x7d, 0x82, 0x81, 0x82, 0x82, 0x83,
0x86, 0x80, 0x80, 0x81, 0x7e, 0x80, 0x7d, 0x7a, 0x7e, 0x81, 0x7e, 0x7e, 0x80, 0x7f, 0x81, 0x82,
0x80, 0x81, 0x82, 0x7f, 0x7f, 0x7d, 0x7c, 0x7f, 0x7b, 0x7b, 0x7d, 0x7a, 0x7a, 0x7e, 0x7e, 0x7c,
0x7c, 0x7f, 0x80, 0x7f, 0x80, 0x82, 0x81, 0x81, 0x80, 0x7e, 0x80, 0x7f, 0x81, 0x7b, 0x7c, 0x7f,
0x7f, 0x81, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x83, 0x7e, 0x7f, 0x85, 0x81, 0x83,
0x84, 0x80, 0x84, 0x81, 0x81, 0x83, 0x81, 0x83, 0x80, 0x84, 0x80, 0x80, 0x85, 0x80, 0x81, 0x7f,
0x82, 0x82, 0x81, 0x81, 0x80, 0x81, 0x80, 0x87, 0x81, 0x7c, 0x80, 0x7f, 0x80, 0x7d, 0x7c, 0x7d,
0x80, 0x80, 0x80, 0x82, 0x7d, 0x81, 0x82, 0x7e, 0x82, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x82,
0x7f, 0x80, 0x7f, 0x7f, 0x81, 0x7f, 0x80, 0x7e, 0x81, 0x80, 0x7e, 0x80, 0x7e, 0x7f, 0x80, 0x80,
0x82, 0x7f, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x80, 0x80,
0x80, 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x7d, 0x7e, 0x7d, 0x7c, 0x7d, 0x7c, 0x7c,
0x7d, 0x7c, 0x7d, 0x7e, 0x7f, 0x7e, 0x7e, 0x7f, 0x7d, 0x7f, 0x7f, 0x80, 0x7f, 0x7e, 0x7f, 0x80,
0x7e, 0x80, 0x7e, 0x7e, 0x80, 0x7e, 0x80, 0x7e, 0x7f, 0x7e, 0x7d, 0x7f, 0x7d, 0x7d, 0x7d, 0x7d,
0x7d, 0x7d, 0x7e, 0x7f, 0x7f, 0x7d, 0x7e, 0x7f, 0x7e, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80,
0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f,
0x7f, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80,
0x81, 0x80, 0x82, 0x83, 0x81, 0x82, 0x81, 0x82, 0x82, 0x82, 0x81, 0x81, 0x83, 0x82, 0x82, 0x82,
0x81, 0x83, 0x82, 0x81, 0x81, 0x80, 0x80, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7e, 0x80, 0x7d, 0x80,
0x81, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x80, 0x81, 0x81, 0x80,
0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x81, 0x80, 0x7f, 0x81, 0x81, 0x82, 0x81,
0x80, 0x82, 0x82, 0x80, 0x81, 0x81, 0x80, 0x80, 0x7e, 0x7d, 0x7f, 0x7e, 0x81, 0x81, 0x7e, 0x7f,
0x82, 0x7f, 0x7d, 0x7f, 0x7d, 0x81, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x80,
0x7f, 0x7e, 0x7f, 0x7f, 0x7e, 0x7c, 0x7d, 0x7e, 0x7d, 0x7d, 0x7e, 0x7d, 0x7e, 0x7c, 0x7e, 0x7e,
0x7c, 0x7e, 0x7d, 0x7e, 0x7e, 0x7e, 0x7d, 0x7d, 0x7c, 0x7b, 0x7c, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
0x7b, 0x7c, 0x7c, 0x7d, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d,
0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x81,
0x81, 0x81, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82,
0x81, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e,
0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f,
0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x81, 0x80, 0x83, 0x80, 0x80, 0x80, 0x84, 0x84,
0x7b, 0x7e, 0x80, 0x80, 0x7e, 0x80, 0x7e, 0x7f, 0x81, 0x81, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x7e,
0x7f, 0x80, 0x80, 0x7f, 0x81, 0x82, 0x80, 0x80, 0x81, 0x81, 0x80, 0x81, 0x7f, 0x80, 0x80, 0x81,
0x81, 0x81, 0x81, 0x84, 0x83, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x81, 0x7e, 0x7e, 0x7f, 0x81, 0x7f,
0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x81, 0x82, 0x82, 0x80, 0x7f, 0x80,
0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x7d, 0x7e, 0x7e, 0x7f, 0x80,
0x80, 0x80, 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x80, 0x80, 0x81, 0x7f, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7f,
0x7e, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7e, 0x80, 0x7e, 0x7f, 0x7f,
0x7e, 0x7f, 0x7e, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x7f, 0x80, 0x80, 0x82,
0x81, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x81, 0x80, 0x81, 0x80, 0x82, 0x7f,
0x7f, 0x7e, 0x7e, 0x80, 0x7e, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x81, 0x80,
0x81, 0x80, 0x80, 0x81, 0x80, 0x83, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7e, 0x80, 0x7f,
0x7f, 0x80, 0x7f, 0x82, 0x80, 0x81, 0x7f, 0x7e, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80,
0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x81, 0x80, 0x80, 0x80, 0x81, 0x81, 0x7f, 0x7f, 0x7f,
0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x81, 0x7f, 0x80, 0x7e, 0x7f, 0x7f,
0x7e, 0x80, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7d, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x80,
0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x81, 0x81, 0x81, 0x80, 0x80, 0x7f, 0x7f, 0x80, 0x7f,
0x7f, 0x7f, 0x81, 0x81, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x7f, 0x7f,
0x7f, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x80, 0x80, 0x7f, 0x7e, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7e, 0x7f, 0x7e
};
static const Uint8 right[1777] = {
0x7f, 0x7e, 0x7e, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x82, 0x83, 0x83, 0x83,
0x82, 0x81, 0x81, 0x80, 0x7f, 0x7e, 0x7c, 0x7b, 0x7a, 0x7a, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, 0x88, 0x89, 0x89, 0x89, 0x88, 0x87, 0x84, 0x82, 0x80, 0x7e,
0x7c, 0x7b, 0x7a, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x76, 0x77, 0x78, 0x78, 0x78, 0x7b, 0x81, 0x87,
0x8c, 0x8e, 0x90, 0x92, 0x91, 0x8d, 0x87, 0x81, 0x7d, 0x7b, 0x7a, 0x79, 0x79, 0x7a, 0x79, 0x78,
0x75, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76, 0x76, 0x7b, 0x83, 0x88, 0x8b, 0x8f, 0x95, 0x98,
0x95, 0x8d, 0x86, 0x83, 0x80, 0x7e, 0x7c, 0x7c, 0x7e, 0x7e, 0x7c, 0x79, 0x78, 0x76, 0x75, 0x72,
0x73, 0x74, 0x72, 0x6f, 0x6d, 0x72, 0x7e, 0x87, 0x8b, 0x90, 0x98, 0x9f, 0x9b, 0x91, 0x85, 0x7f,
0x7b, 0x78, 0x79, 0x7f, 0x87, 0x8b, 0x8a, 0x89, 0x89, 0x86, 0x81, 0x79, 0x75, 0x74, 0x73, 0x73,
0x6f, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x72, 0x77, 0x82, 0x8f, 0x95, 0x99, 0x9c, 0x9e, 0x99, 0x8c,
0x7f, 0x74, 0x71, 0x70, 0x74, 0x7e, 0x8a, 0x92, 0x91, 0x8f, 0x8f, 0x8d, 0x85, 0x7c, 0x76, 0x75,
0x76, 0x75, 0x71, 0x6d, 0x6b, 0x68, 0x64, 0x64, 0x66, 0x6e, 0x83, 0x8f, 0x93, 0x9b, 0xa3, 0xa4,
0x97, 0x86, 0x76, 0x6f, 0x6d, 0x6e, 0x78, 0x87, 0x94, 0x98, 0x96, 0x94, 0x91, 0x89, 0x7e, 0x74,
0x6f, 0x70, 0x74, 0x72, 0x6e, 0x6b, 0x67, 0x62, 0x60, 0x60, 0x69, 0x84, 0x91, 0x95, 0xa1, 0xae,
0xb0, 0x9b, 0x84, 0x74, 0x6a, 0x65, 0x67, 0x78, 0x8b, 0x98, 0x9f, 0x9e, 0x9a, 0x90, 0x86, 0x7c,
0x71, 0x6a, 0x6c, 0x73, 0x74, 0x6d, 0x69, 0x65, 0x5e, 0x5c, 0x60, 0x6f, 0x8b, 0x95, 0x9b, 0xac,
0xb3, 0xa5, 0x89, 0x7a, 0x6b, 0x5c, 0x5f, 0x70, 0x88, 0x97, 0xa5, 0xac, 0xa1, 0x95, 0x8e, 0x86,
0x76, 0x6a, 0x6b, 0x72, 0x72, 0x6c, 0x67, 0x5e, 0x55, 0x52, 0x56, 0x78, 0x9c, 0x91, 0x9c, 0xbc,
0xb8, 0x98, 0x83, 0x7f, 0x5e, 0x4c, 0x6c, 0x83, 0x8a, 0x9a, 0xb7, 0xae, 0x8a, 0x8f, 0x93, 0x79,
0x69, 0x76, 0x76, 0x69, 0x70, 0x70, 0x5b, 0x50, 0x51, 0x57, 0x52, 0x77, 0xb2, 0x90, 0x95, 0xc8,
0xb1, 0x8d, 0x89, 0x8a, 0x55, 0x4e, 0x87, 0x7f, 0x82, 0xb3, 0xb9, 0x8f, 0x8c, 0x9d, 0x79, 0x71,
0x80, 0x6a, 0x61, 0x7b, 0x70, 0x51, 0x63, 0x62, 0x3e, 0x50, 0x61, 0x9a, 0xad, 0x7e, 0xba, 0xb5,
0x94, 0x9f, 0x93, 0x75, 0x4b, 0x7b, 0x79, 0x6c, 0xab, 0xaf, 0x9f, 0x93, 0x8e, 0x7a, 0x7f, 0x89,
0x6a, 0x6e, 0x71, 0x66, 0x5e, 0x63, 0x5c, 0x53, 0x53, 0x50, 0x5a, 0xb8, 0xbd, 0x6d, 0xc3, 0xb2,
0x8a, 0xa7, 0xa1, 0x70, 0x4c, 0x88, 0x63, 0x7d, 0xb1, 0xa1, 0xa6, 0x8e, 0x6a, 0x7c, 0x95, 0x8b,
0x84, 0x72, 0x5c, 0x5c, 0x67, 0x64, 0x61, 0x56, 0x65, 0x52, 0x44, 0x80, 0xda, 0x8a, 0x88, 0xc9,
0x89, 0x96, 0xb1, 0x92, 0x4a, 0x6f, 0x6d, 0x78, 0xa5, 0xa7, 0xa0, 0x98, 0x66, 0x6e, 0xa6, 0x9d,
0x95, 0x70, 0x52, 0x57, 0x73, 0x69, 0x72, 0x5a, 0x55, 0x52, 0x50, 0x3d, 0xb8, 0xdb, 0x5d, 0xa9,
0xab, 0x82, 0xad, 0xc3, 0x65, 0x4c, 0x6c, 0x6d, 0x98, 0xac, 0x9f, 0x97, 0x74, 0x5a, 0xa0, 0xb1,
0x9e, 0x7e, 0x52, 0x54, 0x74, 0x71, 0x6a, 0x6a, 0x5a, 0x53, 0x4b, 0x46, 0x5e, 0xe5, 0xaa, 0x62,
0xab, 0x8f, 0x97, 0xcb, 0xa5, 0x4b, 0x4f, 0x67, 0x88, 0xa6, 0xa4, 0x98, 0x84, 0x61, 0x80, 0xb7,
0xb4, 0x98, 0x64, 0x4e, 0x64, 0x77, 0x72, 0x72, 0x55, 0x54, 0x4e, 0x52, 0x3c, 0x96, 0xf0, 0x69,
0x7f, 0xa2, 0x80, 0xc1, 0xc8, 0x75, 0x46, 0x4d, 0x74, 0xa4, 0x9e, 0x95, 0x8a, 0x6a, 0x73, 0xa6,
0xb7, 0xb4, 0x81, 0x60, 0x5e, 0x71, 0x7c, 0x74, 0x6b, 0x54, 0x54, 0x48, 0x4f, 0x44, 0xc3, 0xcb,
0x5b, 0x9b, 0x86, 0x99, 0xd4, 0xa3, 0x71, 0x3e, 0x4b, 0x91, 0x99, 0x9d, 0x95, 0x70, 0x72, 0x85,
0xb0, 0xbd, 0xa5, 0x7e, 0x67, 0x67, 0x78, 0x77, 0x6e, 0x63, 0x53, 0x5b, 0x39, 0x50, 0x48, 0xb5,
0xc2, 0x6a, 0xa5, 0x77, 0xa8, 0xbd, 0x98, 0x89, 0x3a, 0x60, 0x83, 0x85, 0xa9, 0x87, 0x87, 0x74,
0x77, 0xac, 0xa9, 0xb9, 0x8a, 0x71, 0x6b, 0x6d, 0x81, 0x6d, 0x66, 0x51, 0x60, 0x3c, 0x50, 0x4a,
0x91, 0xbf, 0x83, 0xae, 0x7a, 0xa4, 0xa1, 0x97, 0x92, 0x4b, 0x73, 0x68, 0x86, 0x8e, 0x8c, 0x95,
0x79, 0x83, 0x86, 0xa2, 0xab, 0xa6, 0x8d, 0x79, 0x6a, 0x75, 0x68, 0x74, 0x56, 0x5c, 0x4e, 0x4c,
0x49, 0x5d, 0xb1, 0x88, 0xb9, 0x8d, 0xa4, 0x90, 0x94, 0x8b, 0x66, 0x72, 0x69, 0x83, 0x7c, 0x91,
0x82, 0x89, 0x79, 0x87, 0x8a, 0xa1, 0x9f, 0xa5, 0x95, 0x8d, 0x7a, 0x6f, 0x6f, 0x61, 0x62, 0x58,
0x5f, 0x52, 0x52, 0x4f, 0x80, 0x90, 0xa1, 0xa6, 0xa3, 0x9c, 0x90, 0x86, 0x74, 0x6d, 0x6c, 0x7a,
0x83, 0x8a, 0x8c, 0x88, 0x7f, 0x80, 0x82, 0x8f, 0x99, 0x9e, 0xa3, 0x9a, 0x93, 0x84, 0x73, 0x68,
0x5d, 0x5e, 0x5d, 0x5f, 0x5e, 0x5d, 0x52, 0x6a, 0x7d, 0x8d, 0x9f, 0xa6, 0xac, 0xa0, 0x95, 0x7d,
0x6e, 0x64, 0x6a, 0x76, 0x81, 0x8e, 0x98, 0x94, 0x8e, 0x84, 0x84, 0x84, 0x86, 0x91, 0x98, 0x9d,
0x9a, 0x8c, 0x7b, 0x67, 0x5c, 0x58, 0x58, 0x5e, 0x5e, 0x64, 0x60, 0x67, 0x75, 0x7f, 0x8e, 0x99,
0xa2, 0xa5, 0xa2, 0x99, 0x87, 0x74, 0x6a, 0x67, 0x6e, 0x7b, 0x87, 0x96, 0x97, 0x97, 0x94, 0x8e,
0x8c, 0x8a, 0x8b, 0x8a, 0x8a, 0x88, 0x84, 0x7b, 0x72, 0x66, 0x5e, 0x58, 0x57, 0x5a, 0x60, 0x64,
0x6c, 0x78, 0x81, 0x8c, 0x96, 0x9d, 0x9f, 0xa1, 0x99, 0x8f, 0x80, 0x76, 0x70, 0x6c, 0x70, 0x76,
0x81, 0x8a, 0x93, 0x97, 0x98, 0x94, 0x91, 0x8c, 0x8a, 0x87, 0x81, 0x7c, 0x74, 0x71, 0x6b, 0x68,
0x65, 0x62, 0x60, 0x61, 0x63, 0x67, 0x6c, 0x77, 0x82, 0x8a, 0x96, 0x9c, 0xa4, 0xa5, 0xa0, 0x95,
0x86, 0x7b, 0x71, 0x6e, 0x6e, 0x73, 0x79, 0x82, 0x8b, 0x94, 0x99, 0x98, 0x95, 0x8e, 0x88, 0x81,
0x7b, 0x77, 0x73, 0x6f, 0x6c, 0x6a, 0x68, 0x67, 0x66, 0x69, 0x69, 0x6e, 0x70, 0x77, 0x81, 0x88,
0x91, 0x97, 0x9f, 0xa1, 0xa2, 0x9b, 0x92, 0x82, 0x77, 0x6c, 0x6a, 0x6b, 0x71, 0x79, 0x83, 0x8d,
0x93, 0x97, 0x96, 0x95, 0x8f, 0x8b, 0x84, 0x7d, 0x76, 0x71, 0x6a, 0x68, 0x67, 0x68, 0x6b, 0x6d,
0x71, 0x73, 0x76, 0x79, 0x7e, 0x83, 0x8a, 0x8f, 0x94, 0x97, 0x97, 0x95, 0x8f, 0x87, 0x7f, 0x79,
0x76, 0x76, 0x78, 0x7a, 0x7e, 0x81, 0x86, 0x8a, 0x8c, 0x8e, 0x8d, 0x8a, 0x86, 0x80, 0x7c, 0x78,
0x74, 0x71, 0x70, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x82, 0x81, 0x80,
0x7e, 0x7f, 0x81, 0x84, 0x88, 0x8b, 0x8d, 0x8d, 0x8b, 0x87, 0x83, 0x7d, 0x7a, 0x77, 0x78, 0x7a,
0x7e, 0x81, 0x83, 0x84, 0x84, 0x84, 0x82, 0x80, 0x7f, 0x7d, 0x7b, 0x7a, 0x78, 0x78, 0x77, 0x78,
0x78, 0x79, 0x7c, 0x7e, 0x81, 0x83, 0x83, 0x84, 0x83, 0x82, 0x81, 0x80, 0x80, 0x7f, 0x7f, 0x80,
0x80, 0x81, 0x82, 0x83, 0x84, 0x84, 0x84, 0x83, 0x83, 0x81, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80,
0x7f, 0x7e, 0x7d, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x80, 0x80, 0x81, 0x80, 0x7f, 0x7e, 0x7d,
0x7d, 0x7d, 0x7e, 0x80, 0x80, 0x81, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x81, 0x80,
0x81, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x80, 0x80, 0x7e, 0x7d, 0x7d, 0x7e, 0x7e, 0x7f,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x80, 0x80, 0x80, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x82, 0x82, 0x82, 0x81, 0x80,
0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f,
0x80, 0x80, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f,
0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
0x81, 0x81, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x81, 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e,
0x7e, 0x7d, 0x7e, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x82, 0x82, 0x81, 0x81, 0x80, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x7f, 0x80,
0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7f, 0x87, 0x83, 0x7d, 0x81, 0x80, 0x7e, 0x81, 0x7b,
0x7d, 0x84, 0x7f, 0x81, 0x83, 0x82, 0x7f, 0x80, 0x7c, 0x7b, 0x7d, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x7e, 0x7f, 0x7e, 0x7f, 0x80, 0x80, 0x81, 0x82, 0x82, 0x82, 0x82, 0x80, 0x80, 0x7f, 0x7f,
0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x82, 0x80, 0x7f, 0x80, 0x81, 0x80, 0x81, 0x7f,
0x83, 0x85, 0x7f, 0x80, 0x84, 0x83, 0x7d, 0x7c, 0x7d, 0x80, 0x7d, 0x7d, 0x7e, 0x7e, 0x7d, 0x83,
0x81, 0x7d, 0x7d, 0x81, 0x7f, 0x7c, 0x7c, 0x7c, 0x7d, 0x7c, 0x83, 0x80, 0x84, 0x84, 0x82, 0x7d,
0x7f, 0x7d, 0x7c, 0x7e, 0x7e, 0x7f, 0x81, 0x84, 0x82, 0x81, 0x7e, 0x7f, 0x7f, 0x7f, 0x7e, 0x80,
0x81, 0x80, 0x7f, 0x80, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81,
0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82, 0x81, 0x83, 0x81, 0x82, 0x80, 0x80, 0x7f, 0x7f, 0x80,
0x7d, 0x80, 0x7e, 0x81, 0x7f, 0x81, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x7d, 0x81, 0x80, 0x82, 0x7f,
0x81, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7e, 0x80, 0x7f, 0x81, 0x7f, 0x81, 0x81, 0x81, 0x81, 0x81,
0x82, 0x81, 0x81, 0x80, 0x81, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7e,
0x7f, 0x7e, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7e, 0x80, 0x7f, 0x82, 0x80, 0x81, 0x81, 0x80,
0x81, 0x80, 0x81, 0x80, 0x81, 0x80, 0x81, 0x80, 0x80, 0x7e, 0x7f, 0x7e, 0x7d, 0x7e, 0x7e, 0x7f,
0x7f, 0x7f, 0x7e, 0x7d, 0x80, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x81, 0x7e, 0x81, 0x81, 0x83,
0x80, 0x81, 0x80, 0x80, 0x81, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x7f, 0x80, 0x7f, 0x80, 0x7d, 0x80,
0x7e, 0x7d, 0x80, 0x80, 0x83, 0x7f, 0x83, 0x7e, 0x83, 0x7f, 0x80, 0x7f, 0x7e, 0x81, 0x7f, 0x7f,
0x80, 0x80, 0x81, 0x7e, 0x7f, 0x7f, 0x80, 0x81, 0x80, 0x83, 0x7f, 0x82, 0x7f, 0x82, 0x7f, 0x80,
0x80, 0x7e, 0x7f, 0x7d, 0x7e, 0x7d, 0x7e, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x81,
0x82, 0x80, 0x82, 0x80, 0x82, 0x80, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x80, 0x7e, 0x80, 0x80, 0x81,
0x7f, 0x7f, 0x7e, 0x80, 0x7d, 0x7e, 0x7e, 0x7f, 0x80, 0x7f, 0x80, 0x7e, 0x81, 0x7e, 0x81, 0x7f,
0x80, 0x7f, 0x80, 0x81, 0x7f, 0x80, 0x7e, 0x81, 0x7e, 0x80, 0x7d, 0x80, 0x80, 0x80, 0x81, 0x80,
0x82, 0x7e, 0x83, 0x7d, 0x80, 0x7c, 0x7d, 0x7e, 0x7c, 0x7e, 0x7d, 0x7e, 0x7f, 0x7e, 0x7e, 0x80,
0x7e, 0x81, 0x7e, 0x81, 0x7f, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x83, 0x80, 0x81, 0x80,
0x80, 0x80, 0x80, 0x7f, 0x80, 0x7e, 0x7f, 0x7f, 0x81, 0x7f, 0x80, 0x80, 0x7f, 0x7e, 0x80, 0x80,
0x81, 0x82, 0x81, 0x82, 0x81, 0x81, 0x81, 0x82, 0x80, 0x80, 0x7e, 0x82, 0x80, 0x84, 0x81, 0x80,
0x7f, 0x81, 0x80, 0x7f, 0x80, 0x7d, 0x80, 0x7d, 0x81, 0x7f, 0x81, 0x80, 0x81, 0x81, 0x80, 0x80,
0x7e, 0x80, 0x7f, 0x81, 0x7f, 0x81, 0x81, 0x81, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x81, 0x80, 0x80, 0x7e, 0x81, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x7e, 0x81,
0x7e, 0x7f, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x7f, 0x81, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x80,
0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7f, 0x7e, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7e, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81,
0x80
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -33,7 +33,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/camera/read-and-draw", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/camera/read-and-draw", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
@@ -83,6 +83,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
the window when we get a first frame from the camera. */
if (!texture) {
SDL_SetWindowSize(window, frame->w, frame->h); /* Resize the window to match */
SDL_SetRenderLogicalPresentation(renderer, frame->w, frame->h, SDL_LOGICAL_PRESENTATION_LETTERBOX);
texture = SDL_CreateTexture(renderer, frame->format, SDL_TEXTUREACCESS_STREAMING, frame->w, frame->h);
}
+1
View File
@@ -10,4 +10,5 @@ audio
camera
asyncio
pen
misc
demo
+54 -8
View File
@@ -18,9 +18,12 @@
#define SNAKE_GAME_HEIGHT 18U
#define SNAKE_MATRIX_SIZE (SNAKE_GAME_WIDTH * SNAKE_GAME_HEIGHT)
#define THREE_BITS 0x7U /* ~CHAR_MAX >> (CHAR_BIT - SNAKE_CELL_MAX_BITS) */
#define SNAKE_CELL_MAX_BITS 3U /* floor(log2(SNAKE_CELL_FOOD)) + 1 */
#define SNAKE_CELL_SET_BITS (~(~0u << SNAKE_CELL_MAX_BITS))
#define SHIFT(x, y) (((x) + ((y) * SNAKE_GAME_WIDTH)) * SNAKE_CELL_MAX_BITS)
static SDL_Joystick *joystick = NULL;
typedef enum
{
SNAKE_CELL_NOTHING = 0U,
@@ -31,8 +34,6 @@ typedef enum
SNAKE_CELL_FOOD = 5U
} SnakeCell;
#define SNAKE_CELL_MAX_BITS 3U /* floor(log2(SNAKE_CELL_FOOD)) + 1 */
typedef enum
{
SNAKE_DIR_RIGHT,
@@ -66,7 +67,7 @@ SnakeCell snake_cell_at(const SnakeContext *ctx, char x, char y)
const int shift = SHIFT(x, y);
unsigned short range;
SDL_memcpy(&range, ctx->cells + (shift / 8), sizeof(range));
return (SnakeCell)((range >> (shift % 8)) & THREE_BITS);
return (SnakeCell)((range >> (shift % 8)) & SNAKE_CELL_SET_BITS);
}
static void set_rect_xy_(SDL_FRect *r, short x, short y)
@@ -82,8 +83,8 @@ static void put_cell_at_(SnakeContext *ctx, char x, char y, SnakeCell ct)
unsigned char *const pos = ctx->cells + (shift / 8);
unsigned short range;
SDL_memcpy(&range, pos, sizeof(range));
range &= ~(THREE_BITS << adjust); /* clear bits */
range |= (ct & THREE_BITS) << adjust;
range &= ~(SNAKE_CELL_SET_BITS << adjust); /* clear bits */
range |= (ct & SNAKE_CELL_SET_BITS) << adjust;
SDL_memcpy(pos, &range, sizeof(range));
}
@@ -186,6 +187,8 @@ void snake_step(SnakeContext *ctx)
case SNAKE_DIR_DOWN:
++ctx->head_ypos;
break;
default:
break;
}
wrap_around_(&ctx->head_xpos, SNAKE_GAME_WIDTH);
wrap_around_(&ctx->head_ypos, SNAKE_GAME_HEIGHT);
@@ -238,6 +241,26 @@ static SDL_AppResult handle_key_event_(SnakeContext *ctx, SDL_Scancode key_code)
return SDL_APP_CONTINUE;
}
static SDL_AppResult handle_hat_event_(SnakeContext *ctx, Uint8 hat) {
switch (hat) {
case SDL_HAT_RIGHT:
snake_redir(ctx, SNAKE_DIR_RIGHT);
break;
case SDL_HAT_UP:
snake_redir(ctx, SNAKE_DIR_UP);
break;
case SDL_HAT_LEFT:
snake_redir(ctx, SNAKE_DIR_LEFT);
break;
case SDL_HAT_DOWN:
snake_redir(ctx, SNAKE_DIR_DOWN);
break;
default:
break;
}
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppIterate(void *appstate)
{
AppState *as = (AppState *)appstate;
@@ -305,7 +328,8 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
}
}
if (!SDL_Init(SDL_INIT_VIDEO)) {
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
@@ -316,9 +340,10 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
*appstate = as;
if (!SDL_CreateWindowAndRenderer("examples/demo/snake", SDL_WINDOW_WIDTH, SDL_WINDOW_HEIGHT, 0, &as->window, &as->renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/demo/snake", SDL_WINDOW_WIDTH, SDL_WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &as->window, &as->renderer)) {
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(as->renderer, SDL_WINDOW_WIDTH, SDL_WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
snake_initialize(&as->snake_ctx);
@@ -333,14 +358,35 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
switch (event->type) {
case SDL_EVENT_QUIT:
return SDL_APP_SUCCESS;
case SDL_EVENT_JOYSTICK_ADDED:
if (joystick == NULL) {
joystick = SDL_OpenJoystick(event->jdevice.which);
if (!joystick) {
SDL_Log("Failed to open joystick ID %u: %s", (unsigned int) event->jdevice.which, SDL_GetError());
}
}
break;
case SDL_EVENT_JOYSTICK_REMOVED:
if (joystick && (SDL_GetJoystickID(joystick) == event->jdevice.which)) {
SDL_CloseJoystick(joystick);
joystick = NULL;
}
break;
case SDL_EVENT_JOYSTICK_HAT_MOTION:
return handle_hat_event_(ctx, event->jhat.value);
case SDL_EVENT_KEY_DOWN:
return handle_key_event_(ctx, event->key.scancode);
default:
break;
}
return SDL_APP_CONTINUE;
}
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
if (joystick) {
SDL_CloseJoystick(joystick);
}
if (appstate != NULL) {
AppState *as = (AppState *)appstate;
SDL_DestroyRenderer(as->renderer);
@@ -265,7 +265,7 @@ static void draw(SDL_Renderer *renderer, const float (*edges)[6], const Player p
SDL_RenderLine(renderer, hor_origin-10, ver_origin, hor_origin+10, ver_origin);
}
}
SDL_SetRenderClipRect(renderer, 0);
SDL_SetRenderClipRect(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDebugText(renderer, 0, 0, debug_string);
SDL_RenderPresent(renderer);
@@ -347,7 +347,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
if (!SDL_Init(SDL_INIT_VIDEO)) {
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/demo/woodeneye-008", 640, 480, 0, &as->window, &as->renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/demo/woodeneye-008", 640, 480, SDL_WINDOW_RESIZABLE, &as->window, &as->renderer)) {
return SDL_APP_FAILURE;
}
@@ -27,13 +27,12 @@
typedef struct {
Uint8 ram[RAM_SIZE + 8];
Uint8 screenbuf[SCREEN_W * SCREEN_H];
Uint64 last_tick;
Uint64 tick_acc;
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Surface* screen;
SDL_Texture* screentex;
SDL_Palette* palette;
SDL_Texture* texture;
SDL_Texture* rendertarget; /* we need this render target for text to look good */
SDL_AudioStream* audiostream;
char status[SCREEN_W / 8];
@@ -131,16 +130,12 @@ static void print(BytePusher* vm, int x, int y, const char* str) {
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
BytePusher* vm;
SDL_Palette* palette;
SDL_Rect usable_bounds;
SDL_AudioSpec audiospec = { SDL_AUDIO_S8, 1, SAMPLES_PER_FRAME * FRAMES_PER_SECOND };
SDL_DisplayID primary_display;
SDL_PropertiesID texprops;
int zoom = 2;
int i;
Uint8 r, g, b;
(void)argc;
(void)argv;
if (!SDL_SetAppMetadata("SDL 3 BytePusher", "1.0", "com.example.SDL3BytePusher")) {
return SDL_APP_FAILURE;
@@ -186,13 +181,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
return SDL_APP_FAILURE;
}
if (!(vm->screen = SDL_CreateSurfaceFrom(
SCREEN_W, SCREEN_H, SDL_PIXELFORMAT_INDEX8, vm->screenbuf, SCREEN_W
))) {
return SDL_APP_FAILURE;
}
if (!(palette = SDL_CreateSurfacePalette(vm->screen))) {
if (!(vm->palette = SDL_CreatePalette(256))) {
return SDL_APP_FAILURE;
}
i = 0;
@@ -200,27 +189,22 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
for (g = 0; g < 6; ++g) {
for (b = 0; b < 6; ++b, ++i) {
SDL_Color color = { (Uint8)(r * 0x33), (Uint8)(g * 0x33), (Uint8)(b * 0x33), SDL_ALPHA_OPAQUE };
palette->colors[i] = color;
vm->palette->colors[i] = color;
}
}
}
for (; i < 256; ++i) {
SDL_Color color = { 0, 0, 0, SDL_ALPHA_OPAQUE };
palette->colors[i] = color;
vm->palette->colors[i] = color;
}
texprops = SDL_CreateProperties();
SDL_SetNumberProperty(texprops, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STREAMING);
SDL_SetNumberProperty(texprops, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, SCREEN_W);
SDL_SetNumberProperty(texprops, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, SCREEN_H);
vm->screentex = SDL_CreateTextureWithProperties(vm->renderer, texprops);
SDL_SetNumberProperty(texprops, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_TARGET);
vm->rendertarget = SDL_CreateTextureWithProperties(vm->renderer, texprops);
SDL_DestroyProperties(texprops);
if (!vm->screentex || !vm->rendertarget) {
vm->texture = SDL_CreateTexture(vm->renderer, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STREAMING, SCREEN_W, SCREEN_H);
vm->rendertarget = SDL_CreateTexture(vm->renderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_TARGET, SCREEN_W, SCREEN_H);
if (!vm->texture || !vm->rendertarget) {
return SDL_APP_FAILURE;
}
SDL_SetTextureScaleMode(vm->screentex, SDL_SCALEMODE_NEAREST);
SDL_SetTexturePalette(vm->texture, vm->palette);
SDL_SetTextureScaleMode(vm->texture, SDL_SCALEMODE_NEAREST);
SDL_SetTextureScaleMode(vm->rendertarget, SDL_SCALEMODE_NEAREST);
if (!(vm->audiostream = SDL_OpenAudioDeviceStream(
@@ -236,6 +220,10 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
vm->last_tick = SDL_GetTicksNS();
vm->tick_acc = NS_PER_SECOND;
if (argc > 1) {
load_file(vm, argv[1]);
}
return SDL_APP_CONTINUE;
}
@@ -284,30 +272,23 @@ SDL_AppResult SDL_AppIterate(void* appstate) {
}
if (updated) {
SDL_Surface *tex;
const void *pixels = &vm->ram[(Uint32)vm->ram[IO_SCREEN_PAGE] << 16];
SDL_UpdateTexture(vm->texture, NULL, pixels, SCREEN_W);
SDL_SetRenderTarget(vm->renderer, vm->rendertarget);
SDL_RenderTexture(vm->renderer, vm->texture, NULL, NULL);
if (!SDL_LockTextureToSurface(vm->screentex, NULL, &tex)) {
return SDL_APP_FAILURE;
if (vm->display_help) {
print(vm, 4, 4, "Drop a BytePusher file in this");
print(vm, 8, 12, "window to load and run it!");
print(vm, 4, 28, "Press ENTER to switch between");
print(vm, 8, 36, "positional and symbolic input.");
}
vm->screen->pixels = &vm->ram[(Uint32)vm->ram[IO_SCREEN_PAGE] << 16];
SDL_BlitSurface(vm->screen, NULL, tex, NULL);
SDL_UnlockTexture(vm->screentex);
SDL_RenderTexture(vm->renderer, vm->screentex, NULL, NULL);
}
if (vm->display_help) {
print(vm, 4, 4, "Drop a BytePusher file in this");
print(vm, 8, 12, "window to load and run it!");
print(vm, 4, 28, "Press ENTER to switch between");
print(vm, 8, 36, "positional and symbolic input.");
}
if (vm->status_ticks > 0) {
vm->status_ticks -= 1;
print(vm, 4, SCREEN_H - 12, vm->status);
if (vm->status_ticks > 0) {
vm->status_ticks -= 1;
print(vm, 4, SCREEN_H - 12, vm->status);
}
}
SDL_SetRenderTarget(vm->renderer, NULL);
@@ -407,8 +388,8 @@ void SDL_AppQuit(void* appstate, SDL_AppResult result) {
BytePusher* vm = (BytePusher*)appstate;
SDL_DestroyAudioStream(vm->audiostream);
SDL_DestroyTexture(vm->rendertarget);
SDL_DestroyTexture(vm->screentex);
SDL_DestroySurface(vm->screen);
SDL_DestroyTexture(vm->texture);
SDL_DestroyPalette(vm->palette);
SDL_DestroyRenderer(vm->renderer);
SDL_DestroyWindow(vm->window);
SDL_free(vm);
@@ -13,8 +13,8 @@
and knows how to map arbitrary buttons and such to look like an
Xbox/PlayStation/etc gamepad. This is easier, and better, for many games,
but isn't necessarily a good fit for complex apps and hardware. A flight
simulator, a realistic racing game, etc, might want this interface instead
of gamepads. */
simulator, a realistic racing game, etc, might want the joystick interface
instead of gamepads. */
/* SDL can handle multiple joysticks, but for simplicity, this program only
deals with the first stick it sees. */
@@ -41,7 +41,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/input/joystick-polling", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/input/joystick-polling", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
@@ -13,8 +13,8 @@
and knows how to map arbitrary buttons and such to look like an
Xbox/PlayStation/etc gamepad. This is easier, and better, for many games,
but isn't necessarily a good fit for complex apps and hardware. A flight
simulator, a realistic racing game, etc, might want this interface instead
of gamepads. */
simulator, a realistic racing game, etc, might want the joystick interface
instead of gamepads. */
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
@@ -111,7 +111,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/input/joystick-events", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/input/joystick-events", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 534 KiB

@@ -0,0 +1,11 @@
This example code looks for the current gamepad state once per frame,
and draws a visual representation of it. See 01-joystick-polling for the
equivalent example code for the lower-level joystick API.
Please note that on the web, gamepads don't show up until you interact with
them, so press a button to "connect" the controller.
Also note that on the web, gamepad triggers are treated as buttons (either
pressed or not) instead of axes (pressed 0 to 100 percent). This is a web
issue, not an SDL limitation.
@@ -0,0 +1,221 @@
/*
* This example code looks for the current gamepad state once per frame,
* and draws a visual representation of it. See 01-joystick-polling for the
* equivalent example code for the lower-level joystick API.
*
* This code is public domain. Feel free to use it for any purpose!
*/
/* Joysticks are low-level interfaces: there's something with a bunch of
buttons, axes and hats, in no understood order or position. This is
a flexible interface, but you'll need to build some sort of configuration
UI to let people tell you what button, etc, does what. On top of this
interface, SDL offers the "gamepad" API, which works with lots of devices,
and knows how to map arbitrary buttons and such to look like an
Xbox/PlayStation/etc gamepad. This is easier, and better, for many games,
but isn't necessarily a good fit for complex apps and hardware. A flight
simulator, a realistic racing game, etc, might want the joystick interface
instead of gamepads. */
/* SDL can handle multiple gamepads, but for simplicity, this program only
deals with the first gamepad it sees. */
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static SDL_Gamepad *gamepad = NULL;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
char *png_path = NULL;
SDL_Surface *surface = NULL;
SDL_SetAppMetadata("Example Input Gamepad Polling", "1.0", "com.example.input-gamepad-polling");
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/input/gamepad-polling", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_STRETCH)) {
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%sgamepad_front.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(png_path); /* done with this, the file is loaded. */
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
} else if (event->type == SDL_EVENT_GAMEPAD_ADDED) {
/* this event is sent for each hotplugged gamepad, but also each already-connected gamepad during SDL_Init(). */
if (gamepad == NULL) { /* we don't have a stick yet and one was added, open it! */
gamepad = SDL_OpenGamepad(event->gdevice.which);
if (!gamepad) {
SDL_Log("Failed to open gamepad ID %u: %s", (unsigned int) event->gdevice.which, SDL_GetError());
}
}
} else if (event->type == SDL_EVENT_GAMEPAD_REMOVED) {
if (gamepad && (SDL_GetGamepadID(gamepad) == event->gdevice.which)) {
SDL_CloseGamepad(gamepad); /* our controller was unplugged. */
gamepad = NULL;
}
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const char *text = "Plug in a gamepad, please.";
static Uint64 leftthumblast = 0xFFFFFFFF;
static Uint64 rightthumblast = 0xFFFFFFFF;
const Uint64 now = SDL_GetTicks();
Sint16 axis_x, axis_y;
float x, y;
int i;
if (gamepad) { /* we have a stick opened? */
text = SDL_GetGamepadName(gamepad);
}
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); /* white */
SDL_RenderClear(renderer);
/* note that you can get input as events, instead of polling, which is
better since it won't miss button presses if the system is lagging,
but often times checking the current state per-frame is good enough,
and maybe better if you'd rather _drop_ inputs due to lag. */
if (gamepad) { /* we have a stick opened? */
/* where to draw the buttons */
const SDL_FRect buttons[] = {
{ 497, 266, 38, 38 }, /* SDL_GAMEPAD_BUTTON_SOUTH */
{ 550, 217, 38, 38 }, /* SDL_GAMEPAD_BUTTON_EAST */
{ 445, 221, 38, 38 }, /* SDL_GAMEPAD_BUTTON_WEST */
{ 499, 173, 38, 38 }, /* SDL_GAMEPAD_BUTTON_NORTH */
{ 235, 228, 32, 29 }, /* SDL_GAMEPAD_BUTTON_BACK */
{ 287, 195, 69, 69 }, /* SDL_GAMEPAD_BUTTON_GUIDE */
{ 377, 228, 32, 29 }, /* SDL_GAMEPAD_BUTTON_START */
{ 91, 234, 63, 63 }, /* SDL_GAMEPAD_BUTTON_LEFT_STICK */
{ 381, 354, 63, 63 }, /* SDL_GAMEPAD_BUTTON_RIGHT_STICK */
{ 74, 73, 102, 29 }, /* SDL_GAMEPAD_BUTTON_LEFT_SHOULDER */
{ 468, 73, 102, 29 }, /* SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER */
{ 207, 316, 32, 32 }, /* SDL_GAMEPAD_BUTTON_DPAD_UP */
{ 207, 384, 32, 32 }, /* SDL_GAMEPAD_BUTTON_DPAD_DOWN */
{ 173, 351, 32, 32 }, /* SDL_GAMEPAD_BUTTON_DPAD_LEFT */
{ 242, 351, 32, 32 }, /* SDL_GAMEPAD_BUTTON_DPAD_RIGHT */
{ 310, 286, 23, 27 }, /* SDL_GAMEPAD_BUTTON_MISC1 */
/* there are other buttons: paddles on the back of the gamepad, touchpads, etc, but this is good enough for now. */
};
SDL_RenderTexture(renderer, texture, NULL, NULL); /* draw the gamepad picture to the whole window. */
/* draw green boxes over buttons that are currently pressed. */
SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF); /* green */
for (i = 0; i < SDL_arraysize(buttons); i++) {
if (SDL_GetGamepadButton(gamepad, (SDL_GamepadButton) i)) {
SDL_RenderFillRect(renderer, &buttons[i]);
}
}
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0x00, 0xFF); /* yellow */
/* left thumb axis. */
axis_x = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTX);
axis_y = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTY);
if ((SDL_abs(axis_x) > 1000) || (SDL_abs(axis_y) > 1000)) { /* zero means centered, but it might be a little off zero... */
leftthumblast = now; /* keep drawing, we're still moving. */
}
if ((now - leftthumblast) < 500) { /* draw if there was movement in the last half-second. */
const SDL_FRect box = { 107 + ((axis_x / 32767.0f) * 30.0f), 252 + ((axis_y / 32767.0f) * 30.0f), 30, 30 };
SDL_RenderFillRect(renderer, &box);
}
/* right thumb axis. */
axis_x = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTX);
axis_y = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTY);
if ((SDL_abs(axis_x) > 1000) || (SDL_abs(axis_y) > 1000)) { /* zero means centered, but it might be a little off zero... */
rightthumblast = now; /* keep drawing, we're still moving. */
}
if ((now - rightthumblast) < 500) { /* draw if there was movement in the last half-second. */
const SDL_FRect box = { 397 + ((axis_x / 32767.0f) * 30.0f), 370 + ((axis_y / 32767.0f) * 30.0f), 30, 30 };
SDL_RenderFillRect(renderer, &box);
}
/* left trigger. */
axis_y = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER);
if (axis_y > 1000) { /* zero means unpressed, but it might be a little off zero... */
const float height = ((axis_y / 32767.0f) * 65.0f);
const SDL_FRect box = { 127, 1 + (65.0f - height), 37, height };
SDL_RenderFillRect(renderer, &box);
}
/* right trigger. */
axis_y = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER);
if (axis_y > 1000) { /* zero means unpressed, but it might be a little off zero... */
const float height = ((axis_y / 32767.0f) * 65.0f);
const SDL_FRect box = { 481, 1 + (65.0f - height), 37, height };
SDL_RenderFillRect(renderer, &box);
}
}
x = (((float) WINDOW_WIDTH) - (SDL_strlen(text) * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE)) / 2.0f;
if (gamepad) {
y = (float) (WINDOW_HEIGHT - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2));
} else {
y = (((float) WINDOW_HEIGHT) - SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) / 2.0f;
}
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0xFF, 0xFF); /* blue */
SDL_RenderDebugText(renderer, x, y, text);
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
SDL_CloseGamepad(gamepad);
/* SDL will clean up the window/renderer for us. */
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

@@ -0,0 +1,2 @@
This example code looks for gamepad input in the event handler, and
reports any changes as a flood of info.
@@ -0,0 +1,212 @@
/*
* This example code looks for gamepad input in the event handler, and
* reports any changes as a flood of info.
*
* This code is public domain. Feel free to use it for any purpose!
*/
/* Joysticks are low-level interfaces: there's something with a bunch of
buttons, axes and hats, in no understood order or position. This is
a flexible interface, but you'll need to build some sort of configuration
UI to let people tell you what button, etc, does what. On top of this
interface, SDL offers the "gamepad" API, which works with lots of devices,
and knows how to map arbitrary buttons and such to look like an
Xbox/PlayStation/etc gamepad. This is easier, and better, for many games,
but isn't necessarily a good fit for complex apps and hardware. A flight
simulator, a realistic racing game, etc, might want the joystick interface
instead of gamepads. */
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Color colors[64];
#define MOTION_EVENT_COOLDOWN 40
typedef struct EventMessage
{
char *str;
SDL_Color color;
Uint64 start_ticks;
struct EventMessage *next;
} EventMessage;
static EventMessage messages;
static EventMessage *messages_tail = &messages;
static const char *battery_state_string(SDL_PowerState state)
{
switch (state) {
case SDL_POWERSTATE_ERROR: return "ERROR";
case SDL_POWERSTATE_UNKNOWN: return "UNKNOWN";
case SDL_POWERSTATE_ON_BATTERY: return "ON BATTERY";
case SDL_POWERSTATE_NO_BATTERY: return "NO BATTERY";
case SDL_POWERSTATE_CHARGING: return "CHARGING";
case SDL_POWERSTATE_CHARGED: return "CHARGED";
default: break;
}
return "UNKNOWN";
}
static void add_message(SDL_JoystickID jid, const char *fmt, ...)
{
const SDL_Color *color = &colors[((size_t) jid) % SDL_arraysize(colors)];
EventMessage *msg = NULL;
char *str = NULL;
va_list ap;
msg = (EventMessage *) SDL_calloc(1, sizeof (*msg));
if (!msg) {
return; // oh well.
}
va_start(ap, fmt);
SDL_vasprintf(&str, fmt, ap);
va_end(ap);
if (!str) {
SDL_free(msg);
return; // oh well.
}
msg->str = str;
SDL_copyp(&msg->color, color);
msg->start_ticks = SDL_GetTicks();
msg->next = NULL;
messages_tail->next = msg;
messages_tail = msg;
}
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
int i;
SDL_SetAppMetadata("Example Input Gamepad Events", "1.0", "com.example.input-gamepad-events");
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/input/gamepad-events", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
colors[0].r = colors[0].g = colors[0].b = colors[0].a = 255;
for (i = 1; i < SDL_arraysize(colors); i++) {
colors[i].r = SDL_rand(255);
colors[i].g = SDL_rand(255);
colors[i].b = SDL_rand(255);
colors[i].a = 255;
}
add_message(0, "Please plug in a gamepad.");
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
} else if (event->type == SDL_EVENT_GAMEPAD_ADDED) {
/* this event is sent for each hotplugged stick, but also each already-connected gamepad during SDL_Init(). */
const SDL_JoystickID which = event->gdevice.which;
SDL_Gamepad *gamepad = SDL_OpenGamepad(which);
if (!gamepad) {
add_message(which, "Gamepad #%u add, but not opened: %s", (unsigned int) which, SDL_GetError());
} else {
char *mapping = SDL_GetGamepadMapping(gamepad);
add_message(which, "Gamepad #%u ('%s') added", (unsigned int) which, SDL_GetGamepadName(gamepad));
if (mapping) {
add_message(which, "Gamepad #%u mapping: %s", (unsigned int) which, mapping);
SDL_free(mapping);
}
}
} else if (event->type == SDL_EVENT_GAMEPAD_REMOVED) {
const SDL_JoystickID which = event->gdevice.which;
SDL_Gamepad *gamepad = SDL_GetGamepadFromID(which);
if (gamepad) {
SDL_CloseGamepad(gamepad); /* the gamepad was unplugged. */
}
add_message(which, "Gamepad #%u removed", (unsigned int) which);
} else if (event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
static Uint64 axis_motion_cooldown_time = 0; /* these are spammy, only show every X milliseconds. */
const Uint64 now = SDL_GetTicks();
if (now >= axis_motion_cooldown_time) {
const SDL_JoystickID which = event->gaxis.which;
axis_motion_cooldown_time = now + MOTION_EVENT_COOLDOWN;
add_message(which, "Gamepad #%u axis %s -> %d", (unsigned int) which, SDL_GetGamepadStringForAxis((SDL_GamepadAxis) event->gaxis.axis), (int) event->gaxis.value);
}
} else if ((event->type == SDL_EVENT_GAMEPAD_BUTTON_UP) || (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN)) {
const SDL_JoystickID which = event->gbutton.which;
add_message(which, "Gamepad #%u button %s -> %s", (unsigned int) which, SDL_GetGamepadStringForButton((SDL_GamepadButton) event->gbutton.button), event->gbutton.down ? "PRESSED" : "RELEASED");
} else if (event->type == SDL_EVENT_JOYSTICK_BATTERY_UPDATED) {
const SDL_JoystickID which = event->jbattery.which;
if (SDL_IsGamepad(which)) { /* this is only reported for joysticks, so make sure this joystick is _actually_ a gamepad. */
add_message(which, "Gamepad #%u battery -> %s - %d%%", (unsigned int) which, battery_state_string(event->jbattery.state), event->jbattery.percent);
}
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const Uint64 now = SDL_GetTicks();
const float msg_lifetime = 3500.0f; /* milliseconds a message lives for. */
EventMessage *msg = messages.next;
float prev_y = 0.0f;
int winw = 640, winh = 480;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_GetWindowSize(window, &winw, &winh);
while (msg) {
float x, y;
const float life_percent = ((float) (now - msg->start_ticks)) / msg_lifetime;
if (life_percent >= 1.0f) { /* msg is done. */
messages.next = msg->next;
if (messages_tail == msg) {
messages_tail = &messages;
}
SDL_free(msg->str);
SDL_free(msg);
msg = messages.next;
continue;
}
x = (((float) winw) - (SDL_strlen(msg->str) * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE)) / 2.0f;
y = ((float) winh) * life_percent;
if ((prev_y != 0.0f) && ((prev_y - y) < ((float) SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE))) {
msg->start_ticks = now;
break; // wait for the previous message to tick up a little.
}
SDL_SetRenderDrawColor(renderer, msg->color.r, msg->color.g, msg->color.b, (Uint8) (((float) msg->color.a) * (1.0f - life_percent)));
SDL_RenderDebugText(renderer, x, y, msg->str);
prev_y = y;
msg = msg->next;
}
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_Quit();
/* SDL will clean up the window/renderer for us. We let the gamepads leak. */
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -0,0 +1,4 @@
This example code reports power status (plugged in, battery level, etc).
Note that only Chrome-based browsers support this API currently. Firefox and
Safari will report this as unknown, but this may change later!
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+155
View File
@@ -0,0 +1,155 @@
/*
* This example code reports power status (plugged in, battery level, etc).
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example Misc Power", "1.0", "com.example.misc-power");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/misc/power", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const SDL_FRect frame = { 100, 200, 440, 80 }; /* the percentage bar dimensions. */
/* Query for battery info */
int seconds = 0, percent = 0;
const SDL_PowerState state = SDL_GetPowerInfo(&seconds, &percent);
/* We set up different drawing details for each power state, then
run it all through the same drawing code. */
int clearr = 0, clearg = 0, clearb = 0; /* clear window to this color. */
int textr = 255, textg = 255, textb = 255; /* draw messages in this color. */
int framer = 255, frameg = 255, frameb = 255; /* draw a percentage bar frame in this color. */
int barr = 0, barg = 0, barb = 0; /* draw a percentage bar in this color. */
const char *msg = NULL;
const char *msg2 = NULL;
switch (state) {
case SDL_POWERSTATE_ERROR:
msg2 = "ERROR GETTING POWER STATE";
msg = SDL_GetError();
clearr = 255; /* red background */
break;
default: /* in case this does something unexpected later, treat it as unknown. */
case SDL_POWERSTATE_UNKNOWN:
msg = "Power state is unknown.";
clearr = clearb = clearg = 50; /* grey background */
break;
case SDL_POWERSTATE_ON_BATTERY:
msg = "Running on battery.";
barr = 255; /* draw in red */
break;
case SDL_POWERSTATE_NO_BATTERY:
msg = "Plugged in, no battery available.";
clearg = 50; /* green background */
break;
case SDL_POWERSTATE_CHARGING:
msg = "Charging.";
barb = barg = 255; /* draw in cyan */
break;
case SDL_POWERSTATE_CHARGED:
msg = "Charged.";
barg = 255; /* draw in green */
break;
}
SDL_SetRenderDrawColor(renderer, clearr, clearg, clearb, 255);
SDL_RenderClear(renderer);
if (percent >= 0) {
float x, y;
SDL_FRect pctrect;
char remainstr[64];
char msgbuf[128];
SDL_copyp(&pctrect, &frame);
pctrect.w *= percent / 100.0f;
if (seconds < 0) {
SDL_strlcpy(remainstr, "unknown time", sizeof (remainstr));
} else {
int hours, minutes;
hours = seconds / (60 * 60);
seconds -= hours * (60 * 60);
minutes = seconds / 60;
seconds -= minutes * 60;
SDL_snprintf(remainstr, sizeof (remainstr), "%02d:%02d:%02d", hours, minutes, seconds);
}
SDL_snprintf(msgbuf, sizeof (msgbuf), "Battery: %3d percent, %s remaining", percent, remainstr);
x = frame.x + ((frame.w - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * SDL_strlen(msgbuf))) / 2.0f);
y = frame.y + frame.h + SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
SDL_SetRenderDrawColor(renderer, barr, barg, barb, 255); /* draw percent bar. */
SDL_RenderFillRect(renderer, &pctrect);
SDL_SetRenderDrawColor(renderer, framer, frameg, frameb, 255); /* draw frame on top of bar. */
SDL_RenderRect(renderer, &frame);
SDL_SetRenderDrawColor(renderer, textr, textg, textb, 255);
SDL_RenderDebugText(renderer, x, y, msgbuf); /* draw text about battery level */
}
if (msg) {
const float x = frame.x + ((frame.w - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * SDL_strlen(msg))) / 2.0f);
const float y = frame.y - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2);
SDL_SetRenderDrawColor(renderer, textr, textg, textb, 255);
SDL_RenderDebugText(renderer, x, y, msg);
}
if (msg2) {
const float x = frame.x + ((frame.w - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * SDL_strlen(msg2))) / 2.0f);
const float y = frame.y - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 4);
SDL_SetRenderDrawColor(renderer, textr, textg, textb, 255);
SDL_RenderDebugText(renderer, x, y, msg2);
}
/* put the new rendering on the screen. */
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
/* SDL will clean up the window/renderer for us. */
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

@@ -0,0 +1,6 @@
This example code lets the user copy and paste with the system clipboard.
This only handles text, but SDL supports other data types, too.
Note that only Chrome-based browsers support this API currently. This uses a
new Javascript API, so hopefully this will be available everywhere soon!
@@ -0,0 +1,235 @@
/*
* This example code lets the user copy and paste with the system clipboard.
*
* This only handles text, but SDL supports other data types, too.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static const char *copybuttonstr = "Click here to copy!";
static const char *pastebuttonstr = "Click here to paste!";
static SDL_FRect currenttimerect;
static SDL_FRect copybuttonrect;
static SDL_FRect pastetextrect;
static SDL_FRect pastebuttonrect;
static bool copy_pressed = false;
static bool paste_pressed = false;
static char current_time[64];
static char *pasted_str = NULL;
static void CalculateCurrentTimeString(void)
{
SDL_Time ticks = 0;
SDL_DateTime dt;
if (!SDL_GetCurrentTime(&ticks) || !SDL_TimeToDateTime(ticks, &dt, true)) {
SDL_snprintf(current_time, sizeof (current_time), "(Don't know the current time, sorry.)");
} else {
static const char *month[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
static const char *day[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
SDL_snprintf(current_time, sizeof (current_time), "%s, %s %d, %d %02d:%02d:%02d", day[dt.day_of_week], month[dt.month-1], dt.day, dt.year, dt.hour, dt.minute, dt.second);
}
}
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example Misc Clipboard", "1.0", "com.example.misc-clipboard");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/misc/clipboard", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
CalculateCurrentTimeString();
/* set up the locations where we'll draw stuff. */
currenttimerect.x = 30;
currenttimerect.y = 10;
currenttimerect.w = 390;
currenttimerect.h = SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 10;
copybuttonrect.x = currenttimerect.x + currenttimerect.w + 30;
copybuttonrect.y = currenttimerect.y;
copybuttonrect.w = (float) ((SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * SDL_strlen(copybuttonstr)) + 10);
copybuttonrect.h = currenttimerect.h;
pastetextrect.x = 10;
pastetextrect.y = currenttimerect.y + currenttimerect.h + 10;
pastetextrect.w = 620;
pastetextrect.h = ((480 - pastetextrect.y) - copybuttonrect.h) - 20;
pastebuttonrect.w = (float) ((SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * SDL_strlen(pastebuttonstr)) + 10);
pastebuttonrect.x = (640 - pastebuttonrect.w) / 2.0f;
pastebuttonrect.y = pastetextrect.y + pastetextrect.h + 10;
pastebuttonrect.h = copybuttonrect.h;
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
SDL_ConvertEventToRenderCoordinates(renderer, event);
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
} else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (event->button.button == SDL_BUTTON_LEFT) {
const SDL_FPoint p = { event->button.x, event->button.y };
copy_pressed = SDL_PointInRectFloat(&p, &copybuttonrect);
paste_pressed = SDL_PointInRectFloat(&p, &pastebuttonrect);
}
} else if (event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
if (event->button.button == SDL_BUTTON_LEFT) {
const SDL_FPoint p = { event->button.x, event->button.y };
if (copy_pressed && SDL_PointInRectFloat(&p, &copybuttonrect)) {
SDL_SetClipboardText(current_time);
} else if (paste_pressed && SDL_PointInRectFloat(&p, &pastebuttonrect)) {
SDL_free(pasted_str);
pasted_str = SDL_GetClipboardText();
}
copy_pressed = paste_pressed = false;
}
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
static void RenderPastedText(void)
{
char *str = pasted_str;
if (str) {
float x = pastetextrect.x + 5;
float y = pastetextrect.y + 5;
const float w = pastetextrect.w - 10;
const float h = pastetextrect.h;
const size_t max_chars_per_line = (size_t) (w / SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE);
char *newline;
size_t slen;
char ch;
/* this doesn't wordwrap, or deal with Unicode....this is just a simple example app! */
while ((newline = SDL_strchr(str, '\n')) != NULL) {
const bool ignore_cr = ((newline > str) && (newline[-1] == '\r'));
if (ignore_cr) {
newline[-1] = '\0';
}
*newline = '\0';
slen = SDL_strlen(str); /* length to end of line. */
slen = SDL_min(slen, max_chars_per_line);
ch = str[slen];
str[slen] = '\0';
SDL_RenderDebugText(renderer, x, y, str);
str[slen] = ch;
if (ignore_cr) {
newline[-1] = '\r';
}
*newline = '\n';
str = newline + 1;
y += (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2);
if ((h - y) < SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) {
break; // no space for another line, stop here.
}
}
/* last text after newline, if there's room. */
if ((h - y) >= SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) {
slen = SDL_strlen(str); /* length to end of line. */
slen = SDL_min(slen, max_chars_per_line);
ch = str[slen];
str[slen] = '\0';
SDL_RenderDebugText(renderer, x, y, str);
str[slen] = ch;
}
}
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
float x, y;
CalculateCurrentTimeString();
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black */
SDL_RenderClear(renderer);
/* draw a frame around the current time. */
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderFillRect(renderer, &currenttimerect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderRect(renderer, &currenttimerect);
/* draw the current time inside the frame. */
x = currenttimerect.x + ((currenttimerect.w - (SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * SDL_strlen(current_time))) / 2.0f);
y = currenttimerect.y + 5;
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
SDL_RenderDebugText(renderer, x, y, current_time);
/* draw a frame for the "copy the current time to the clipboard" button. */
if (copy_pressed) {
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
} else {
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
}
SDL_RenderFillRect(renderer, &copybuttonrect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderRect(renderer, &copybuttonrect);
/* draw the "copy this text" button string. */
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDebugText(renderer, copybuttonrect.x + 5, copybuttonrect.y + 5, copybuttonstr);
/* draw a frame for the pasted text area. */
SDL_SetRenderDrawColor(renderer, 0, 53, 25, 255);
SDL_RenderFillRect(renderer, &pastetextrect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderRect(renderer, &pastetextrect);
/* draw pasted text. */
SDL_SetRenderDrawColor(renderer, 0, 219, 107, 255);
RenderPastedText();
/* draw a frame for the "paste from the clipboard" button. */
if (paste_pressed) {
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
} else {
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
}
SDL_RenderFillRect(renderer, &pastebuttonrect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderRect(renderer, &pastebuttonrect);
/* draw the "paste some text" button string. */
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDebugText(renderer, pastebuttonrect.x + 5, pastebuttonrect.y + 5, pastebuttonstr);
/* put the new rendering on the screen. */
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_free(pasted_str);
/* SDL will clean up the window/renderer for us. */
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

+1
View File
@@ -0,0 +1 @@
Various examples from smaller subsystems
+2 -1
View File
@@ -24,10 +24,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/clear", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/clear", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
@@ -26,10 +26,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/primitives", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/primitives", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* set up some random points */
for (i = 0; i < SDL_arraysize(points); i++) {
+4 -2
View File
@@ -23,10 +23,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/lines", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/lines", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
@@ -76,8 +77,9 @@ SDL_AppResult SDL_AppIterate(void *appstate)
const float size = 30.0f;
const float x = 320.0f;
const float y = 95.0f - (size / 2.0f);
const float r = (float) i * (SDL_PI_F / 180.0f);
SDL_SetRenderDrawColor(renderer, SDL_rand(256), SDL_rand(256), SDL_rand(256), SDL_ALPHA_OPAQUE);
SDL_RenderLine(renderer, x, y, x + SDL_sinf((float) i) * size, y + SDL_cosf((float) i) * size);
SDL_RenderLine(renderer, x, y, x + SDL_cosf(r) * size, y + SDL_sinf(r) * size);
}
SDL_RenderPresent(renderer); /* put it all on the screen! */
@@ -43,10 +43,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/points", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/points", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* set up the data for a bunch of points. */
for (i = 0; i < SDL_arraysize(points); i++) {
@@ -26,10 +26,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/rectangles", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/rectangles", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
@@ -1,3 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a
.bmp file, and then draws it a few times each frame.
.png file, and then draws it a few times each frame.
@@ -23,7 +23,7 @@ static int texture_height = 0;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Textures", "1.0", "com.example.renderer-textures");
@@ -32,25 +32,26 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/textures", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
times) with data from a png file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
SDL_Log("Couldn't load png: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
SDL_free(png_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
@@ -29,10 +29,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/streaming-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/streaming-textures", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, TEXTURE_SIZE, TEXTURE_SIZE);
if (!texture) {
@@ -65,7 +66,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
/* To update a streaming texture, you need to lock it first. This gets you access to the pixels.
Note that this is considered a _write-only_ operation: the buffer you get from locking
might not acutally have the existing contents of the texture, and you have to write to every
might not actually have the existing contents of the texture, and you have to write to every
locked pixel! */
/* You can use SDL_LockTexture() to get an array of raw pixels, but we're going to use
@@ -1,3 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
This example creates an SDL window and renderer, loads a texture from a .png
file, and then draws it, rotating around the center of the screen.
@@ -23,7 +23,7 @@ static int texture_height = 0;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Rotating Textures", "1.0", "com.example.renderer-rotating-textures");
@@ -32,25 +32,26 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/rotating-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/rotating-textures", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
SDL_free(png_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
@@ -1,3 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
This example creates an SDL window and renderer, loads a texture from a .png
file, and then draws it, scaling it up and down.
@@ -23,7 +23,7 @@ static int texture_height = 0;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Scaling Textures", "1.0", "com.example.renderer-scaling-textures");
@@ -32,25 +32,26 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/scaling-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/scaling-textures", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
SDL_free(png_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
@@ -1,3 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
This example creates an SDL window and renderer, loads a texture from a .png
file, and then draws geometry (arbitrary polygons) using it.
@@ -23,7 +23,7 @@ static int texture_height = 0;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Geometry", "1.0", "com.example.renderer-geometry");
@@ -32,25 +32,26 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/geometry", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/geometry", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
SDL_free(png_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
@@ -1,3 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a
.bmp file, and then draws it a few times each frame, adjusting the colors.
.png file, and then draws it a few times each frame, adjusting the colors.
@@ -23,7 +23,7 @@ static int texture_height = 0;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Color Mods", "1.0", "com.example.renderer-color-mods");
@@ -32,25 +32,26 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/color-mods", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/color-mods", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
SDL_free(png_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
@@ -1,4 +1,4 @@
This example creates an SDL window and renderer, loads a texture
from a .bmp file, and then draws it a few times each frame, adjusting
from a .png file, and then draws it a few times each frame, adjusting
the viewport before each draw.
@@ -23,7 +23,7 @@ static int texture_height = 0;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Viewport", "1.0", "com.example.renderer-viewport");
@@ -32,25 +32,26 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/viewport", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/viewport", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
SDL_free(png_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
@@ -1,5 +1,5 @@
This example creates an SDL window and renderer, loads a texture
from a .bmp file, and stretches it across the window. Each frame, we move
from a .png file, and stretches it across the window. Each frame, we move
the clipping rectangle around, so only a small square of the texture is
actually drawn.
@@ -30,7 +30,7 @@ static Uint64 last_time = 0;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Clipping Rectangle", "1.0", "com.example.renderer-cliprect");
@@ -39,10 +39,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/cliprect", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/cliprect", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
cliprect_direction.x = cliprect_direction.y = 1.0f;
@@ -53,15 +54,15 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
SDL_free(png_path); /* done with this, the file is loaded. */
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
@@ -93,20 +94,20 @@ SDL_AppResult SDL_AppIterate(void *appstate)
/* Set a new clipping rectangle position */
cliprect_position.x += distance * cliprect_direction.x;
if (cliprect_position.x < 0.0f) {
cliprect_position.x = 0.0f;
if (cliprect_position.x < -CLIPRECT_SIZE) {
cliprect_position.x = -CLIPRECT_SIZE;
cliprect_direction.x = 1.0f;
} else if (cliprect_position.x >= (WINDOW_WIDTH - CLIPRECT_SIZE)) {
cliprect_position.x = (WINDOW_WIDTH - CLIPRECT_SIZE) - 1;
} else if (cliprect_position.x >= WINDOW_WIDTH) {
cliprect_position.x = WINDOW_WIDTH - 1;
cliprect_direction.x = -1.0f;
}
cliprect_position.y += distance * cliprect_direction.y;
if (cliprect_position.y < 0.0f) {
cliprect_position.y = 0.0f;
if (cliprect_position.y < -CLIPRECT_SIZE) {
cliprect_position.y = -CLIPRECT_SIZE;
cliprect_direction.y = 1.0f;
} else if (cliprect_position.y >= (WINDOW_HEIGHT - CLIPRECT_SIZE)) {
cliprect_position.y = (WINDOW_HEIGHT - CLIPRECT_SIZE) - 1;
} else if (cliprect_position.y >= WINDOW_HEIGHT) {
cliprect_position.y = WINDOW_HEIGHT - 1;
cliprect_direction.y = -1.0f;
}
SDL_SetRenderClipRect(renderer, &cliprect);
@@ -32,7 +32,7 @@ static int converted_texture_height = 0;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Read Pixels", "1.0", "com.example.renderer-read-pixels");
@@ -41,25 +41,26 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/read-pixels", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/read-pixels", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
SDL_free(png_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
@@ -26,10 +26,11 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/debug-text", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/renderer/debug-text", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, and uses
SDL_RenderTextureAffine to draw a 3D cube using only 2D rendering operations.
@@ -0,0 +1,146 @@
/* affine-textures.c ... */
/*
* This example creates an SDL window and renderer, and then draws a cube
* using affine-transformed textures every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *png_path = NULL;
SDL_SetAppMetadata("Example Renderer Affine Textures", "1.0", "com.example.renderer-affine-textures");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/affine-textures", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .png into a surface, move it to a texture from there. */
SDL_asprintf(&png_path, "%ssample.png", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadPNG(png_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(png_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const float x0 = 0.5f * WINDOW_WIDTH;
const float y0 = 0.5f * WINDOW_HEIGHT;
const float px = SDL_min(WINDOW_WIDTH, WINDOW_HEIGHT) / SDL_sqrtf(3.0f);
const Uint64 now = SDL_GetTicks();
const float rad = (((float) ((int) (now % 2000))) / 2000.0f) * SDL_PI_F * 2;
const float cos = SDL_cosf(rad);
const float sin = SDL_sinf(rad);
const float k[3] = { 3.0f / SDL_sqrtf(50.0f), 4.0f / SDL_sqrtf(50.0f), 5.0f / SDL_sqrtf(50.0f)};
float mat[9] = {
cos + (1.0f-cos)*k[0]*k[0], -sin*k[2] + (1.0f-cos)*k[0]*k[1], sin*k[1] + (1.0f-cos)*k[0]*k[2],
sin*k[2] + (1.0f-cos)*k[0]*k[1], cos + (1.0f-cos)*k[1]*k[1], -sin*k[0] + (1.0f-cos)*k[1]*k[2],
-sin*k[1] + (1.0f-cos)*k[0]*k[2], sin*k[0] + (1.0f-cos)*k[1]*k[2], cos + (1.0f-cos)*k[2]*k[2],
};
float corners[16];
int i;
for (i = 0; i < 8; i++) {
const float x = (i & 1) ? -0.5f : 0.5f;
const float y = (i & 2) ? -0.5f : 0.5f;
const float z = (i & 4) ? -0.5f : 0.5f;
corners[0 + 2*i] = mat[0]*x + mat[1]*y + mat[2]*z;
corners[1 + 2*i] = mat[3]*x + mat[4]*y + mat[5]*z;
}
SDL_SetRenderDrawColor(renderer, 0x42, 0x87, 0xf5, SDL_ALPHA_OPAQUE); // light blue background.
SDL_RenderClear(renderer);
for (i = 1; i < 7; i++) {
const int dir = 3 & ((i & 4) ? ~i : i);
const int odd = (i & 1) ^ ((i & 2) >> 1) ^ ((i & 4) >> 2);
if (0 < (odd ? 1.0f : -1.0f) * mat[5 + dir]) continue;
int origin_index = (1 << ((dir - 1) % 3));
int right_index = (1 << ((dir + odd) % 3)) | origin_index;
int down_index = (1 << ((dir + (odd^1)) % 3)) | origin_index;
if (!odd) {
origin_index ^= 7;
right_index ^= 7;
down_index ^= 7;
}
SDL_FPoint origin, right, down;
origin.x = x0 + px*corners[0 + 2*origin_index];
origin.y = y0 + px*corners[1 + 2*origin_index];
right.x = x0 + px*corners[0 + 2*right_index];
right.y = y0 + px*corners[1 + 2*right_index];
down.x = x0 + px*corners[0 + 2*down_index];
down.y = y0 + px*corners[1 + 2*down_index];
SDL_RenderTextureAffine(renderer, texture, NULL, &origin, &right, &down);
}
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE;
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

@@ -0,0 +1,49 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
This is for generating thumbnails and videos of examples. Just include it
temporarily and let it override SDL_RenderPresent, etc, and it'll dump each
frame rendered to a new .png file.
*/
static bool SAVERENDERING_SDL_RenderPresent(SDL_Renderer *renderer)
{
static unsigned int framenum = 0;
SDL_Surface *surface = SDL_RenderReadPixels(renderer, NULL);
if (!surface) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to read pixels for frame #%u! (%s)", framenum, SDL_GetError());
} else {
char fname[64];
SDL_snprintf(fname, sizeof (fname), "frame%05u.png", framenum);
if (!SDL_SavePNG(surface, fname)) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to save png for frame #%u! (%s)", framenum, SDL_GetError());
}
SDL_DestroySurface(surface);
}
framenum++;
return SDL_RenderPresent(renderer);
}
#define SDL_RenderPresent SAVERENDERING_SDL_RenderPresent
+4 -2
View File
@@ -6,6 +6,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>@project_name@ Examples: @category_description@</title>
<link rel="icon" href="/@project_name@/thumbnail.png" type="image/png" />
@preload_images_html@
<link
rel="stylesheet"
type="text/css"
@@ -21,7 +24,6 @@
<meta property="og:title" content="@project_name@ Examples: @category_description@">
<meta property="og:description" content="@project_name@ Examples: @category_description@">
<meta property="og:image" content="@preview_image@" />
</head>
<body>
<header>
@@ -31,7 +33,7 @@
<nav class="breadcrumb">
<ul>
<li><a href="/@project_name@/">@project_name@</a></li>
<li><a href="/@project_name@/@category_name@">@category_name@</a></li>
<li><a href="/@project_name@/@category_name@/">@category_name@</a></li>
</ul>
</nav>
<h1>@project_name@ examples: @category_description@</h1>
+4 -1
View File
@@ -6,6 +6,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>@project_name@ Examples</title>
<link rel="icon" href="/@project_name@/thumbnail.png" type="image/png" />
@preload_images_html@
<link
rel="stylesheet"
type="text/css"
@@ -30,7 +33,7 @@
<main>
<nav class="breadcrumb">
<ul>
<li><a href="/@project_name@">@project_name@</a></li>
<li><a href="/@project_name@/">@project_name@</a></li>
</ul>
</nav>
<h1>@project_name@ examples</h1>
+3 -1
View File
@@ -23,10 +23,12 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/CATEGORY/NAME", 640, 480, 0, &window, &renderer)) {
if (!SDL_CreateWindowAndRenderer("examples/CATEGORY/NAME", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
+7 -7
View File
@@ -9,7 +9,7 @@
<meta property="og:type" content="website">
<meta property="og:title" content="@project_name@ Example: @category_name@/@example_name@">
<meta property="og:description" content="@description@">
<meta property="og:description" content="@short_description@">
<meta property="og:image" content="@preview_image@" />
<link rel="stylesheet" type="text/css" href="/@project_name@/examples.css" />
@@ -92,7 +92,7 @@
#output-container:hover,
#output-container:focus-within {
top: 50%;
top: 20%;
}
#output-container:focus-within {
@@ -151,7 +151,7 @@
#source-code:hover,
#source-code:focus-within {
top: 50%;
top: 20%;
}
#source-code:focus-within {
@@ -202,9 +202,9 @@
<div id="content">
<nav class="breadcrumb">
<ul>
<li><a href="/@project_name@">@project_name@</a></li>
<li><a href="/@project_name@/@category_name@">@category_name@</a></li>
<li><a href="/@project_name@/@category_name@/@example_name@">@example_name@</a></li>
<li><a href="/@project_name@/">@project_name@</a></li>
<li><a href="/@project_name@/@category_name@/">@category_name@</a></li>
<li><a href="/@project_name@/@category_name@/@example_name@/">@example_name@</a></li>
</ul>
</nav>
<hr/>
@@ -241,7 +241,7 @@
return function(text) {
var elem = document.getElementById('output-container');
if (elem.style['top'] == '') {
elem.style['top'] = '50%';
elem.style['top'] = '20%';
setTimeout(function() { elem.style['top'] = ''; }, 3000);
}