Initial Commit
359
thirdparty/SDL3-3.4.0/examples/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,359 @@
|
||||
#
|
||||
# CMake script for building the SDL examples
|
||||
#
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(CheckStructHasMember)
|
||||
include(CMakePushCheckState)
|
||||
include(sdlcompilers)
|
||||
|
||||
if(SDL_EXAMPLES_LINK_SHARED)
|
||||
set(sdl_name_component SDL3-shared)
|
||||
else()
|
||||
set(sdl_name_component SDL3-static)
|
||||
endif()
|
||||
set(HAVE_EXAMPLES_LINK_SHARED "${SDL_EXAMPLES_LINK_SHARED}" PARENT_SCOPE)
|
||||
|
||||
set(SDL_EXAMPLE_EXECUTABLES)
|
||||
|
||||
if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
||||
set(example_bin_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
||||
if(NOT IS_ABSOLUTE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
||||
set(example_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
||||
endif()
|
||||
else()
|
||||
set(example_bin_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.20)
|
||||
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
set(example_bin_dir "${example_bin_dir}$<$<BOOL:${is_multi_config}>:/$<CONFIG>>")
|
||||
endif()
|
||||
|
||||
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)
|
||||
foreach(resource_file IN LISTS RESOURCE_FILES)
|
||||
get_filename_component(res_file_name ${resource_file} NAME)
|
||||
list(APPEND RESOURCE_FILE_NAMES "${res_file_name}")
|
||||
set(resource_file_bindir "${example_bin_dir}/${res_file_name}")
|
||||
add_custom_command(OUTPUT "${resource_file_bindir}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${resource_file}" "${resource_file_bindir}"
|
||||
DEPENDS "${resource_file}"
|
||||
)
|
||||
list(APPEND RESOURCE_FILES_BINDIR "${resource_file_bindir}")
|
||||
endforeach()
|
||||
add_custom_target(copy-sdl-example-resources
|
||||
DEPENDS "${RESOURCE_FILES_BINDIR}"
|
||||
)
|
||||
|
||||
macro(add_sdl_example_executable TARGET)
|
||||
cmake_parse_arguments(AST "BUILD_DEPENDENT" "" "SOURCES;DATAFILES" ${ARGN})
|
||||
if(AST_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Unknown argument(s): ${AST_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
if(NOT AST_SOURCES)
|
||||
message(FATAL_ERROR "add_sdl_example_executable needs at least one source")
|
||||
endif()
|
||||
if(ANDROID)
|
||||
add_library(${TARGET} SHARED ${AST_SOURCES} ${AST_DATAFILES})
|
||||
else()
|
||||
add_executable(${TARGET} ${AST_SOURCES} ${AST_DATAFILES})
|
||||
endif()
|
||||
SDL_AddCommonCompilerFlags(${TARGET})
|
||||
target_link_libraries(${TARGET} PRIVATE SDL3::${sdl_name_component})
|
||||
|
||||
list(APPEND SDL_EXAMPLE_EXECUTABLES ${TARGET})
|
||||
if(AST_DATAFILES)
|
||||
if(PSP OR PS2)
|
||||
add_custom_command(TARGET ${TARGET} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E make_directory $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET}
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${AST_DATAFILES} $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
elseif(NOT APPLE AND NOT N3DS)
|
||||
add_dependencies(${TARGET} copy-sdl-example-resources)
|
||||
endif()
|
||||
if(EMSCRIPTEN)
|
||||
foreach(res IN LISTS AST_DATAFILES)
|
||||
get_filename_component(res_name "${res}" NAME)
|
||||
target_link_options(${TARGET} PRIVATE "SHELL:--embed-file ${res}@${res_name}")
|
||||
endforeach()
|
||||
endif()
|
||||
set_property(TARGET ${TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES "$<TARGET_FILE_DIR:${TARGET}>/$<JOIN:${AST_DATAFILES},$<SEMICOLON>$<TARGET_FILE_DIR:${TARGET}>/>")
|
||||
endif()
|
||||
|
||||
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(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()
|
||||
endmacro()
|
||||
|
||||
add_sdl_example_executable(renderer-clear SOURCES renderer/01-clear/clear.c)
|
||||
add_sdl_example_executable(renderer-primitives SOURCES renderer/02-primitives/primitives.c)
|
||||
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.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.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.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)
|
||||
add_sdl_example_executable(demo-bytepusher SOURCES demo/04-bytepusher/bytepusher.c)
|
||||
|
||||
# When you add an example, remember to add the Visual Studio project as well:
|
||||
# - 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 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...
|
||||
# - Test if they work
|
||||
# - Save the SDL.sln solution
|
||||
|
||||
if(PSP)
|
||||
# Build EBOOT files if building for PSP
|
||||
foreach(APP ${SDL_EXAMPLE_EXECUTABLES})
|
||||
create_pbp_file(
|
||||
TARGET ${APP}
|
||||
TITLE SDL-${APP}
|
||||
ICON_PATH NULL
|
||||
BACKGROUND_PATH NULL
|
||||
PREVIEW_PATH NULL
|
||||
OUTPUT_DIR $<TARGET_FILE_DIR:${APP}>/sdl-${APP}
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(RISCOS)
|
||||
set(SDL_EXAMPLE_EXECUTABLES_AIF)
|
||||
foreach(APP ${SDL_EXAMPLE_EXECUTABLES})
|
||||
set_property(TARGET ${APP} APPEND_STRING PROPERTY LINK_FLAGS " -static")
|
||||
add_custom_command(
|
||||
OUTPUT ${APP},ff8
|
||||
COMMAND elf2aif ${APP} ${APP},ff8
|
||||
DEPENDS ${APP}
|
||||
)
|
||||
add_custom_target(${APP}-aif ALL DEPENDS ${APP},ff8)
|
||||
list(APPEND SDL_EXAMPLE_EXECUTABLES_AIF ${CMAKE_CURRENT_BINARY_DIR}/${APP},ff8)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(SDL_INSTALL_EXAMPLES)
|
||||
if(RISCOS)
|
||||
install(
|
||||
FILES ${SDL_EXAMPLE_EXECUTABLES_AIF}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3
|
||||
)
|
||||
else()
|
||||
install(
|
||||
TARGETS ${SDL_EXAMPLE_EXECUTABLES}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3
|
||||
)
|
||||
endif()
|
||||
if(MSVC)
|
||||
foreach(example IN LISTS SDL_EXAMPLE_EXECUTABLES)
|
||||
SDL_install_pdb(${example} "${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3")
|
||||
endforeach()
|
||||
endif()
|
||||
install(
|
||||
FILES ${RESOURCE_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ANDROID AND TARGET SDL3::Jar)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake/android")
|
||||
find_package(SdlAndroid MODULE)
|
||||
if(SdlAndroid_FOUND)
|
||||
set(apks "")
|
||||
set(packages "")
|
||||
|
||||
include(SdlAndroidFunctions)
|
||||
sdl_create_android_debug_keystore(SDL_example-debug-keystore)
|
||||
sdl_android_compile_resources(SDL_example-resources RESFOLDER ${CMAKE_CURRENT_SOURCE_DIR}/../test/android/res)
|
||||
add_custom_target(sdl-example-apks)
|
||||
foreach(EXAMPLE ${SDL_EXAMPLE_EXECUTABLES})
|
||||
set(ANDROID_MANIFEST_APP_NAME "${EXAMPLE}")
|
||||
set(ANDROID_MANIFEST_LABEL "${EXAMPLE}")
|
||||
set(ANDROID_MANIFEST_LIB_NAME "$<TARGET_FILE_BASE_NAME:${EXAMPLE}>")
|
||||
set(ANDROID_MANIFEST_PACKAGE "org.libsdl.sdl.example.${EXAMPLE}")
|
||||
set(generated_manifest_path "${CMAKE_CURRENT_BINARY_DIR}/android/${EXAMPLE}-src/AndroidManifest.xml")
|
||||
string(REPLACE "." "/" JAVA_PACKAGE_DIR "${ANDROID_MANIFEST_PACKAGE}")
|
||||
set(GENERATED_SRC_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/android/${EXAMPLE}-src")
|
||||
set(GENERATED_RES_FOLDER "${GENERATED_SRC_FOLDER}/res")
|
||||
set(JAVA_PACKAGE_DIR "${GENERATED_SRC_FOLDER}/${JAVA_PACKAGE_DIR}")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/SDLEntryTestActivity.java.cmake "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java" @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/SDLTestActivity.java.cmake "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/res/values/strings.xml.cmake android/res/values/strings-${EXAMPLE}.xml @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/res/xml/shortcuts.xml.cmake "${GENERATED_RES_FOLDER}/xml/shortcuts.xml" @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/AndroidManifest.xml.cmake "${generated_manifest_path}" @ONLY)
|
||||
file(GENERATE
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/android/${EXAMPLE}-$<CONFIG>/res/values/strings.xml"
|
||||
INPUT "${CMAKE_CURRENT_BINARY_DIR}/android/res/values/strings-${EXAMPLE}.xml"
|
||||
)
|
||||
|
||||
sdl_android_compile_resources(${EXAMPLE}-resources
|
||||
RESOURCES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/android/${EXAMPLE}-$<CONFIG>/res/values/strings.xml"
|
||||
"${GENERATED_RES_FOLDER}/xml/shortcuts.xml"
|
||||
)
|
||||
|
||||
sdl_android_link_resources(${EXAMPLE}-apk-linked
|
||||
MANIFEST "${generated_manifest_path}"
|
||||
PACKAGE ${ANDROID_MANIFEST_PACKAGE}
|
||||
RES_TARGETS SDL_example-resources ${EXAMPLE}-resources
|
||||
TARGET_SDK_VERSION 31
|
||||
)
|
||||
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding;utf-8")
|
||||
set(classes_path "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${EXAMPLE}-java.dir/classes")
|
||||
# Some CMake versions have a slow `cmake -E make_directory` implementation
|
||||
if(NOT IS_DIRECTORY "${classes_path}")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${classes_path}")
|
||||
endif()
|
||||
set(OUT_JAR "${CMAKE_CURRENT_BINARY_DIR}/${EXAMPLE}.jar")
|
||||
add_custom_command(
|
||||
OUTPUT "${OUT_JAR}"
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf "${classes_path}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${classes_path}"
|
||||
COMMAND ${Java_JAVAC_EXECUTABLE}
|
||||
-source 1.8 -target 1.8
|
||||
-bootclasspath "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>"
|
||||
"${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java"
|
||||
"${JAVA_PACKAGE_DIR}/SDLTestActivity.java"
|
||||
$<TARGET_PROPERTY:${EXAMPLE}-apk-linked,JAVA_R>
|
||||
-cp "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>:${SDL_ANDROID_PLATFORM_ANDROID_JAR}"
|
||||
-d "${classes_path}"
|
||||
COMMAND ${Java_JAR_EXECUTABLE} cf "${OUT_JAR}" -C "${classes_path}" .
|
||||
DEPENDS $<TARGET_PROPERTY:${EXAMPLE}-apk-linked,OUTPUTS> "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>" "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java"
|
||||
)
|
||||
add_custom_target(${EXAMPLE}-jar DEPENDS "${OUT_JAR}")
|
||||
set_property(TARGET ${EXAMPLE}-jar PROPERTY OUTPUT "${OUT_JAR}")
|
||||
|
||||
set(dexworkdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${EXAMPLE}-dex.dir")
|
||||
# Some CMake versions have a slow `cmake -E make_directory` implementation
|
||||
if(NOT IS_DIRECTORY "${dexworkdir}")
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${dexworkdir}")
|
||||
endif()
|
||||
set(classes_dex_base_name "classes.dex")
|
||||
set(classes_dex "${dexworkdir}/${classes_dex_base_name}")
|
||||
add_custom_command(
|
||||
OUTPUT "${classes_dex}"
|
||||
COMMAND SdlAndroid::d8
|
||||
$<TARGET_PROPERTY:${EXAMPLE}-jar,OUTPUT>
|
||||
$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>
|
||||
--lib "${SDL_ANDROID_PLATFORM_ANDROID_JAR}"
|
||||
--output "${dexworkdir}"
|
||||
DEPENDS $<TARGET_PROPERTY:${EXAMPLE}-jar,OUTPUT> $<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>
|
||||
)
|
||||
add_custom_target(${EXAMPLE}-dex DEPENDS "${classes_dex}")
|
||||
set_property(TARGET ${EXAMPLE}-dex PROPERTY OUTPUT "${classes_dex}")
|
||||
set_property(TARGET ${EXAMPLE}-dex PROPERTY OUTPUT_BASE_NAME "${classes_dex_base_name}")
|
||||
|
||||
sdl_add_to_apk_unaligned(${EXAMPLE}-unaligned-apk
|
||||
APK_IN ${EXAMPLE}-apk-linked
|
||||
OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/intermediates"
|
||||
ASSETS ${RESOURCE_FILES}
|
||||
NATIVE_LIBS SDL3::SDL3-shared ${EXAMPLE}
|
||||
DEX ${EXAMPLE}-dex
|
||||
)
|
||||
|
||||
sdl_apk_align(${EXAMPLE}-aligned-apk ${EXAMPLE}-unaligned-apk
|
||||
OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/intermediates"
|
||||
)
|
||||
sdl_apk_sign(${EXAMPLE}-apk ${EXAMPLE}-aligned-apk
|
||||
KEYSTORE SDL_example-debug-keystore
|
||||
)
|
||||
add_dependencies(sdl-example-apks ${EXAMPLE}-apk)
|
||||
|
||||
if(TARGET SdlAndroid::adb)
|
||||
add_custom_target(install-${EXAMPLE}
|
||||
COMMAND "${CMAKE_COMMAND}" -DACTION=install "-DAPKS=$<TARGET_PROPERTY:${EXAMPLE}-apk,OUTPUT>" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake"
|
||||
DEPENDS "${EXAMPLE}-apk"
|
||||
)
|
||||
add_custom_target(start-${EXAMPLE}
|
||||
COMMAND "${ADB_BIN}" shell am start-activity -S "${ANDROID_MANIFEST_PACKAGE}/.SDLTestActivity"
|
||||
)
|
||||
add_custom_target(build-install-start-${EXAMPLE}
|
||||
COMMAND "${CMAKE_COMMAND}" -DACTION=build-install-run "-DEXECUTABLES=${EXAMPLE}" "-DBUILD_FOLDER=${CMAKE_BINARY_DIR}" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake"
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND packages "${ANDROID_MANIFEST_PACKAGE}")
|
||||
list(APPEND install_targets install-${EXAMPLE})
|
||||
endforeach()
|
||||
|
||||
if(TARGET SdlAndroid::adb)
|
||||
add_custom_target(install-sdl-example-apks
|
||||
DEPENDS ${install_targets}
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(uninstall-sdl-example-apks
|
||||
COMMAND "${CMAKE_COMMAND}" "-DADB=$<TARGET_FILE:SdlAndroid::adb>" -DACTION=uninstall "-DPACKAGES=${packages}" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
94
thirdparty/SDL3-3.4.0/examples/README.md
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
# Examples
|
||||
|
||||
## What is this?
|
||||
|
||||
In here are a collection of standalone SDL application examples. Unless
|
||||
otherwise stated, they should work on all supported platforms out of the box.
|
||||
If they don't [please file a bug to let us know](https://github.com/libsdl-org/SDL/issues/new).
|
||||
|
||||
|
||||
## What is this SDL_AppIterate thing?
|
||||
|
||||
SDL can optionally build apps as a collection of callbacks instead of the
|
||||
usual program structure that starts and ends in a function called `main`.
|
||||
The examples use this format for two reasons.
|
||||
|
||||
First, it allows the examples to work when built as web applications without
|
||||
a pile of ugly `#ifdef`s, and all of these examples are published on the web
|
||||
at [examples.libsdl.org](https://examples.libsdl.org/), so you can easily see
|
||||
them in action.
|
||||
|
||||
Second, it's example code! The callbacks let us cleanly break the program up
|
||||
into the four logical pieces most apps care about:
|
||||
|
||||
- Program startup
|
||||
- Event handling
|
||||
- What the program actually does in a single frame
|
||||
- Program shutdown
|
||||
|
||||
A detailed technical explanation of these callbacks is in
|
||||
docs/README-main-functions.md (or view that page on the web on
|
||||
[the wiki](https://wiki.libsdl.org/SDL3/README/main-functions#main-callbacks-in-sdl3)).
|
||||
|
||||
|
||||
## I would like to build and run these examples myself.
|
||||
|
||||
When you build SDL with CMake, you can add `-DSDL_EXAMPLES=On` to the
|
||||
CMake command line. When you build SDL, these examples will be built with it.
|
||||
|
||||
But most of these can just be built as a single .c file, as long as you point
|
||||
your compiler at SDL3's headers and link against SDL.
|
||||
|
||||
|
||||
## What is the license on the example code? Can I paste this into my project?
|
||||
|
||||
All code in the examples directory is considered public domain! You can do
|
||||
anything you like with it, including copy/paste it into your closed-source
|
||||
project, sell it, and pretend you wrote it yourself. We do not require you to
|
||||
give us credit for this code (but we always appreciate if you do!).
|
||||
|
||||
This is only true for the examples directory. The rest of SDL falls under the
|
||||
[zlib license](https://github.com/libsdl-org/SDL/blob/main/LICENSE.txt).
|
||||
|
||||
|
||||
## What is template.html and highlight-plugin.lua in this directory?
|
||||
|
||||
This is what [examples.libsdl.org](https://examples.libsdl.org/) uses when
|
||||
generating the web versions of these example programs. You can ignore this,
|
||||
unless you are improving it, in which case we definitely would love to hear
|
||||
from you!
|
||||
|
||||
|
||||
## What is template.c in this directory?
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
6
thirdparty/SDL3-3.4.0/examples/asyncio/01-load-bitmaps/README.txt
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
This example code loads a few bitmap files from disk using the asynchronous
|
||||
i/o, and then draws it to the window. It uses a task group to watch multiple
|
||||
reads and deal with them in whatever order they finish.
|
||||
|
||||
Note that for a single tiny file like this, you'd probably not want to bother
|
||||
with async i/o in real life, but this is just an example of how to do it.
|
||||
126
thirdparty/SDL3-3.4.0/examples/asyncio/01-load-bitmaps/load-bitmaps.c
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* This example code loads a bitmap with asynchronous i/o and renders it.
|
||||
*
|
||||
* 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_AsyncIOQueue *queue = NULL;
|
||||
|
||||
#define TOTAL_TEXTURES 4
|
||||
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 },
|
||||
{ 20, 200, 96, 60 },
|
||||
{ 525, 180, 96, 96 },
|
||||
{ 288, 375, 64, 64 }
|
||||
};
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create async i/o queue!", SDL_GetError(), NULL);
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* 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(), 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 *) pngs[i]); /* attach the filename as app-specific data, so we can see it later. */
|
||||
SDL_free(path);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SDL_AsyncIOOutcome outcome;
|
||||
int i;
|
||||
|
||||
if (SDL_GetAsyncIOResult(queue, &outcome)) { /* a .png file load has finished? */
|
||||
if (outcome.result == SDL_ASYNCIO_COMPLETE) {
|
||||
/* 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 == pngs[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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]) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create texture!", SDL_GetError(), NULL);
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
SDL_DestroySurface(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_free(outcome.buffer);
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
for (i = 0; i < SDL_arraysize(textures); i++) {
|
||||
SDL_RenderTexture(renderer, textures[i], NULL, &texture_rects[i]);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_DestroyAsyncIOQueue(queue);
|
||||
|
||||
for (i = 0; i < SDL_arraysize(textures); i++) {
|
||||
SDL_DestroyTexture(textures[i]);
|
||||
}
|
||||
|
||||
/* SDL will clean up the window/renderer for us. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/asyncio/01-load-bitmaps/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 74 KiB |
1
thirdparty/SDL3-3.4.0/examples/asyncio/description.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Asynchronous I/O
|
||||
5
thirdparty/SDL3-3.4.0/examples/audio/01-simple-playback/README.txt
vendored
Normal file
@@ -0,0 +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 creates a simple audio stream for playing sound, and
|
||||
generates a sine wave sound effect for it to play as time goes on. This is the
|
||||
simplest way to get up and running with procedural sound.
|
||||
104
thirdparty/SDL3-3.4.0/examples/audio/01-simple-playback/simple-playback.c
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This example code creates a simple audio stream for playing sound, and
|
||||
* generates a sine wave sound effect for it to play as time goes on. This
|
||||
* is the simplest way to get up and running with procedural sound.
|
||||
*
|
||||
* 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;
|
||||
static int current_sine_sample = 0;
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
SDL_AudioSpec spec;
|
||||
|
||||
SDL_SetAppMetadata("Example Audio Simple Playback", "1.0", "com.example.audio-simple-playback");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* 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, 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.
|
||||
The stream will convert it to whatever the hardware wants on the other side. */
|
||||
spec.channels = 1;
|
||||
spec.format = SDL_AUDIO_F32;
|
||||
spec.freq = 8000;
|
||||
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL);
|
||||
if (!stream) {
|
||||
SDL_Log("Couldn't create audio stream: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* SDL_OpenAudioDeviceStream starts the device paused. You have to tell it to start! */
|
||||
SDL_ResumeAudioStreamDevice(stream);
|
||||
|
||||
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)
|
||||
{
|
||||
/* see if we need to feed the audio stream more data yet.
|
||||
We're being lazy here, but if there's less than half a second queued, generate more.
|
||||
A sine wave is unchanging audio--easy to stream--but for video games, you'll want
|
||||
to generate significantly _less_ audio ahead of time! */
|
||||
const int minimum_audio = (8000 * sizeof (float)) / 2; /* 8000 float samples per second. Half of that. */
|
||||
if (SDL_GetAudioStreamQueued(stream) < minimum_audio) {
|
||||
static float samples[512]; /* this will feed 512 samples each frame until we get to our maximum. */
|
||||
int i;
|
||||
|
||||
/* generate a 440Hz pure tone */
|
||||
for (i = 0; i < SDL_arraysize(samples); i++) {
|
||||
const int freq = 440;
|
||||
const float phase = current_sine_sample * freq / 8000.0f;
|
||||
samples[i] = SDL_sinf(phase * 2 * SDL_PI_F);
|
||||
current_sine_sample++;
|
||||
}
|
||||
|
||||
/* wrapping around to avoid floating-point errors */
|
||||
current_sine_sample %= 8000;
|
||||
|
||||
/* feed the new data to the stream. It will queue at the end, and trickle out as the hardware needs more data. */
|
||||
SDL_PutAudioStreamData(stream, samples, sizeof (samples));
|
||||
}
|
||||
|
||||
/* we're not doing anything with the renderer, so just blank it out. */
|
||||
SDL_RenderClear(renderer);
|
||||
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. */
|
||||
}
|
||||
|
||||
5
thirdparty/SDL3-3.4.0/examples/audio/02-simple-playback-callback/README.txt
vendored
Normal file
@@ -0,0 +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 creates a simple audio stream for playing sound, and
|
||||
generates a sine wave sound effect for it to play as time goes on. Unlike
|
||||
the previous example, this uses a callback to generate sound.
|
||||
116
thirdparty/SDL3-3.4.0/examples/audio/02-simple-playback-callback/simple-playback-callback.c
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This example code creates a simple audio stream for playing sound, and
|
||||
* generates a sine wave sound effect for it to play as time goes on. Unlike
|
||||
* the previous example, this uses a callback to generate sound.
|
||||
*
|
||||
* This might be the path of least resistance if you're moving an SDL2
|
||||
* program's audio code to SDL3.
|
||||
*
|
||||
* 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;
|
||||
static int current_sine_sample = 0;
|
||||
|
||||
/* this function will be called (usually in a background thread) when the audio stream is consuming data. */
|
||||
static void SDLCALL FeedTheAudioStreamMore(void *userdata, SDL_AudioStream *astream, int additional_amount, int total_amount)
|
||||
{
|
||||
/* total_amount is how much data the audio stream is eating right now, additional_amount is how much more it needs
|
||||
than what it currently has queued (which might be zero!). You can supply any amount of data here; it will take what
|
||||
it needs and use the extra later. If you don't give it enough, it will take everything and then feed silence to the
|
||||
hardware for the rest. Ideally, though, we always give it what it needs and no extra, so we aren't buffering more
|
||||
than necessary. */
|
||||
additional_amount /= sizeof (float); /* convert from bytes to samples */
|
||||
while (additional_amount > 0) {
|
||||
float samples[128]; /* this will feed 128 samples each iteration until we have enough. */
|
||||
const int total = SDL_min(additional_amount, SDL_arraysize(samples));
|
||||
int i;
|
||||
|
||||
/* generate a 440Hz pure tone */
|
||||
for (i = 0; i < total; i++) {
|
||||
const int freq = 440;
|
||||
const float phase = current_sine_sample * freq / 8000.0f;
|
||||
samples[i] = SDL_sinf(phase * 2 * SDL_PI_F);
|
||||
current_sine_sample++;
|
||||
}
|
||||
|
||||
/* wrapping around to avoid floating-point errors */
|
||||
current_sine_sample %= 8000;
|
||||
|
||||
/* feed the new data to the stream. It will queue at the end, and trickle out as the hardware needs more data. */
|
||||
SDL_PutAudioStreamData(astream, samples, total * sizeof (float));
|
||||
additional_amount -= total; /* subtract what we've just fed the stream. */
|
||||
}
|
||||
}
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
SDL_AudioSpec spec;
|
||||
|
||||
SDL_SetAppMetadata("Example Simple Audio Playback Callback", "1.0", "com.example.audio-simple-playback-callback");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* 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, 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.
|
||||
The stream will convert it to whatever the hardware wants on the other side. */
|
||||
spec.channels = 1;
|
||||
spec.format = SDL_AUDIO_F32;
|
||||
spec.freq = 8000;
|
||||
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, FeedTheAudioStreamMore, NULL);
|
||||
if (!stream) {
|
||||
SDL_Log("Couldn't create audio stream: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* SDL_OpenAudioDeviceStream starts the device paused. You have to tell it to start! */
|
||||
SDL_ResumeAudioStreamDevice(stream);
|
||||
|
||||
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)
|
||||
{
|
||||
/* we're not doing anything with the renderer, so just blank it out. */
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
/* all the work of feeding the audio stream is happening in a callback in a background thread. */
|
||||
|
||||
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. */
|
||||
}
|
||||
|
||||
5
thirdparty/SDL3-3.4.0/examples/audio/03-load-wav/README.txt
vendored
Normal file
@@ -0,0 +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 creates a simple audio stream for playing sound, and
|
||||
loads a .wav file that is pushed through the stream in a loop.
|
||||
|
||||
104
thirdparty/SDL3-3.4.0/examples/audio/03-load-wav/load-wav.c
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This example code creates a simple audio stream for playing sound, and
|
||||
* loads a .wav file that is pushed through the stream in a loop.
|
||||
*
|
||||
* This code is public domain. Feel free to use it for any purpose!
|
||||
*
|
||||
* The .wav file is a sample from Will Provost's song, The Living Proof,
|
||||
* used with permission.
|
||||
*
|
||||
* From the album The Living Proof
|
||||
* Publisher: 5 Guys Named Will
|
||||
* Copyright 1996 Will Provost
|
||||
* https://itunes.apple.com/us/album/the-living-proof/id4153978
|
||||
* http://www.amazon.com/The-Living-Proof-Will-Provost/dp/B00004R8RH
|
||||
*/
|
||||
|
||||
#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;
|
||||
static Uint8 *wav_data = NULL;
|
||||
static Uint32 wav_data_len = 0;
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
SDL_AudioSpec spec;
|
||||
char *wav_path = NULL;
|
||||
|
||||
SDL_SetAppMetadata("Example Audio Load Wave", "1.0", "com.example.audio-load-wav");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* 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, 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 */
|
||||
if (!SDL_LoadWAV(wav_path, &spec, &wav_data, &wav_data_len)) {
|
||||
SDL_Log("Couldn't load .wav file: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
SDL_free(wav_path); /* done with this string. */
|
||||
|
||||
/* Create our audio stream in the same format as the .wav file. It'll convert to what the audio hardware wants. */
|
||||
stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL);
|
||||
if (!stream) {
|
||||
SDL_Log("Couldn't create audio stream: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* SDL_OpenAudioDeviceStream starts the device paused. You have to tell it to start! */
|
||||
SDL_ResumeAudioStreamDevice(stream);
|
||||
|
||||
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)
|
||||
{
|
||||
/* see if we need to feed the audio stream more data yet.
|
||||
We're being lazy here, but if there's less than the entire wav file left to play,
|
||||
just shove a whole copy of it into the queue, so we always have _tons_ of
|
||||
data queued for playback. */
|
||||
if (SDL_GetAudioStreamQueued(stream) < (int)wav_data_len) {
|
||||
/* feed more data to the stream. It will queue at the end, and trickle out as the hardware needs more data. */
|
||||
SDL_PutAudioStreamData(stream, wav_data, wav_data_len);
|
||||
}
|
||||
|
||||
/* we're not doing anything with the renderer, so just blank it out. */
|
||||
SDL_RenderClear(renderer);
|
||||
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(wav_data); /* strictly speaking, this isn't necessary because the process is ending, but it's good policy. */
|
||||
/* SDL will clean up the window/renderer for us. */
|
||||
}
|
||||
|
||||
5
thirdparty/SDL3-3.4.0/examples/audio/04-multiple-streams/README.txt
vendored
Normal file
@@ -0,0 +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 in audio streams and binds
|
||||
them for playback, repeating both sounds on loop. This shows several streams
|
||||
mixing into a single playback device.
|
||||
136
thirdparty/SDL3-3.4.0/examples/audio/04-multiple-streams/multiple-streams.c
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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_AudioDeviceID audio_device = 0;
|
||||
|
||||
/* things that are playing sound (the audiostream itself, plus the original data, so we can refill to loop. */
|
||||
typedef struct Sound {
|
||||
Uint8 *wav_data;
|
||||
Uint32 wav_data_len;
|
||||
SDL_AudioStream *stream;
|
||||
} Sound;
|
||||
|
||||
static Sound sounds[2];
|
||||
|
||||
static bool init_sound(const char *fname, Sound *sound)
|
||||
{
|
||||
bool retval = false;
|
||||
SDL_AudioSpec spec;
|
||||
char *wav_path = NULL;
|
||||
|
||||
/* Load the .wav files from wherever the app is being run from. */
|
||||
SDL_asprintf(&wav_path, "%s%s", SDL_GetBasePath(), fname); /* allocate a string of the full file path */
|
||||
if (!SDL_LoadWAV(wav_path, &spec, &sound->wav_data, &sound->wav_data_len)) {
|
||||
SDL_Log("Couldn't load .wav file: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create an audio stream. Set the source format to the wav's format (what
|
||||
we'll input), leave the dest format NULL here (it'll change to what the
|
||||
device wants once we bind it). */
|
||||
sound->stream = SDL_CreateAudioStream(&spec, NULL);
|
||||
if (!sound->stream) {
|
||||
SDL_Log("Couldn't create audio stream: %s", SDL_GetError());
|
||||
} else if (!SDL_BindAudioStream(audio_device, sound->stream)) { /* once bound, it'll start playing when there is data available! */
|
||||
SDL_Log("Failed to bind '%s' stream to device: %s", fname, SDL_GetError());
|
||||
} else {
|
||||
retval = true; /* success! */
|
||||
}
|
||||
|
||||
SDL_free(wav_path); /* done with this string. */
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
|
||||
SDL_SetAppMetadata("Example Audio Multiple Streams", "1.0", "com.example.audio-multiple-streams");
|
||||
|
||||
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/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);
|
||||
if (audio_device == 0) {
|
||||
SDL_Log("Couldn't open audio device: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (!init_sound("sample.wav", &sounds[0])) {
|
||||
return SDL_APP_FAILURE;
|
||||
} else if (!init_sound("sword.wav", &sounds[1])) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SDL_arraysize(sounds); i++) {
|
||||
/* If less than a full copy of the audio is queued for playback, put another copy in there.
|
||||
This is overkill, but easy when lots of RAM is cheap. One could be more careful and
|
||||
queue less at a time, as long as the stream doesn't run dry. */
|
||||
if (SDL_GetAudioStreamQueued(sounds[i].stream) < ((int) sounds[i].wav_data_len)) {
|
||||
SDL_PutAudioStreamData(sounds[i].stream, sounds[i].wav_data, (int) sounds[i].wav_data_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* just blank the screen. */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_CloseAudioDevice(audio_device);
|
||||
|
||||
for (i = 0; i < SDL_arraysize(sounds); i++) {
|
||||
if (sounds[i].stream) {
|
||||
SDL_DestroyAudioStream(sounds[i].stream);
|
||||
}
|
||||
SDL_free(sounds[i].wav_data);
|
||||
}
|
||||
|
||||
/* SDL will clean up the window/renderer for us. */
|
||||
}
|
||||
7
thirdparty/SDL3-3.4.0/examples/audio/05-planar-data/README.txt
vendored
Normal file
@@ -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.
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/audio/05-planar-data/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
368
thirdparty/SDL3-3.4.0/examples/audio/05-planar-data/planar-data.c
vendored
Normal file
@@ -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
|
||||
};
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/audio/05-planar-data/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/audio/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/audio/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
1
thirdparty/SDL3-3.4.0/examples/camera/01-read-and-draw/README.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
This reads from a webcam and draws frames of video to the screen.
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/camera/01-read-and-draw/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 339 KiB |
114
thirdparty/SDL3-3.4.0/examples/camera/01-read-and-draw/read-and-draw.c
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* This example code reads frames from a camera and draws it to the screen.
|
||||
*
|
||||
* This is a very simple approach that is often Good Enough. You can get
|
||||
* fancier with this: multiple cameras, front/back facing cameras on phones,
|
||||
* color spaces, choosing formats and framerates...this just requests
|
||||
* _anything_ and goes with what it is handed.
|
||||
*
|
||||
* 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_Camera *camera = NULL;
|
||||
static SDL_Texture *texture = NULL;
|
||||
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
SDL_CameraID *devices = NULL;
|
||||
int devcount = 0;
|
||||
|
||||
SDL_SetAppMetadata("Example Camera Read and Draw", "1.0", "com.example.camera-read-and-draw");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CAMERA)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
devices = SDL_GetCameras(&devcount);
|
||||
if (devices == NULL) {
|
||||
SDL_Log("Couldn't enumerate camera devices: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
} else if (devcount == 0) {
|
||||
SDL_Log("Couldn't find any camera devices! Please connect a camera and try again.");
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
camera = SDL_OpenCamera(devices[0], NULL); // just take the first thing we see in any format it wants.
|
||||
SDL_free(devices);
|
||||
if (camera == NULL) {
|
||||
SDL_Log("Couldn't open camera: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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_CAMERA_DEVICE_APPROVED) {
|
||||
SDL_Log("Camera use approved by user!");
|
||||
} else if (event->type == SDL_EVENT_CAMERA_DEVICE_DENIED) {
|
||||
SDL_Log("Camera use denied by user!");
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
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)
|
||||
{
|
||||
Uint64 timestampNS = 0;
|
||||
SDL_Surface *frame = SDL_AcquireCameraFrame(camera, ×tampNS);
|
||||
|
||||
if (frame != NULL) {
|
||||
/* Some platforms (like Emscripten) don't know _what_ the camera offers
|
||||
until the user gives permission, so we build the texture and resize
|
||||
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);
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
SDL_UpdateTexture(texture, NULL, frame->pixels, frame->pitch);
|
||||
}
|
||||
|
||||
SDL_ReleaseCameraFrame(camera, frame);
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0x99, 0x99, 0x99, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(renderer);
|
||||
if (texture) { /* draw the latest camera frame, if available. */
|
||||
SDL_RenderTexture(renderer, texture, NULL, NULL);
|
||||
}
|
||||
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_CloseCamera(camera);
|
||||
SDL_DestroyTexture(texture);
|
||||
/* SDL will clean up the window/renderer for us. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/camera/01-read-and-draw/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 234 KiB |
14
thirdparty/SDL3-3.4.0/examples/categories.txt
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Blank lines and lines that start with '#' in this file are ignored.
|
||||
|
||||
# Categories, by directory name, go in here, in the order they should be
|
||||
# listed on the main page. If this file is missing, it'll assume any
|
||||
# subdirectory is a category and sort them alphabetically.
|
||||
|
||||
renderer
|
||||
input
|
||||
audio
|
||||
camera
|
||||
asyncio
|
||||
pen
|
||||
misc
|
||||
demo
|
||||
1
thirdparty/SDL3-3.4.0/examples/demo/01-snake/README.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
A complete game of Snake, written in SDL.
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/demo/01-snake/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
396
thirdparty/SDL3-3.4.0/examples/demo/01-snake/snake.c
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Logic implementation of the Snake game. It is designed to efficiently
|
||||
* represent the state of the game in memory.
|
||||
*
|
||||
* 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>
|
||||
|
||||
#define STEP_RATE_IN_MILLISECONDS 125
|
||||
#define SNAKE_BLOCK_SIZE_IN_PIXELS 24
|
||||
#define SDL_WINDOW_WIDTH (SNAKE_BLOCK_SIZE_IN_PIXELS * SNAKE_GAME_WIDTH)
|
||||
#define SDL_WINDOW_HEIGHT (SNAKE_BLOCK_SIZE_IN_PIXELS * SNAKE_GAME_HEIGHT)
|
||||
|
||||
#define SNAKE_GAME_WIDTH 24U
|
||||
#define SNAKE_GAME_HEIGHT 18U
|
||||
#define SNAKE_MATRIX_SIZE (SNAKE_GAME_WIDTH * SNAKE_GAME_HEIGHT)
|
||||
|
||||
#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,
|
||||
SNAKE_CELL_SRIGHT = 1U,
|
||||
SNAKE_CELL_SUP = 2U,
|
||||
SNAKE_CELL_SLEFT = 3U,
|
||||
SNAKE_CELL_SDOWN = 4U,
|
||||
SNAKE_CELL_FOOD = 5U
|
||||
} SnakeCell;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SNAKE_DIR_RIGHT,
|
||||
SNAKE_DIR_UP,
|
||||
SNAKE_DIR_LEFT,
|
||||
SNAKE_DIR_DOWN
|
||||
} SnakeDirection;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char cells[(SNAKE_MATRIX_SIZE * SNAKE_CELL_MAX_BITS) / 8U];
|
||||
char head_xpos;
|
||||
char head_ypos;
|
||||
char tail_xpos;
|
||||
char tail_ypos;
|
||||
char next_dir;
|
||||
char inhibit_tail_step;
|
||||
unsigned occupied_cells;
|
||||
} SnakeContext;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SnakeContext snake_ctx;
|
||||
Uint64 last_step;
|
||||
} AppState;
|
||||
|
||||
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)) & SNAKE_CELL_SET_BITS);
|
||||
}
|
||||
|
||||
static void set_rect_xy_(SDL_FRect *r, short x, short y)
|
||||
{
|
||||
r->x = (float)(x * SNAKE_BLOCK_SIZE_IN_PIXELS);
|
||||
r->y = (float)(y * SNAKE_BLOCK_SIZE_IN_PIXELS);
|
||||
}
|
||||
|
||||
static void put_cell_at_(SnakeContext *ctx, char x, char y, SnakeCell ct)
|
||||
{
|
||||
const int shift = SHIFT(x, y);
|
||||
const int adjust = shift % 8;
|
||||
unsigned char *const pos = ctx->cells + (shift / 8);
|
||||
unsigned short range;
|
||||
SDL_memcpy(&range, pos, sizeof(range));
|
||||
range &= ~(SNAKE_CELL_SET_BITS << adjust); /* clear bits */
|
||||
range |= (ct & SNAKE_CELL_SET_BITS) << adjust;
|
||||
SDL_memcpy(pos, &range, sizeof(range));
|
||||
}
|
||||
|
||||
static int are_cells_full_(SnakeContext *ctx)
|
||||
{
|
||||
return ctx->occupied_cells == SNAKE_GAME_WIDTH * SNAKE_GAME_HEIGHT;
|
||||
}
|
||||
|
||||
static void new_food_pos_(SnakeContext *ctx)
|
||||
{
|
||||
while (true) {
|
||||
const char x = (char) SDL_rand(SNAKE_GAME_WIDTH);
|
||||
const char y = (char) SDL_rand(SNAKE_GAME_HEIGHT);
|
||||
if (snake_cell_at(ctx, x, y) == SNAKE_CELL_NOTHING) {
|
||||
put_cell_at_(ctx, x, y, SNAKE_CELL_FOOD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void snake_initialize(SnakeContext *ctx)
|
||||
{
|
||||
int i;
|
||||
SDL_zeroa(ctx->cells);
|
||||
ctx->head_xpos = ctx->tail_xpos = SNAKE_GAME_WIDTH / 2;
|
||||
ctx->head_ypos = ctx->tail_ypos = SNAKE_GAME_HEIGHT / 2;
|
||||
ctx->next_dir = SNAKE_DIR_RIGHT;
|
||||
ctx->inhibit_tail_step = ctx->occupied_cells = 4;
|
||||
--ctx->occupied_cells;
|
||||
put_cell_at_(ctx, ctx->tail_xpos, ctx->tail_ypos, SNAKE_CELL_SRIGHT);
|
||||
for (i = 0; i < 4; i++) {
|
||||
new_food_pos_(ctx);
|
||||
++ctx->occupied_cells;
|
||||
}
|
||||
}
|
||||
|
||||
void snake_redir(SnakeContext *ctx, SnakeDirection dir)
|
||||
{
|
||||
SnakeCell ct = snake_cell_at(ctx, ctx->head_xpos, ctx->head_ypos);
|
||||
if ((dir == SNAKE_DIR_RIGHT && ct != SNAKE_CELL_SLEFT) ||
|
||||
(dir == SNAKE_DIR_UP && ct != SNAKE_CELL_SDOWN) ||
|
||||
(dir == SNAKE_DIR_LEFT && ct != SNAKE_CELL_SRIGHT) ||
|
||||
(dir == SNAKE_DIR_DOWN && ct != SNAKE_CELL_SUP)) {
|
||||
ctx->next_dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
static void wrap_around_(char *val, char max)
|
||||
{
|
||||
if (*val < 0) {
|
||||
*val = max - 1;
|
||||
} else if (*val > max - 1) {
|
||||
*val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void snake_step(SnakeContext *ctx)
|
||||
{
|
||||
const SnakeCell dir_as_cell = (SnakeCell)(ctx->next_dir + 1);
|
||||
SnakeCell ct;
|
||||
char prev_xpos;
|
||||
char prev_ypos;
|
||||
/* Move tail forward */
|
||||
if (--ctx->inhibit_tail_step == 0) {
|
||||
++ctx->inhibit_tail_step;
|
||||
ct = snake_cell_at(ctx, ctx->tail_xpos, ctx->tail_ypos);
|
||||
put_cell_at_(ctx, ctx->tail_xpos, ctx->tail_ypos, SNAKE_CELL_NOTHING);
|
||||
switch (ct) {
|
||||
case SNAKE_CELL_SRIGHT:
|
||||
ctx->tail_xpos++;
|
||||
break;
|
||||
case SNAKE_CELL_SUP:
|
||||
ctx->tail_ypos--;
|
||||
break;
|
||||
case SNAKE_CELL_SLEFT:
|
||||
ctx->tail_xpos--;
|
||||
break;
|
||||
case SNAKE_CELL_SDOWN:
|
||||
ctx->tail_ypos++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wrap_around_(&ctx->tail_xpos, SNAKE_GAME_WIDTH);
|
||||
wrap_around_(&ctx->tail_ypos, SNAKE_GAME_HEIGHT);
|
||||
}
|
||||
/* Move head forward */
|
||||
prev_xpos = ctx->head_xpos;
|
||||
prev_ypos = ctx->head_ypos;
|
||||
switch (ctx->next_dir) {
|
||||
case SNAKE_DIR_RIGHT:
|
||||
++ctx->head_xpos;
|
||||
break;
|
||||
case SNAKE_DIR_UP:
|
||||
--ctx->head_ypos;
|
||||
break;
|
||||
case SNAKE_DIR_LEFT:
|
||||
--ctx->head_xpos;
|
||||
break;
|
||||
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);
|
||||
/* Collisions */
|
||||
ct = snake_cell_at(ctx, ctx->head_xpos, ctx->head_ypos);
|
||||
if (ct != SNAKE_CELL_NOTHING && ct != SNAKE_CELL_FOOD) {
|
||||
snake_initialize(ctx);
|
||||
return;
|
||||
}
|
||||
put_cell_at_(ctx, prev_xpos, prev_ypos, dir_as_cell);
|
||||
put_cell_at_(ctx, ctx->head_xpos, ctx->head_ypos, dir_as_cell);
|
||||
if (ct == SNAKE_CELL_FOOD) {
|
||||
if (are_cells_full_(ctx)) {
|
||||
snake_initialize(ctx);
|
||||
return;
|
||||
}
|
||||
new_food_pos_(ctx);
|
||||
++ctx->inhibit_tail_step;
|
||||
++ctx->occupied_cells;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_AppResult handle_key_event_(SnakeContext *ctx, SDL_Scancode key_code)
|
||||
{
|
||||
switch (key_code) {
|
||||
/* Quit. */
|
||||
case SDL_SCANCODE_ESCAPE:
|
||||
case SDL_SCANCODE_Q:
|
||||
return SDL_APP_SUCCESS;
|
||||
/* Restart the game as if the program was launched. */
|
||||
case SDL_SCANCODE_R:
|
||||
snake_initialize(ctx);
|
||||
break;
|
||||
/* Decide new direction of the snake. */
|
||||
case SDL_SCANCODE_RIGHT:
|
||||
snake_redir(ctx, SNAKE_DIR_RIGHT);
|
||||
break;
|
||||
case SDL_SCANCODE_UP:
|
||||
snake_redir(ctx, SNAKE_DIR_UP);
|
||||
break;
|
||||
case SDL_SCANCODE_LEFT:
|
||||
snake_redir(ctx, SNAKE_DIR_LEFT);
|
||||
break;
|
||||
case SDL_SCANCODE_DOWN:
|
||||
snake_redir(ctx, SNAKE_DIR_DOWN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
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;
|
||||
SnakeContext *ctx = &as->snake_ctx;
|
||||
const Uint64 now = SDL_GetTicks();
|
||||
SDL_FRect r;
|
||||
unsigned i;
|
||||
unsigned j;
|
||||
int ct;
|
||||
|
||||
// run game logic if we're at or past the time to run it.
|
||||
// if we're _really_ behind the time to run it, run it
|
||||
// several times.
|
||||
while ((now - as->last_step) >= STEP_RATE_IN_MILLISECONDS) {
|
||||
snake_step(ctx);
|
||||
as->last_step += STEP_RATE_IN_MILLISECONDS;
|
||||
}
|
||||
|
||||
r.w = r.h = SNAKE_BLOCK_SIZE_IN_PIXELS;
|
||||
SDL_SetRenderDrawColor(as->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(as->renderer);
|
||||
for (i = 0; i < SNAKE_GAME_WIDTH; i++) {
|
||||
for (j = 0; j < SNAKE_GAME_HEIGHT; j++) {
|
||||
ct = snake_cell_at(ctx, i, j);
|
||||
if (ct == SNAKE_CELL_NOTHING)
|
||||
continue;
|
||||
set_rect_xy_(&r, i, j);
|
||||
if (ct == SNAKE_CELL_FOOD)
|
||||
SDL_SetRenderDrawColor(as->renderer, 80, 80, 255, SDL_ALPHA_OPAQUE);
|
||||
else /* body */
|
||||
SDL_SetRenderDrawColor(as->renderer, 0, 128, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderFillRect(as->renderer, &r);
|
||||
}
|
||||
}
|
||||
SDL_SetRenderDrawColor(as->renderer, 255, 255, 0, SDL_ALPHA_OPAQUE); /*head*/
|
||||
set_rect_xy_(&r, ctx->head_xpos, ctx->head_ypos);
|
||||
SDL_RenderFillRect(as->renderer, &r);
|
||||
SDL_RenderPresent(as->renderer);
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *key;
|
||||
const char *value;
|
||||
} extended_metadata[] =
|
||||
{
|
||||
{ SDL_PROP_APP_METADATA_URL_STRING, "https://examples.libsdl.org/SDL3/demo/01-snake/" },
|
||||
{ SDL_PROP_APP_METADATA_CREATOR_STRING, "SDL team" },
|
||||
{ SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Placed in the public domain" },
|
||||
{ SDL_PROP_APP_METADATA_TYPE_STRING, "game" }
|
||||
};
|
||||
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!SDL_SetAppMetadata("Example Snake game", "1.0", "com.example.Snake")) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
for (i = 0; i < SDL_arraysize(extended_metadata); i++) {
|
||||
if (!SDL_SetAppMetadataProperty(extended_metadata[i].key, extended_metadata[i].value)) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
AppState *as = (AppState *)SDL_calloc(1, sizeof(AppState));
|
||||
if (!as) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
*appstate = as;
|
||||
|
||||
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);
|
||||
|
||||
as->last_step = SDL_GetTicks();
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
||||
{
|
||||
SnakeContext *ctx = &((AppState *)appstate)->snake_ctx;
|
||||
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);
|
||||
SDL_DestroyWindow(as->window);
|
||||
SDL_free(as);
|
||||
}
|
||||
}
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/demo/01-snake/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
1
thirdparty/SDL3-3.4.0/examples/demo/02-woodeneye-008/README.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Minimal splitscreen FPS with multiple mouse and keyboards, drawn with the 2D Render API.
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/demo/02-woodeneye-008/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 457 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/demo/02-woodeneye-008/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 25 KiB |
480
thirdparty/SDL3-3.4.0/examples/demo/02-woodeneye-008/woodeneye-008.c
vendored
Normal file
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#define MAP_BOX_SCALE 16
|
||||
#define MAP_BOX_EDGES_LEN (12 + MAP_BOX_SCALE * 2)
|
||||
#define MAX_PLAYER_COUNT 4
|
||||
#define CIRCLE_DRAW_SIDES 32
|
||||
#define CIRCLE_DRAW_SIDES_LEN (CIRCLE_DRAW_SIDES + 1)
|
||||
|
||||
typedef struct {
|
||||
SDL_MouseID mouse;
|
||||
SDL_KeyboardID keyboard;
|
||||
double pos[3];
|
||||
double vel[3];
|
||||
unsigned int yaw;
|
||||
int pitch;
|
||||
float radius, height;
|
||||
unsigned char color[3];
|
||||
unsigned char wasd;
|
||||
} Player;
|
||||
|
||||
typedef struct {
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
int player_count;
|
||||
Player players[MAX_PLAYER_COUNT];
|
||||
float edges[MAP_BOX_EDGES_LEN][6];
|
||||
} AppState;
|
||||
|
||||
static const struct {
|
||||
const char *key;
|
||||
const char *value;
|
||||
} extended_metadata[] = {
|
||||
{ SDL_PROP_APP_METADATA_URL_STRING, "https://examples.libsdl.org/SDL3/demo/02-woodeneye-008/" },
|
||||
{ SDL_PROP_APP_METADATA_CREATOR_STRING, "SDL team" },
|
||||
{ SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Placed in the public domain" },
|
||||
{ SDL_PROP_APP_METADATA_TYPE_STRING, "game" }
|
||||
};
|
||||
|
||||
static int whoseMouse(SDL_MouseID mouse, const Player players[], int players_len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < players_len; i++) {
|
||||
if (players[i].mouse == mouse) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int whoseKeyboard(SDL_KeyboardID keyboard, const Player players[], int players_len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < players_len; i++) {
|
||||
if (players[i].keyboard == keyboard) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void shoot(int shooter, Player players[], int players_len)
|
||||
{
|
||||
int i, j;
|
||||
double x0 = players[shooter].pos[0];
|
||||
double y0 = players[shooter].pos[1];
|
||||
double z0 = players[shooter].pos[2];
|
||||
double bin_rad = SDL_PI_D / 2147483648.0;
|
||||
double yaw_rad = bin_rad * players[shooter].yaw;
|
||||
double pitch_rad = bin_rad * players[shooter].pitch;
|
||||
double cos_yaw = SDL_cos( yaw_rad);
|
||||
double sin_yaw = SDL_sin( yaw_rad);
|
||||
double cos_pitch = SDL_cos(pitch_rad);
|
||||
double sin_pitch = SDL_sin(pitch_rad);
|
||||
double vx = -sin_yaw*cos_pitch;
|
||||
double vy = sin_pitch;
|
||||
double vz = -cos_yaw*cos_pitch;
|
||||
for (i = 0; i < players_len; i++) {
|
||||
if (i == shooter) continue;
|
||||
Player *target = &(players[i]);
|
||||
int hit = 0;
|
||||
for (j = 0; j < 2; j++) {
|
||||
double r = target->radius;
|
||||
double h = target->height;
|
||||
double dx = target->pos[0] - x0;
|
||||
double dy = target->pos[1] - y0 + (j == 0 ? 0 : r - h);
|
||||
double dz = target->pos[2] - z0;
|
||||
double vd = vx*dx + vy*dy + vz*dz;
|
||||
double dd = dx*dx + dy*dy + dz*dz;
|
||||
double vv = vx*vx + vy*vy + vz*vz;
|
||||
double rr = r * r;
|
||||
if (vd < 0) continue;
|
||||
if (vd * vd >= vv * (dd - rr)) hit += 1;
|
||||
}
|
||||
if (hit) {
|
||||
target->pos[0] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256;
|
||||
target->pos[1] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256;
|
||||
target->pos[2] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update(Player *players, int players_len, Uint64 dt_ns)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < players_len; i++) {
|
||||
Player *player = &players[i];
|
||||
double rate = 6.0;
|
||||
double time = (double)dt_ns * 1e-9;
|
||||
double drag = SDL_exp(-time * rate);
|
||||
double diff = 1.0 - drag;
|
||||
double mult = 60.0;
|
||||
double grav = 25.0;
|
||||
double yaw = (double)player->yaw;
|
||||
double rad = yaw * SDL_PI_D / 2147483648.0;
|
||||
double cos = SDL_cos(rad);
|
||||
double sin = SDL_sin(rad);
|
||||
unsigned char wasd = player->wasd;
|
||||
double dirX = (wasd & 8 ? 1.0 : 0.0) - (wasd & 2 ? 1.0 : 0.0);
|
||||
double dirZ = (wasd & 4 ? 1.0 : 0.0) - (wasd & 1 ? 1.0 : 0.0);
|
||||
double norm = dirX * dirX + dirZ * dirZ;
|
||||
double accX = mult * (norm == 0 ? 0 : ( cos*dirX + sin*dirZ) / SDL_sqrt(norm));
|
||||
double accZ = mult * (norm == 0 ? 0 : (-sin*dirX + cos*dirZ) / SDL_sqrt(norm));
|
||||
double velX = player->vel[0];
|
||||
double velY = player->vel[1];
|
||||
double velZ = player->vel[2];
|
||||
player->vel[0] -= velX * diff;
|
||||
player->vel[1] -= grav * time;
|
||||
player->vel[2] -= velZ * diff;
|
||||
player->vel[0] += diff * accX / rate;
|
||||
player->vel[2] += diff * accZ / rate;
|
||||
player->pos[0] += (time - diff/rate) * accX / rate + diff * velX / rate;
|
||||
player->pos[1] += -0.5 * grav * time * time + velY * time;
|
||||
player->pos[2] += (time - diff/rate) * accZ / rate + diff * velZ / rate;
|
||||
double scale = (double)MAP_BOX_SCALE;
|
||||
double bound = scale - player->radius;
|
||||
double posX = SDL_max(SDL_min(bound, player->pos[0]), -bound);
|
||||
double posY = SDL_max(SDL_min(bound, player->pos[1]), player->height - scale);
|
||||
double posZ = SDL_max(SDL_min(bound, player->pos[2]), -bound);
|
||||
if (player->pos[0] != posX) player->vel[0] = 0;
|
||||
if (player->pos[1] != posY) player->vel[1] = (wasd & 16) ? 8.4375 : 0;
|
||||
if (player->pos[2] != posZ) player->vel[2] = 0;
|
||||
player->pos[0] = posX;
|
||||
player->pos[1] = posY;
|
||||
player->pos[2] = posZ;
|
||||
}
|
||||
}
|
||||
|
||||
static void drawCircle(SDL_Renderer *renderer, float r, float x, float y)
|
||||
{
|
||||
float ang;
|
||||
SDL_FPoint points[CIRCLE_DRAW_SIDES_LEN];
|
||||
int i;
|
||||
for (i = 0; i < CIRCLE_DRAW_SIDES_LEN; i++) {
|
||||
ang = 2.0f * SDL_PI_F * (float)i / (float)CIRCLE_DRAW_SIDES;
|
||||
points[i].x = x + r * SDL_cosf(ang);
|
||||
points[i].y = y + r * SDL_sinf(ang);
|
||||
}
|
||||
SDL_RenderLines(renderer, (const SDL_FPoint*)&points, CIRCLE_DRAW_SIDES_LEN);
|
||||
}
|
||||
|
||||
static void drawClippedSegment(
|
||||
SDL_Renderer *renderer,
|
||||
float ax, float ay, float az,
|
||||
float bx, float by, float bz,
|
||||
float x, float y, float z, float w)
|
||||
{
|
||||
if (az >= -w && bz >= -w) return;
|
||||
float dx = ax - bx;
|
||||
float dy = ay - by;
|
||||
if (az > -w) {
|
||||
float t = (-w - bz) / (az - bz);
|
||||
ax = bx + dx * t;
|
||||
ay = by + dy * t;
|
||||
az = -w;
|
||||
} else if (bz > -w) {
|
||||
float t = (-w - az) / (bz - az);
|
||||
bx = ax - dx * t;
|
||||
by = ay - dy * t;
|
||||
bz = -w;
|
||||
}
|
||||
ax = -z * ax / az;
|
||||
ay = -z * ay / az;
|
||||
bx = -z * bx / bz;
|
||||
by = -z * by / bz;
|
||||
SDL_RenderLine(renderer, x + ax, y - ay, x + bx, y - by);
|
||||
}
|
||||
|
||||
static char debug_string[32];
|
||||
static void draw(SDL_Renderer *renderer, const float (*edges)[6], const Player players[], int players_len)
|
||||
{
|
||||
int w, h, i, j, k;
|
||||
if (!SDL_GetRenderOutputSize(renderer, &w, &h)) {
|
||||
return;
|
||||
}
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(renderer);
|
||||
if (players_len > 0) {
|
||||
float wf = (float)w;
|
||||
float hf = (float)h;
|
||||
int part_hor = players_len > 2 ? 2 : 1;
|
||||
int part_ver = players_len > 1 ? 2 : 1;
|
||||
float size_hor = wf / ((float)part_hor);
|
||||
float size_ver = hf / ((float)part_ver);
|
||||
for (i = 0; i < players_len; i++) {
|
||||
const Player *player = &players[i];
|
||||
float mod_x = (float)(i % part_hor);
|
||||
float mod_y = (float)(i / part_hor);
|
||||
float hor_origin = (mod_x + 0.5f) * size_hor;
|
||||
float ver_origin = (mod_y + 0.5f) * size_ver;
|
||||
float cam_origin = (float)(0.5 * SDL_sqrt(size_hor * size_hor + size_ver * size_ver));
|
||||
float hor_offset = mod_x * size_hor;
|
||||
float ver_offset = mod_y * size_ver;
|
||||
SDL_Rect rect;
|
||||
rect.x = (int)hor_offset;
|
||||
rect.y = (int)ver_offset;
|
||||
rect.w = (int)size_hor;
|
||||
rect.h = (int)size_ver;
|
||||
SDL_SetRenderClipRect(renderer, &rect);
|
||||
double x0 = player->pos[0];
|
||||
double y0 = player->pos[1];
|
||||
double z0 = player->pos[2];
|
||||
double bin_rad = SDL_PI_D / 2147483648.0;
|
||||
double yaw_rad = bin_rad * player->yaw;
|
||||
double pitch_rad = bin_rad * player->pitch;
|
||||
double cos_yaw = SDL_cos( yaw_rad);
|
||||
double sin_yaw = SDL_sin( yaw_rad);
|
||||
double cos_pitch = SDL_cos(pitch_rad);
|
||||
double sin_pitch = SDL_sin(pitch_rad);
|
||||
double mat[9] = {
|
||||
cos_yaw , 0, -sin_yaw ,
|
||||
sin_yaw*sin_pitch, cos_pitch, cos_yaw*sin_pitch,
|
||||
sin_yaw*cos_pitch, -sin_pitch, cos_yaw*cos_pitch
|
||||
};
|
||||
SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255);
|
||||
for (k = 0; k < MAP_BOX_EDGES_LEN; k++) {
|
||||
const float *line = edges[k];
|
||||
float ax = (float)(mat[0] * (line[0] - x0) + mat[1] * (line[1] - y0) + mat[2] * (line[2] - z0));
|
||||
float ay = (float)(mat[3] * (line[0] - x0) + mat[4] * (line[1] - y0) + mat[5] * (line[2] - z0));
|
||||
float az = (float)(mat[6] * (line[0] - x0) + mat[7] * (line[1] - y0) + mat[8] * (line[2] - z0));
|
||||
float bx = (float)(mat[0] * (line[3] - x0) + mat[1] * (line[4] - y0) + mat[2] * (line[5] - z0));
|
||||
float by = (float)(mat[3] * (line[3] - x0) + mat[4] * (line[4] - y0) + mat[5] * (line[5] - z0));
|
||||
float bz = (float)(mat[6] * (line[3] - x0) + mat[7] * (line[4] - y0) + mat[8] * (line[5] - z0));
|
||||
drawClippedSegment(renderer, ax, ay, az, bx, by, bz, hor_origin, ver_origin, cam_origin, 1);
|
||||
}
|
||||
for (j = 0; j < players_len; j++) {
|
||||
if (i == j) continue;
|
||||
const Player *target = &players[j];
|
||||
SDL_SetRenderDrawColor(renderer, target->color[0], target->color[1], target->color[2], 255);
|
||||
for (k = 0; k < 2; k++) {
|
||||
double rx = target->pos[0] - player->pos[0];
|
||||
double ry = target->pos[1] - player->pos[1] + (target->radius - target->height) * (float)k;
|
||||
double rz = target->pos[2] - player->pos[2];
|
||||
double dx = mat[0] * rx + mat[1] * ry + mat[2] * rz;
|
||||
double dy = mat[3] * rx + mat[4] * ry + mat[5] * rz;
|
||||
double dz = mat[6] * rx + mat[7] * ry + mat[8] * rz;
|
||||
double r_eff = target->radius * cam_origin / dz;
|
||||
if (!(dz < 0)) continue;
|
||||
drawCircle(renderer, (float)(r_eff), (float)(hor_origin - cam_origin*dx/dz), (float)(ver_origin + cam_origin*dy/dz));
|
||||
}
|
||||
}
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
SDL_RenderLine(renderer, hor_origin, ver_origin-10, hor_origin, ver_origin+10);
|
||||
SDL_RenderLine(renderer, hor_origin-10, ver_origin, hor_origin+10, ver_origin);
|
||||
}
|
||||
}
|
||||
SDL_SetRenderClipRect(renderer, NULL);
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
SDL_RenderDebugText(renderer, 0, 0, debug_string);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
static void initPlayers(Player *players, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
players[i].pos[0] = 8.0 * (i & 1 ? -1.0 : 1.0);
|
||||
players[i].pos[1] = 0;
|
||||
players[i].pos[2] = 8.0 * (i & 1 ? -1.0 : 1.0) * (i & 2 ? -1.0 : 1.0);
|
||||
players[i].vel[0] = 0;
|
||||
players[i].vel[1] = 0;
|
||||
players[i].vel[2] = 0;
|
||||
players[i].yaw = 0x20000000 + (i & 1 ? 0x80000000 : 0) + (i & 2 ? 0x40000000 : 0);
|
||||
players[i].pitch = -0x08000000;
|
||||
players[i].radius = 0.5f;
|
||||
players[i].height = 1.5f;
|
||||
players[i].wasd = 0;
|
||||
players[i].mouse = 0;
|
||||
players[i].keyboard = 0;
|
||||
players[i].color[0] = (1 << (i / 2)) & 2 ? 0 : 0xff;
|
||||
players[i].color[1] = (1 << (i / 2)) & 1 ? 0 : 0xff;
|
||||
players[i].color[2] = (1 << (i / 2)) & 4 ? 0 : 0xff;
|
||||
players[i].color[0] = (i & 1) ? players[i].color[0] : ~players[i].color[0];
|
||||
players[i].color[1] = (i & 1) ? players[i].color[1] : ~players[i].color[1];
|
||||
players[i].color[2] = (i & 1) ? players[i].color[2] : ~players[i].color[2];
|
||||
}
|
||||
}
|
||||
|
||||
static void initEdges(int scale, float (*edges)[6], int edges_len)
|
||||
{
|
||||
int i, j;
|
||||
const float r = (float)scale;
|
||||
const int map[24] = {
|
||||
0,1 , 1,3 , 3,2 , 2,0 ,
|
||||
7,6 , 6,4 , 4,5 , 5,7 ,
|
||||
6,2 , 3,7 , 0,4 , 5,1
|
||||
};
|
||||
for(i = 0; i < 12; i++) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
edges[i][j+0] = (map[i*2+0] & (1 << j) ? r : -r);
|
||||
edges[i][j+3] = (map[i*2+1] & (1 << j) ? r : -r);
|
||||
}
|
||||
}
|
||||
for(i = 0; i < scale; i++) {
|
||||
float d = (float)(i * 2);
|
||||
for (j = 0; j < 2; j++) {
|
||||
edges[i+12][3*j+0] = j ? r : -r;
|
||||
edges[i+12][3*j+1] = -r;
|
||||
edges[i+12][3*j+2] = d-r;
|
||||
edges[i+12+scale][3*j+0] = d-r;
|
||||
edges[i+12+scale][3*j+1] = -r;
|
||||
edges[i+12+scale][3*j+2] = j ? r : -r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
if (!SDL_SetAppMetadata("Example splitscreen shooter game", "1.0", "com.example.woodeneye-008")) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < SDL_arraysize(extended_metadata); i++) {
|
||||
if (!SDL_SetAppMetadataProperty(extended_metadata[i].key, extended_metadata[i].value)) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
AppState *as = SDL_calloc(1, sizeof(AppState));
|
||||
if (!as) {
|
||||
return SDL_APP_FAILURE;
|
||||
} else {
|
||||
*appstate = as;
|
||||
}
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
if (!SDL_CreateWindowAndRenderer("examples/demo/woodeneye-008", 640, 480, SDL_WINDOW_RESIZABLE, &as->window, &as->renderer)) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
as->player_count = 1;
|
||||
initPlayers(as->players, MAX_PLAYER_COUNT);
|
||||
initEdges(MAP_BOX_SCALE, as->edges, MAP_BOX_EDGES_LEN);
|
||||
debug_string[0] = 0;
|
||||
|
||||
SDL_SetRenderVSync(as->renderer, false);
|
||||
SDL_SetWindowRelativeMouseMode(as->window, true);
|
||||
SDL_SetHintWithPriority(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1", SDL_HINT_OVERRIDE);
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
||||
{
|
||||
AppState *as = appstate;
|
||||
Player *players = as->players;
|
||||
int player_count = as->player_count;
|
||||
int i;
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return SDL_APP_SUCCESS;
|
||||
break;
|
||||
case SDL_EVENT_MOUSE_REMOVED:
|
||||
for (i = 0; i < player_count; i++) {
|
||||
if (players[i].mouse == event->mdevice.which) {
|
||||
players[i].mouse = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_KEYBOARD_REMOVED:
|
||||
for (i = 0; i < player_count; i++) {
|
||||
if (players[i].keyboard == event->kdevice.which) {
|
||||
players[i].keyboard = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_MOUSE_MOTION: {
|
||||
SDL_MouseID id = event->motion.which;
|
||||
int index = whoseMouse(id, players, player_count);
|
||||
if (index >= 0) {
|
||||
players[index].yaw -= ((int)event->motion.xrel) * 0x00080000;
|
||||
players[index].pitch = SDL_max(-0x40000000, SDL_min(0x40000000, players[index].pitch - ((int)event->motion.yrel) * 0x00080000));
|
||||
} else if (id) {
|
||||
for (i = 0; i < MAX_PLAYER_COUNT; i++) {
|
||||
if (players[i].mouse == 0) {
|
||||
players[i].mouse = id;
|
||||
as->player_count = SDL_max(as->player_count, i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
||||
SDL_MouseID id = event->button.which;
|
||||
int index = whoseMouse(id, players, player_count);
|
||||
if (index >= 0) {
|
||||
shoot(index, players, player_count);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_KEY_DOWN: {
|
||||
SDL_Keycode sym = event->key.key;
|
||||
SDL_KeyboardID id = event->key.which;
|
||||
int index = whoseKeyboard(id, players, player_count);
|
||||
if (index >= 0) {
|
||||
if (sym == SDLK_W) players[index].wasd |= 1;
|
||||
if (sym == SDLK_A) players[index].wasd |= 2;
|
||||
if (sym == SDLK_S) players[index].wasd |= 4;
|
||||
if (sym == SDLK_D) players[index].wasd |= 8;
|
||||
if (sym == SDLK_SPACE) players[index].wasd |= 16;
|
||||
} else if (id) {
|
||||
for (i = 0; i < MAX_PLAYER_COUNT; i++) {
|
||||
if (players[i].keyboard == 0) {
|
||||
players[i].keyboard = id;
|
||||
as->player_count = SDL_max(as->player_count, i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_KEY_UP: {
|
||||
SDL_Keycode sym = event->key.key;
|
||||
SDL_KeyboardID id = event->key.which;
|
||||
if (sym == SDLK_ESCAPE) return SDL_APP_SUCCESS;
|
||||
int index = whoseKeyboard(id, players, player_count);
|
||||
if (index >= 0) {
|
||||
if (sym == SDLK_W) players[index].wasd &= 30;
|
||||
if (sym == SDLK_A) players[index].wasd &= 29;
|
||||
if (sym == SDLK_S) players[index].wasd &= 27;
|
||||
if (sym == SDLK_D) players[index].wasd &= 23;
|
||||
if (sym == SDLK_SPACE) players[index].wasd &= 15;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
{
|
||||
AppState *as = appstate;
|
||||
static Uint64 accu = 0;
|
||||
static Uint64 last = 0;
|
||||
static Uint64 past = 0;
|
||||
Uint64 now = SDL_GetTicksNS();
|
||||
Uint64 dt_ns = now - past;
|
||||
update(as->players, as->player_count, dt_ns);
|
||||
draw(as->renderer, (const float (*)[6])as->edges, as->players, as->player_count);
|
||||
if (now - last > 999999999) {
|
||||
last = now;
|
||||
SDL_snprintf(debug_string, sizeof(debug_string), "%" SDL_PRIu64 " fps", accu);
|
||||
accu = 0;
|
||||
}
|
||||
past = now;
|
||||
accu += 1;
|
||||
Uint64 elapsed = SDL_GetTicksNS() - now;
|
||||
if (elapsed < 999999) {
|
||||
SDL_DelayNS(999999 - elapsed);
|
||||
}
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
void SDL_AppQuit(void *appstate, SDL_AppResult result)
|
||||
{
|
||||
SDL_free(appstate); // just free the memory, SDL will clean up the window/renderer for us.
|
||||
}
|
||||
7
thirdparty/SDL3-3.4.0/examples/demo/03-infinite-monkeys/README.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
How many monkeys does it take to write the complete works of Shakespeare?
|
||||
|
||||
Now you can find out!
|
||||
|
||||
Cheer on your favorite monkey as they bash keyboards on their way through classic literature.
|
||||
|
||||
377
thirdparty/SDL3-3.4.0/examples/demo/03-infinite-monkeys/infinite-monkeys.c
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* 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 char *text;
|
||||
static const char *end;
|
||||
static const char *progress;
|
||||
static SDL_Time start_time;
|
||||
static SDL_Time end_time;
|
||||
typedef struct {
|
||||
Uint32 *text;
|
||||
int length;
|
||||
} Line;
|
||||
int row = 0;
|
||||
int rows = 0;
|
||||
int cols = 0;
|
||||
static Line **lines;
|
||||
static Line monkey_chars;
|
||||
static int monkeys = 100;
|
||||
|
||||
/* The highest and lowest scancodes a monkey can hit */
|
||||
#define MIN_MONKEY_SCANCODE SDL_SCANCODE_A
|
||||
#define MAX_MONKEY_SCANCODE SDL_SCANCODE_SLASH
|
||||
|
||||
static const char *default_text =
|
||||
"Jabberwocky, by Lewis Carroll\n"
|
||||
"\n"
|
||||
"'Twas brillig, and the slithy toves\n"
|
||||
" Did gyre and gimble in the wabe:\n"
|
||||
"All mimsy were the borogoves,\n"
|
||||
" And the mome raths outgrabe.\n"
|
||||
"\n"
|
||||
"\"Beware the Jabberwock, my son!\n"
|
||||
" The jaws that bite, the claws that catch!\n"
|
||||
"Beware the Jubjub bird, and shun\n"
|
||||
" The frumious Bandersnatch!\"\n"
|
||||
"\n"
|
||||
"He took his vorpal sword in hand;\n"
|
||||
" Long time the manxome foe he sought-\n"
|
||||
"So rested he by the Tumtum tree\n"
|
||||
" And stood awhile in thought.\n"
|
||||
"\n"
|
||||
"And, as in uffish thought he stood,\n"
|
||||
" The Jabberwock, with eyes of flame,\n"
|
||||
"Came whiffling through the tulgey wood,\n"
|
||||
" And burbled as it came!\n"
|
||||
"\n"
|
||||
"One, two! One, two! And through and through\n"
|
||||
" The vorpal blade went snicker-snack!\n"
|
||||
"He left it dead, and with its head\n"
|
||||
" He went galumphing back.\n"
|
||||
"\n"
|
||||
"\"And hast thou slain the Jabberwock?\n"
|
||||
" Come to my arms, my beamish boy!\n"
|
||||
"O frabjous day! Callooh! Callay!\"\n"
|
||||
" He chortled in his joy.\n"
|
||||
"\n"
|
||||
"'Twas brillig, and the slithy toves\n"
|
||||
" Did gyre and gimble in the wabe:\n"
|
||||
"All mimsy were the borogoves,\n"
|
||||
" And the mome raths outgrabe.\n";
|
||||
|
||||
|
||||
static void FreeLines(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (rows > 0 && cols > 0) {
|
||||
for (i = 0; i < rows; ++i) {
|
||||
SDL_free(lines[i]->text);
|
||||
SDL_free(lines[i]);
|
||||
}
|
||||
SDL_free(lines);
|
||||
lines = NULL;
|
||||
}
|
||||
SDL_free(monkey_chars.text);
|
||||
monkey_chars.text = NULL;
|
||||
}
|
||||
|
||||
static void OnWindowSizeChanged(void)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
if (!SDL_GetCurrentRenderOutputSize(renderer, &w, &h)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FreeLines();
|
||||
|
||||
row = 0;
|
||||
rows = (h / SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) - 4;
|
||||
cols = (w / SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE);
|
||||
if (rows > 0 && cols > 0) {
|
||||
int i;
|
||||
|
||||
lines = (Line **)SDL_malloc(rows * sizeof(Line *));
|
||||
if (lines) {
|
||||
for (i = 0; i < rows; ++i) {
|
||||
lines[i] = (Line *)SDL_malloc(sizeof(Line));
|
||||
if (!lines[i]) {
|
||||
FreeLines();
|
||||
break;
|
||||
}
|
||||
lines[i]->text = (Uint32 *)SDL_malloc(cols * sizeof(Uint32));
|
||||
if (!lines[i]->text) {
|
||||
FreeLines();
|
||||
break;
|
||||
}
|
||||
lines[i]->length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
monkey_chars.text = (Uint32 *)SDL_malloc(cols * sizeof(Uint32));
|
||||
if (monkey_chars.text) {
|
||||
for (i = 0; i < cols; ++i) {
|
||||
monkey_chars.text[i] = ' ';
|
||||
}
|
||||
monkey_chars.length = cols;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
int arg = 1;
|
||||
|
||||
SDL_SetAppMetadata("Infinite Monkeys", "1.0", "com.example.infinite-monkeys");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (!SDL_CreateWindowAndRenderer("examples/demo/infinite-monkeys", 640, 480, 0, &window, &renderer)) {
|
||||
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
SDL_SetRenderVSync(renderer, 1);
|
||||
|
||||
if (argv[arg] && SDL_strcmp(argv[arg], "--monkeys") == 0) {
|
||||
++arg;
|
||||
if (argv[arg]) {
|
||||
monkeys = SDL_atoi(argv[arg]);
|
||||
++arg;
|
||||
} else {
|
||||
SDL_Log("Usage: %s [--monkeys N] [file.txt]", argv[0]);
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (argv[arg]) {
|
||||
const char *file = argv[arg];
|
||||
size_t size;
|
||||
text = (char *)SDL_LoadFile(file, &size);
|
||||
if (!text) {
|
||||
SDL_Log("Couldn't open %s: %s", file, SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
end = text + size;
|
||||
} else {
|
||||
text = SDL_strdup(default_text);
|
||||
end = text + SDL_strlen(text);
|
||||
}
|
||||
progress = text;
|
||||
|
||||
SDL_GetCurrentTime(&start_time);
|
||||
|
||||
OnWindowSizeChanged();
|
||||
|
||||
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)
|
||||
{
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
OnWindowSizeChanged();
|
||||
break;
|
||||
case SDL_EVENT_QUIT:
|
||||
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
|
||||
}
|
||||
return SDL_APP_CONTINUE; /* carry on with the program! */
|
||||
}
|
||||
|
||||
static void DisplayLine(float x, float y, Line *line)
|
||||
{
|
||||
/* Allocate maximum space potentially needed for this line */
|
||||
char *utf8 = (char *)SDL_malloc(line->length * 4 + 1);
|
||||
if (utf8) {
|
||||
char *spot = utf8;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < line->length; ++i) {
|
||||
spot = SDL_UCS4ToUTF8(line->text[i], spot);
|
||||
}
|
||||
*spot = '\0';
|
||||
|
||||
SDL_RenderDebugText(renderer, x, y, utf8);
|
||||
SDL_free(utf8);
|
||||
}
|
||||
}
|
||||
|
||||
static bool CanMonkeyType(Uint32 ch)
|
||||
{
|
||||
SDL_Keymod modstate;
|
||||
SDL_Scancode scancode = SDL_GetScancodeFromKey(ch, &modstate);
|
||||
if (scancode < MIN_MONKEY_SCANCODE || scancode > MAX_MONKEY_SCANCODE) {
|
||||
return false;
|
||||
}
|
||||
/* Monkeys can hit the shift key, but nothing else */
|
||||
if ((modstate & ~SDL_KMOD_SHIFT) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void AdvanceRow(void)
|
||||
{
|
||||
Line *line;
|
||||
|
||||
++row;
|
||||
line = lines[row % rows];
|
||||
line->length = 0;
|
||||
}
|
||||
|
||||
static void AddMonkeyChar(int monkey, Uint32 ch)
|
||||
{
|
||||
if (monkey >= 0 && monkey_chars.text) {
|
||||
monkey_chars.text[(monkey % cols)] = ch;
|
||||
}
|
||||
|
||||
if (lines) {
|
||||
if (ch == '\n') {
|
||||
AdvanceRow();
|
||||
} else {
|
||||
Line *line = lines[row % rows];
|
||||
line->text[line->length++] = ch;
|
||||
if (line->length == cols) {
|
||||
AdvanceRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_StepUTF8(&progress, NULL);
|
||||
}
|
||||
|
||||
static Uint32 GetNextChar(void)
|
||||
{
|
||||
Uint32 ch = 0;
|
||||
while (progress < end) {
|
||||
const char *spot = progress;
|
||||
ch = SDL_StepUTF8(&spot, NULL);
|
||||
if (CanMonkeyType(ch)) {
|
||||
break;
|
||||
} else {
|
||||
/* This is a freebie, monkeys can't type this */
|
||||
AddMonkeyChar(-1, ch);
|
||||
}
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
static Uint32 MonkeyPlay(void)
|
||||
{
|
||||
int count = (MAX_MONKEY_SCANCODE - MIN_MONKEY_SCANCODE + 1);
|
||||
SDL_Scancode scancode = (SDL_Scancode)(MIN_MONKEY_SCANCODE + SDL_rand(count));
|
||||
SDL_Keymod modstate = (SDL_rand(2) ? SDL_KMOD_SHIFT : 0);
|
||||
|
||||
return SDL_GetKeyFromScancode(scancode, modstate, false);
|
||||
}
|
||||
|
||||
/* This function runs once per frame, and is the heart of the program. */
|
||||
SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
{
|
||||
int i, monkey;
|
||||
Uint32 next_char = 0, ch;
|
||||
float x, y;
|
||||
char *caption = NULL;
|
||||
SDL_Time now, elapsed;
|
||||
int hours, minutes, seconds;
|
||||
SDL_FRect rect;
|
||||
|
||||
for (monkey = 0; monkey < monkeys; ++monkey) {
|
||||
if (next_char == 0) {
|
||||
next_char = GetNextChar();
|
||||
if (!next_char) {
|
||||
/* All done! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ch = MonkeyPlay();
|
||||
if (ch == next_char) {
|
||||
AddMonkeyChar(monkey, ch);
|
||||
next_char = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the screen */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
/* Show the text already decoded */
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
|
||||
x = 0.0f;
|
||||
y = 0.0f;
|
||||
if (lines) {
|
||||
int row_offset = row - rows + 1;
|
||||
if (row_offset < 0) {
|
||||
row_offset = 0;
|
||||
}
|
||||
for (i = 0; i < rows; ++i) {
|
||||
Line *line = lines[(row_offset + i) % rows];
|
||||
DisplayLine(x, y, line);
|
||||
y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
}
|
||||
|
||||
/* Show the caption */
|
||||
y = (float)((rows + 1) * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE);
|
||||
if (progress == end) {
|
||||
if (!end_time) {
|
||||
SDL_GetCurrentTime(&end_time);
|
||||
}
|
||||
now = end_time;
|
||||
} else {
|
||||
SDL_GetCurrentTime(&now);
|
||||
}
|
||||
elapsed = (now - start_time);
|
||||
elapsed /= SDL_NS_PER_SECOND;
|
||||
seconds = (int)(elapsed % 60);
|
||||
elapsed /= 60;
|
||||
minutes = (int)(elapsed % 60);
|
||||
elapsed /= 60;
|
||||
hours = (int)elapsed;
|
||||
SDL_asprintf(&caption, "Monkeys: %d - %dH:%dM:%dS", monkeys, hours, minutes, seconds);
|
||||
if (caption) {
|
||||
SDL_RenderDebugText(renderer, x, y, caption);
|
||||
SDL_free(caption);
|
||||
}
|
||||
y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
|
||||
/* Show the characters currently typed */
|
||||
DisplayLine(x, y, &monkey_chars);
|
||||
y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
}
|
||||
|
||||
/* Show the current progress */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE);
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.w = ((float)(progress - text) / (end - text)) * (cols * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE);
|
||||
rect.h = (float)SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
|
||||
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. */
|
||||
|
||||
FreeLines();
|
||||
SDL_free(text);
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/demo/03-infinite-monkeys/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/demo/03-infinite-monkeys/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
4
thirdparty/SDL3-3.4.0/examples/demo/04-bytepusher/README.txt
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
An implementation of the BytePusher VM
|
||||
|
||||
For example programs and more information about BytePusher, see
|
||||
https://esolangs.org/wiki/BytePusher
|
||||
397
thirdparty/SDL3-3.4.0/examples/demo/04-bytepusher/bytepusher.c
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* An implementation of the BytePusher VM.
|
||||
*
|
||||
* For example programs and more information about BytePusher, see
|
||||
* https://esolangs.org/wiki/BytePusher
|
||||
*
|
||||
* This code is public domain. Feel free to use it for any purpose!
|
||||
*/
|
||||
|
||||
#define SDL_MAIN_USE_CALLBACKS
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define SCREEN_W 256
|
||||
#define SCREEN_H 256
|
||||
#define RAM_SIZE 0x1000000
|
||||
#define FRAMES_PER_SECOND 60
|
||||
#define SAMPLES_PER_FRAME 256
|
||||
#define NS_PER_SECOND (Uint64)SDL_NS_PER_SECOND
|
||||
#define MAX_AUDIO_LATENCY_FRAMES 5
|
||||
|
||||
#define IO_KEYBOARD 0
|
||||
#define IO_PC 2
|
||||
#define IO_SCREEN_PAGE 5
|
||||
#define IO_AUDIO_BANK 6
|
||||
|
||||
typedef struct {
|
||||
Uint8 ram[RAM_SIZE + 8];
|
||||
Uint64 last_tick;
|
||||
Uint64 tick_acc;
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
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];
|
||||
int status_ticks;
|
||||
Uint16 keystate;
|
||||
bool display_help;
|
||||
bool positional_input;
|
||||
} BytePusher;
|
||||
|
||||
static const struct {
|
||||
const char *key;
|
||||
const char *value;
|
||||
} extended_metadata[] = {
|
||||
{ SDL_PROP_APP_METADATA_URL_STRING, "https://examples.libsdl.org/SDL3/demo/04-bytepusher/" },
|
||||
{ SDL_PROP_APP_METADATA_CREATOR_STRING, "SDL team" },
|
||||
{ SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Placed in the public domain" },
|
||||
{ SDL_PROP_APP_METADATA_TYPE_STRING, "game" }
|
||||
};
|
||||
|
||||
static inline Uint16 read_u16(const BytePusher* vm, Uint32 addr) {
|
||||
const Uint8* ptr = &vm->ram[addr];
|
||||
return ((Uint16)ptr[0] << 8) | ((Uint16)ptr[1]);
|
||||
}
|
||||
|
||||
static inline Uint32 read_u24(const BytePusher* vm, Uint32 addr) {
|
||||
const Uint8* ptr = &vm->ram[addr];
|
||||
return ((Uint32)ptr[0] << 16) | ((Uint32)ptr[1] << 8) | ((Uint32)ptr[2]);
|
||||
}
|
||||
|
||||
static void set_status(BytePusher* vm, const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
SDL_vsnprintf(vm->status, sizeof(vm->status), fmt, args);
|
||||
va_end(args);
|
||||
vm->status[sizeof(vm->status) - 1] = 0;
|
||||
vm->status_ticks = FRAMES_PER_SECOND * 3;
|
||||
}
|
||||
|
||||
static bool load(BytePusher* vm, SDL_IOStream* stream, bool closeio) {
|
||||
size_t bytes_read = 0;
|
||||
bool ok = true;
|
||||
|
||||
SDL_memset(vm->ram, 0, RAM_SIZE);
|
||||
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (bytes_read < RAM_SIZE) {
|
||||
size_t read = SDL_ReadIO(stream, &vm->ram[bytes_read], RAM_SIZE - bytes_read);
|
||||
bytes_read += read;
|
||||
if (read == 0) {
|
||||
ok = SDL_GetIOStatus(stream) == SDL_IO_STATUS_EOF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (closeio) {
|
||||
SDL_CloseIO(stream);
|
||||
}
|
||||
|
||||
SDL_ClearAudioStream(vm->audiostream);
|
||||
|
||||
vm->display_help = !ok;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static const char* filename(const char* path) {
|
||||
size_t i = SDL_strlen(path) + 1;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
if (path[i] == '/' || path[i] == '\\') {
|
||||
return path + i + 1;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
static bool load_file(BytePusher* vm, const char* path) {
|
||||
if (load(vm, SDL_IOFromFile(path, "rb"), true)) {
|
||||
set_status(vm, "loaded %s", filename(path));
|
||||
return true;
|
||||
} else {
|
||||
set_status(vm, "load failed: %s", filename(path));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void print(BytePusher* vm, int x, int y, const char* str) {
|
||||
SDL_SetRenderDrawColor(vm->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderDebugText(vm->renderer, (float)(x + 1), (float)(y + 1), str);
|
||||
SDL_SetRenderDrawColor(vm->renderer, 0xff, 0xff, 0xff, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderDebugText(vm->renderer, (float)x, (float)y, str);
|
||||
SDL_SetRenderDrawColor(vm->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
||||
BytePusher* vm;
|
||||
SDL_Rect usable_bounds;
|
||||
SDL_AudioSpec audiospec = { SDL_AUDIO_S8, 1, SAMPLES_PER_FRAME * FRAMES_PER_SECOND };
|
||||
SDL_DisplayID primary_display;
|
||||
int zoom = 2;
|
||||
int i;
|
||||
Uint8 r, g, b;
|
||||
|
||||
if (!SDL_SetAppMetadata("SDL 3 BytePusher", "1.0", "com.example.SDL3BytePusher")) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)SDL_arraysize(extended_metadata); i++) {
|
||||
if (!SDL_SetAppMetadataProperty(extended_metadata[i].key, extended_metadata[i].value)) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO)) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (!(vm = (BytePusher *)SDL_calloc(1, sizeof(*vm)))) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
*(BytePusher**)appstate = vm;
|
||||
|
||||
vm->display_help = true;
|
||||
|
||||
primary_display = SDL_GetPrimaryDisplay();
|
||||
if (SDL_GetDisplayUsableBounds(primary_display, &usable_bounds)) {
|
||||
int zoom_w = (usable_bounds.w - usable_bounds.x) * 2 / 3 / SCREEN_W;
|
||||
int zoom_h = (usable_bounds.h - usable_bounds.y) * 2 / 3 / SCREEN_H;
|
||||
zoom = zoom_w < zoom_h ? zoom_w : zoom_h;
|
||||
if (zoom < 1) {
|
||||
zoom = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SDL_CreateWindowAndRenderer("SDL 3 BytePusher",
|
||||
SCREEN_W * zoom, SCREEN_H * zoom, SDL_WINDOW_RESIZABLE,
|
||||
&vm->window, &vm->renderer
|
||||
)) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (!SDL_SetRenderLogicalPresentation(
|
||||
vm->renderer, SCREEN_W, SCREEN_H, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE
|
||||
)) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (!(vm->palette = SDL_CreatePalette(256))) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
i = 0;
|
||||
for (r = 0; r < 6; ++r) {
|
||||
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 };
|
||||
vm->palette->colors[i] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; i < 256; ++i) {
|
||||
SDL_Color color = { 0, 0, 0, SDL_ALPHA_OPAQUE };
|
||||
vm->palette->colors[i] = color;
|
||||
}
|
||||
|
||||
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_SetTexturePalette(vm->texture, vm->palette);
|
||||
SDL_SetTextureScaleMode(vm->texture, SDL_SCALEMODE_NEAREST);
|
||||
SDL_SetTextureScaleMode(vm->rendertarget, SDL_SCALEMODE_NEAREST);
|
||||
|
||||
if (!(vm->audiostream = SDL_OpenAudioDeviceStream(
|
||||
SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audiospec, NULL, NULL
|
||||
))) {
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
SDL_SetAudioStreamGain(vm->audiostream, 0.1f); /* examples are loud! */
|
||||
SDL_ResumeAudioStreamDevice(vm->audiostream);
|
||||
|
||||
set_status(vm, "renderer: %s", SDL_GetRendererName(vm->renderer));
|
||||
|
||||
vm->last_tick = SDL_GetTicksNS();
|
||||
vm->tick_acc = NS_PER_SECOND;
|
||||
|
||||
if (argc > 1) {
|
||||
load_file(vm, argv[1]);
|
||||
}
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppIterate(void* appstate) {
|
||||
BytePusher* vm = (BytePusher*)appstate;
|
||||
|
||||
Uint64 tick = SDL_GetTicksNS();
|
||||
Uint64 delta = tick - vm->last_tick;
|
||||
bool updated, skip_audio;
|
||||
|
||||
vm->last_tick = tick;
|
||||
|
||||
vm->tick_acc += delta * FRAMES_PER_SECOND;
|
||||
updated = vm->tick_acc >= NS_PER_SECOND;
|
||||
skip_audio = vm->tick_acc >= MAX_AUDIO_LATENCY_FRAMES * NS_PER_SECOND;
|
||||
|
||||
if (skip_audio) {
|
||||
// don't let audio fall too far behind
|
||||
SDL_ClearAudioStream(vm->audiostream);
|
||||
}
|
||||
|
||||
while (vm->tick_acc >= NS_PER_SECOND) {
|
||||
Uint32 pc;
|
||||
int i;
|
||||
|
||||
vm->tick_acc -= NS_PER_SECOND;
|
||||
|
||||
vm->ram[IO_KEYBOARD] = (Uint8)(vm->keystate >> 8);
|
||||
vm->ram[IO_KEYBOARD + 1] = (Uint8)(vm->keystate);
|
||||
|
||||
pc = read_u24(vm, IO_PC);
|
||||
for (i = 0; i < SCREEN_W * SCREEN_H; ++i) {
|
||||
Uint32 src = read_u24(vm, pc);
|
||||
Uint32 dst = read_u24(vm, pc + 3);
|
||||
vm->ram[dst] = vm->ram[src];
|
||||
pc = read_u24(vm, pc + 6);
|
||||
}
|
||||
|
||||
if (!skip_audio || vm->tick_acc < NS_PER_SECOND) {
|
||||
SDL_PutAudioStreamData(
|
||||
vm->audiostream,
|
||||
&vm->ram[(Uint32)read_u16(vm, IO_AUDIO_BANK) << 8],
|
||||
SAMPLES_PER_FRAME
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
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 (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);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(vm->renderer, NULL);
|
||||
SDL_RenderClear(vm->renderer);
|
||||
SDL_RenderTexture(vm->renderer, vm->rendertarget, NULL, NULL);
|
||||
SDL_RenderPresent(vm->renderer);
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
static Uint16 keycode_mask(SDL_Keycode key) {
|
||||
int index;
|
||||
if (key >= SDLK_0 && key <= SDLK_9) {
|
||||
index = key - SDLK_0;
|
||||
} else if (key >= SDLK_A && key <= SDLK_F) {
|
||||
index = key - SDLK_A + 10;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return (Uint16)1 << index;
|
||||
}
|
||||
|
||||
static Uint16 scancode_mask(SDL_Scancode scancode) {
|
||||
int index;
|
||||
switch (scancode) {
|
||||
case SDL_SCANCODE_1: index = 0x1; break;
|
||||
case SDL_SCANCODE_2: index = 0x2; break;
|
||||
case SDL_SCANCODE_3: index = 0x3; break;
|
||||
case SDL_SCANCODE_4: index = 0xc; break;
|
||||
case SDL_SCANCODE_Q: index = 0x4; break;
|
||||
case SDL_SCANCODE_W: index = 0x5; break;
|
||||
case SDL_SCANCODE_E: index = 0x6; break;
|
||||
case SDL_SCANCODE_R: index = 0xd; break;
|
||||
case SDL_SCANCODE_A: index = 0x7; break;
|
||||
case SDL_SCANCODE_S: index = 0x8; break;
|
||||
case SDL_SCANCODE_D: index = 0x9; break;
|
||||
case SDL_SCANCODE_F: index = 0xe; break;
|
||||
case SDL_SCANCODE_Z: index = 0xa; break;
|
||||
case SDL_SCANCODE_X: index = 0x0; break;
|
||||
case SDL_SCANCODE_C: index = 0xb; break;
|
||||
case SDL_SCANCODE_V: index = 0xf; break;
|
||||
default: return 0;
|
||||
}
|
||||
return (Uint16)1 << index;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {
|
||||
BytePusher* vm = (BytePusher*)appstate;
|
||||
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return SDL_APP_SUCCESS;
|
||||
|
||||
case SDL_EVENT_DROP_FILE:
|
||||
load_file(vm, event->drop.data);
|
||||
break;
|
||||
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
#ifndef __EMSCRIPTEN__
|
||||
if (event->key.key == SDLK_ESCAPE) {
|
||||
return SDL_APP_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
if (event->key.key == SDLK_RETURN) {
|
||||
vm->positional_input = !vm->positional_input;
|
||||
vm->keystate = 0;
|
||||
if (vm->positional_input) {
|
||||
set_status(vm, "switched to positional input");
|
||||
} else {
|
||||
set_status(vm, "switched to symbolic input");
|
||||
}
|
||||
}
|
||||
if (vm->positional_input) {
|
||||
vm->keystate |= scancode_mask(event->key.scancode);
|
||||
} else {
|
||||
vm->keystate |= keycode_mask(event->key.key);
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_EVENT_KEY_UP:
|
||||
if (vm->positional_input) {
|
||||
vm->keystate &= ~scancode_mask(event->key.scancode);
|
||||
} else {
|
||||
vm->keystate &= ~keycode_mask(event->key.key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
void SDL_AppQuit(void* appstate, SDL_AppResult result) {
|
||||
if (result == SDL_APP_FAILURE) {
|
||||
SDL_Log("Error: %s", SDL_GetError());
|
||||
}
|
||||
if (appstate) {
|
||||
BytePusher* vm = (BytePusher*)appstate;
|
||||
SDL_DestroyAudioStream(vm->audiostream);
|
||||
SDL_DestroyTexture(vm->rendertarget);
|
||||
SDL_DestroyTexture(vm->texture);
|
||||
SDL_DestroyPalette(vm->palette);
|
||||
SDL_DestroyRenderer(vm->renderer);
|
||||
SDL_DestroyWindow(vm->window);
|
||||
SDL_free(vm);
|
||||
}
|
||||
}
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/demo/04-bytepusher/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 420 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/demo/04-bytepusher/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
1
thirdparty/SDL3-3.4.0/examples/demo/description.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Full game and app demos
|
||||
79
thirdparty/SDL3-3.4.0/examples/highlight-plugin.lua
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
-- This code adapted from https://gitlab.com/saalen/highlight/-/wikis/Plug-Ins
|
||||
|
||||
-- first add a description of what the plug-in does
|
||||
Description="Add wiki.libsdl.org reference links to HTML, LaTeX or RTF output"
|
||||
|
||||
-- define the plugin categories (ie. supported output formats; languages)
|
||||
Categories = { "c", "c++" }
|
||||
|
||||
-- the syntaxUpdate function contains code related to syntax recognition
|
||||
function syntaxUpdate(desc)
|
||||
|
||||
-- if the current file is not C/C++ file we exit
|
||||
if desc~="C and C++" then
|
||||
return
|
||||
end
|
||||
|
||||
-- this function returns a qt-project reference link of the given token
|
||||
function getURL(token)
|
||||
-- generate the URL
|
||||
url='https://wiki.libsdl.org/SDL3/'.. token
|
||||
|
||||
-- embed the URL in a hyperlink according to the output format
|
||||
-- first HTML, then LaTeX and RTF
|
||||
if (HL_OUTPUT== HL_FORMAT_HTML or HL_OUTPUT == HL_FORMAT_XHTML) then
|
||||
return '<a class="hl" target="new" href="'
|
||||
.. url .. '">'.. token .. '</a>'
|
||||
elseif (HL_OUTPUT == HL_FORMAT_LATEX) then
|
||||
return '\\href{'..url..'}{'..token..'}'
|
||||
elseif (HL_OUTPUT == HL_FORMAT_RTF) then
|
||||
return '{{\\field{\\*\\fldinst HYPERLINK "'
|
||||
..url..'" }{\\fldrslt\\ul\\ulc0 '..token..'}}}'
|
||||
end
|
||||
end
|
||||
|
||||
-- the Decorate function will be invoked for every recognized token
|
||||
function Decorate(token, state)
|
||||
|
||||
-- we are only interested in keywords, preprocessor or default items
|
||||
if (state ~= HL_STANDARD and state ~= HL_KEYWORD and
|
||||
state ~=HL_PREPROC) then
|
||||
return
|
||||
end
|
||||
|
||||
-- SDL keywords start with SDL_
|
||||
-- if this pattern applies to the token, we return the URL
|
||||
-- if we return nothing, the token is outputted as is
|
||||
if ( (token == "Uint8") or (token == "Uint16") or (token == "Uint32") or (token == "Uint64") or
|
||||
(token == "Sint8") or (token == "Sint16") or (token == "Sint32") or (token == "Sint64") or
|
||||
(string.find(token, "SDL_") == 1) ) then
|
||||
return getURL(token)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- the themeUpdate function contains code related to the theme
|
||||
function themeUpdate(desc)
|
||||
-- the Injections table can be used to add style information to the theme
|
||||
|
||||
-- HTML: we add additional CSS style information to beautify hyperlinks,
|
||||
-- they should have the same color as their surrounding tags
|
||||
if (HL_OUTPUT == HL_FORMAT_HTML or HL_OUTPUT == HL_FORMAT_XHTML) then
|
||||
Injections[#Injections+1]=
|
||||
"a.hl, a.hl:visited {color:inherit;font-weight:inherit;text-decoration:none}"
|
||||
|
||||
-- LaTeX: hyperlinks require the hyperref package, so we add this here
|
||||
-- the colorlinks and pdfborderstyle options remove ugly boxes in the output
|
||||
elseif (HL_OUTPUT==HL_FORMAT_LATEX) then
|
||||
Injections[#Injections+1]=
|
||||
"\\usepackage[colorlinks=false, pdfborderstyle={/S/U/W 1}]{hyperref}"
|
||||
end
|
||||
end
|
||||
|
||||
-- let highlight load the chunks
|
||||
Plugins={
|
||||
{ Type="lang", Chunk=syntaxUpdate },
|
||||
{ Type="theme", Chunk=themeUpdate },
|
||||
}
|
||||
|
||||
2
thirdparty/SDL3-3.4.0/examples/input/01-joystick-polling/README.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
This example code looks for the current joystick state once per frame,
|
||||
and draws a visual representation of it.
|
||||
193
thirdparty/SDL3-3.4.0/examples/input/01-joystick-polling/joystick-polling.c
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* This example code looks for the current joystick state once per frame,
|
||||
* and draws a visual representation of it.
|
||||
*
|
||||
* 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 joysticks, but for simplicity, this program only
|
||||
deals with the first stick 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_Joystick *joystick = NULL;
|
||||
static SDL_Color colors[64];
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_SetAppMetadata("Example Input Joystick Polling", "1.0", "com.example.input-joystick-polling");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for (i = 0; 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;
|
||||
}
|
||||
|
||||
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_JOYSTICK_ADDED) {
|
||||
/* this event is sent for each hotplugged stick, but also each already-connected joystick during SDL_Init(). */
|
||||
if (joystick == NULL) { /* we don't have a stick yet and one was added, open it! */
|
||||
joystick = SDL_OpenJoystick(event->jdevice.which);
|
||||
if (!joystick) {
|
||||
SDL_Log("Failed to open joystick ID %u: %s", (unsigned int) event->jdevice.which, SDL_GetError());
|
||||
}
|
||||
}
|
||||
} else if (event->type == SDL_EVENT_JOYSTICK_REMOVED) {
|
||||
if (joystick && (SDL_GetJoystickID(joystick) == event->jdevice.which)) {
|
||||
SDL_CloseJoystick(joystick); /* our joystick was unplugged. */
|
||||
joystick = 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)
|
||||
{
|
||||
int winw = 640, winh = 480;
|
||||
const char *text = "Plug in a joystick, please.";
|
||||
float x, y;
|
||||
int i;
|
||||
|
||||
if (joystick) { /* we have a stick opened? */
|
||||
text = SDL_GetJoystickName(joystick);
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_GetWindowSize(window, &winw, &winh);
|
||||
|
||||
/* 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 (joystick) { /* we have a stick opened? */
|
||||
const float size = 30.0f;
|
||||
int total;
|
||||
|
||||
/* draw axes as bars going across middle of screen. We don't know if it's an X or Y or whatever axis, so we can't do more than this. */
|
||||
total = SDL_GetNumJoystickAxes(joystick);
|
||||
y = (winh - (total * size)) / 2;
|
||||
x = ((float) winw) / 2.0f;
|
||||
for (i = 0; i < total; i++) {
|
||||
const SDL_Color *color = &colors[i % SDL_arraysize(colors)];
|
||||
const float val = (((float) SDL_GetJoystickAxis(joystick, i)) / 32767.0f); /* make it -1.0f to 1.0f */
|
||||
const float dx = x + (val * x);
|
||||
const SDL_FRect dst = { dx, y, x - SDL_fabsf(dx), size };
|
||||
SDL_SetRenderDrawColor(renderer, color->r, color->g, color->b, color->a);
|
||||
SDL_RenderFillRect(renderer, &dst);
|
||||
y += size;
|
||||
}
|
||||
|
||||
/* draw buttons as blocks across top of window. We only know the button numbers, but not where they are on the device. */
|
||||
total = SDL_GetNumJoystickButtons(joystick);
|
||||
x = (winw - (total * size)) / 2;
|
||||
for (i = 0; i < total; i++) {
|
||||
const SDL_Color *color = &colors[i % SDL_arraysize(colors)];
|
||||
const SDL_FRect dst = { x, 0.0f, size, size };
|
||||
if (SDL_GetJoystickButton(joystick, i)) {
|
||||
SDL_SetRenderDrawColor(renderer, color->r, color->g, color->b, color->a);
|
||||
} else {
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
}
|
||||
SDL_RenderFillRect(renderer, &dst);
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, color->a);
|
||||
SDL_RenderRect(renderer, &dst); /* outline it */
|
||||
x += size;
|
||||
}
|
||||
|
||||
/* draw hats across the bottom of the screen. */
|
||||
total = SDL_GetNumJoystickHats(joystick);
|
||||
x = ((winw - (total * (size * 2.0f))) / 2.0f) + (size / 2.0f);
|
||||
y = ((float) winh) - size;
|
||||
for (i = 0; i < total; i++) {
|
||||
const SDL_Color *color = &colors[i % SDL_arraysize(colors)];
|
||||
const float thirdsize = size / 3.0f;
|
||||
const SDL_FRect cross[] = { { x, y + thirdsize, size, thirdsize }, { x + thirdsize, y, thirdsize, size } };
|
||||
const Uint8 hat = SDL_GetJoystickHat(joystick, i);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 90, 90, 90, 255);
|
||||
SDL_RenderFillRects(renderer, cross, SDL_arraysize(cross));
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, color->r, color->g, color->b, color->a);
|
||||
|
||||
if (hat & SDL_HAT_UP) {
|
||||
const SDL_FRect dst = { x + thirdsize, y, thirdsize, thirdsize };
|
||||
SDL_RenderFillRect(renderer, &dst);
|
||||
}
|
||||
|
||||
if (hat & SDL_HAT_RIGHT) {
|
||||
const SDL_FRect dst = { x + (thirdsize * 2), y + thirdsize, thirdsize, thirdsize };
|
||||
SDL_RenderFillRect(renderer, &dst);
|
||||
}
|
||||
|
||||
if (hat & SDL_HAT_DOWN) {
|
||||
const SDL_FRect dst = { x + thirdsize, y + (thirdsize * 2), thirdsize, thirdsize };
|
||||
SDL_RenderFillRect(renderer, &dst);
|
||||
}
|
||||
|
||||
if (hat & SDL_HAT_LEFT) {
|
||||
const SDL_FRect dst = { x, y + thirdsize, thirdsize, thirdsize };
|
||||
SDL_RenderFillRect(renderer, &dst);
|
||||
}
|
||||
|
||||
x += size * 2;
|
||||
}
|
||||
}
|
||||
|
||||
x = (((float) winw) - (SDL_strlen(text) * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE)) / 2.0f;
|
||||
y = (((float) winh) - SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) / 2.0f;
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
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)
|
||||
{
|
||||
if (joystick) {
|
||||
SDL_CloseJoystick(joystick);
|
||||
}
|
||||
|
||||
/* SDL will clean up the window/renderer for us. */
|
||||
}
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/input/01-joystick-polling/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/input/01-joystick-polling/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
2
thirdparty/SDL3-3.4.0/examples/input/02-joystick-events/README.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
This example code looks for joystick input in the event handler, and
|
||||
reports any changes as a flood of info.
|
||||
232
thirdparty/SDL3-3.4.0/examples/input/02-joystick-events/joystick-events.c
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* This example code looks for joystick 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 *hat_state_string(Uint8 state)
|
||||
{
|
||||
switch (state) {
|
||||
case SDL_HAT_CENTERED: return "CENTERED";
|
||||
case SDL_HAT_UP: return "UP";
|
||||
case SDL_HAT_RIGHT: return "RIGHT";
|
||||
case SDL_HAT_DOWN: return "DOWN";
|
||||
case SDL_HAT_LEFT: return "LEFT";
|
||||
case SDL_HAT_RIGHTUP: return "RIGHT+UP";
|
||||
case SDL_HAT_RIGHTDOWN: return "RIGHT+DOWN";
|
||||
case SDL_HAT_LEFTUP: return "LEFT+UP";
|
||||
case SDL_HAT_LEFTDOWN: return "LEFT+DOWN";
|
||||
default: break;
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
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 Joystick Events", "1.0", "com.example.input-joystick-events");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 joystick.");
|
||||
|
||||
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_JOYSTICK_ADDED) {
|
||||
/* this event is sent for each hotplugged stick, but also each already-connected joystick during SDL_Init(). */
|
||||
const SDL_JoystickID which = event->jdevice.which;
|
||||
SDL_Joystick *joystick = SDL_OpenJoystick(which);
|
||||
if (!joystick) {
|
||||
add_message(which, "Joystick #%u add, but not opened: %s", (unsigned int) which, SDL_GetError());
|
||||
} else {
|
||||
add_message(which, "Joystick #%u ('%s') added", (unsigned int) which, SDL_GetJoystickName(joystick));
|
||||
}
|
||||
} else if (event->type == SDL_EVENT_JOYSTICK_REMOVED) {
|
||||
const SDL_JoystickID which = event->jdevice.which;
|
||||
SDL_Joystick *joystick = SDL_GetJoystickFromID(which);
|
||||
if (joystick) {
|
||||
SDL_CloseJoystick(joystick); /* the joystick was unplugged. */
|
||||
}
|
||||
add_message(which, "Joystick #%u removed", (unsigned int) which);
|
||||
} else if (event->type == SDL_EVENT_JOYSTICK_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->jaxis.which;
|
||||
axis_motion_cooldown_time = now + MOTION_EVENT_COOLDOWN;
|
||||
add_message(which, "Joystick #%u axis %d -> %d", (unsigned int) which, (int) event->jaxis.axis, (int) event->jaxis.value);
|
||||
}
|
||||
} else if (event->type == SDL_EVENT_JOYSTICK_BALL_MOTION) {
|
||||
static Uint64 ball_motion_cooldown_time = 0; /* these are spammy, only show every X milliseconds. */
|
||||
const Uint64 now = SDL_GetTicks();
|
||||
if (now >= ball_motion_cooldown_time) {
|
||||
const SDL_JoystickID which = event->jball.which;
|
||||
ball_motion_cooldown_time = now + MOTION_EVENT_COOLDOWN;
|
||||
add_message(which, "Joystick #%u ball %d -> %d, %d", (unsigned int) which, (int) event->jball.ball, (int) event->jball.xrel, (int) event->jball.yrel);
|
||||
}
|
||||
} else if (event->type == SDL_EVENT_JOYSTICK_HAT_MOTION) {
|
||||
const SDL_JoystickID which = event->jhat.which;
|
||||
add_message(which, "Joystick #%u hat %d -> %s", (unsigned int) which, (int) event->jhat.hat, hat_state_string(event->jhat.value));
|
||||
} else if ((event->type == SDL_EVENT_JOYSTICK_BUTTON_UP) || (event->type == SDL_EVENT_JOYSTICK_BUTTON_DOWN)) {
|
||||
const SDL_JoystickID which = event->jbutton.which;
|
||||
add_message(which, "Joystick #%u button %d -> %s", (unsigned int) which, (int) event->jbutton.button, event->jbutton.down ? "PRESSED" : "RELEASED");
|
||||
} else if (event->type == SDL_EVENT_JOYSTICK_BATTERY_UPDATED) {
|
||||
const SDL_JoystickID which = event->jbattery.which;
|
||||
add_message(which, "Joystick #%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 will clean up the window/renderer for us. We let the joysticks leak. */
|
||||
}
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/input/02-joystick-events/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 534 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/input/02-joystick-events/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
11
thirdparty/SDL3-3.4.0/examples/input/03-gamepad-polling/README.txt
vendored
Normal file
@@ -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.
|
||||
|
||||
221
thirdparty/SDL3-3.4.0/examples/input/03-gamepad-polling/gamepad-polling.c
vendored
Normal file
@@ -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. */
|
||||
}
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/input/03-gamepad-polling/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/input/03-gamepad-polling/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
2
thirdparty/SDL3-3.4.0/examples/input/04-gamepad-events/README.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
This example code looks for gamepad input in the event handler, and
|
||||
reports any changes as a flood of info.
|
||||
212
thirdparty/SDL3-3.4.0/examples/input/04-gamepad-events/gamepad-events.c
vendored
Normal file
@@ -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. */
|
||||
}
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/input/04-gamepad-events/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 435 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/input/04-gamepad-events/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 16 KiB |
4
thirdparty/SDL3-3.4.0/examples/misc/01-power/README.txt
vendored
Normal file
@@ -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!
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/misc/01-power/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 19 KiB |
155
thirdparty/SDL3-3.4.0/examples/misc/01-power/power.c
vendored
Normal 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. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/misc/01-power/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 622 B |
6
thirdparty/SDL3-3.4.0/examples/misc/02-clipboard/README.txt
vendored
Normal file
@@ -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!
|
||||
235
thirdparty/SDL3-3.4.0/examples/misc/02-clipboard/clipboard.c
vendored
Normal file
@@ -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, ©buttonrect);
|
||||
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, ©buttonrect)) {
|
||||
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, ¤ttimerect);
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
SDL_RenderRect(renderer, ¤ttimerect);
|
||||
|
||||
/* 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, ©buttonrect);
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
SDL_RenderRect(renderer, ©buttonrect);
|
||||
|
||||
/* 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. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/misc/02-clipboard/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/misc/02-clipboard/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
1
thirdparty/SDL3-3.4.0/examples/misc/description.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Various examples from smaller subsystems
|
||||
3
thirdparty/SDL3-3.4.0/examples/pen/01-drawing-lines/README.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
You need something with a pen/stylus for this to work.
|
||||
|
||||
This takes pen input and draws lines. Lines are darker when you press harder.
|
||||
121
thirdparty/SDL3-3.4.0/examples/pen/01-drawing-lines/drawing-lines.c
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This example code reads pen/stylus input and draws lines. Darker lines
|
||||
* for harder pressure.
|
||||
*
|
||||
* SDL can track multiple pens, but for simplicity here, this assumes any
|
||||
* pen input we see was from one device.
|
||||
*
|
||||
* 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 *render_target = NULL;
|
||||
static float pressure = 0.0f;
|
||||
static float previous_touch_x = -1.0f;
|
||||
static float previous_touch_y = -1.0f;
|
||||
static float tilt_x = 0.0f;
|
||||
static float tilt_y = 0.0f;
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
int w, h;
|
||||
|
||||
SDL_SetAppMetadata("Example Pen Drawing Lines", "1.0", "com.example.pen-drawing-lines");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (!SDL_CreateWindowAndRenderer("examples/pen/drawing-lines", 640, 480, 0, &window, &renderer)) {
|
||||
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* we make a render target so we can draw lines to it and not have to record and redraw every pen stroke each frame.
|
||||
Instead rendering a frame for us is a single texture draw. */
|
||||
|
||||
/* make sure the render target matches output size (for hidpi displays, etc) so drawing matches the pen's position on a tablet display. */
|
||||
SDL_GetRenderOutputSize(renderer, &w, &h);
|
||||
render_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
|
||||
if (!render_target) {
|
||||
SDL_Log("Couldn't create render target: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
/* just blank the render target to gray to start. */
|
||||
SDL_SetRenderTarget(renderer, render_target);
|
||||
SDL_SetRenderDrawColor(renderer, 100, 100, 100, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_SetRenderTarget(renderer, NULL);
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
|
||||
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. */
|
||||
}
|
||||
|
||||
/* There are several events that track the specific stages of pen activity,
|
||||
but we're only going to look for motion and pressure, for simplicity. */
|
||||
if (event->type == SDL_EVENT_PEN_MOTION) {
|
||||
/* you can check for when the pen is touching, but if pressure > 0.0f, it's definitely touching! */
|
||||
if (pressure > 0.0f) {
|
||||
if (previous_touch_x >= 0.0f) { /* only draw if we're moving while touching */
|
||||
/* draw with the alpha set to the pressure, so you effectively get a fainter line for lighter presses. */
|
||||
SDL_SetRenderTarget(renderer, render_target);
|
||||
SDL_SetRenderDrawColorFloat(renderer, 0, 0, 0, pressure);
|
||||
SDL_RenderLine(renderer, previous_touch_x, previous_touch_y, event->pmotion.x, event->pmotion.y);
|
||||
}
|
||||
previous_touch_x = event->pmotion.x;
|
||||
previous_touch_y = event->pmotion.y;
|
||||
} else {
|
||||
previous_touch_x = previous_touch_y = -1.0f;
|
||||
}
|
||||
} else if (event->type == SDL_EVENT_PEN_AXIS) {
|
||||
if (event->paxis.axis == SDL_PEN_AXIS_PRESSURE) {
|
||||
pressure = event->paxis.value; /* remember new pressure for later draws. */
|
||||
} else if(event->paxis.axis == SDL_PEN_AXIS_XTILT) {
|
||||
tilt_x = event->paxis.value;
|
||||
} else if(event->paxis.axis == SDL_PEN_AXIS_YTILT) {
|
||||
tilt_y = event->paxis.value;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char debug_text[1024];
|
||||
|
||||
/* make sure we're drawing to the window and not the render target */
|
||||
SDL_SetRenderTarget(renderer, NULL);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(renderer); /* just in case. */
|
||||
SDL_RenderTexture(renderer, render_target, NULL, NULL);
|
||||
SDL_snprintf(debug_text, sizeof(debug_text), "Tilt: %f %f", tilt_x, tilt_y);
|
||||
SDL_RenderDebugText(renderer, 0, 8, debug_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(render_target);
|
||||
/* SDL will clean up the window/renderer for us. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/pen/01-drawing-lines/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/pen/01-drawing-lines/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
3
thirdparty/SDL3-3.4.0/examples/renderer/01-clear/README.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
This example code creates an SDL window and renderer, and then clears the
|
||||
window to a different color every frame, so you'll effectively get a window
|
||||
that's smoothly fading between colors.
|
||||
69
thirdparty/SDL3-3.4.0/examples/renderer/01-clear/clear.c
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This example code creates an SDL window and renderer, and then clears the
|
||||
* window to a different color every frame, so you'll effectively get a window
|
||||
* that's smoothly fading between colors.
|
||||
*
|
||||
* 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 Renderer Clear", "1.0", "com.example.renderer-clear");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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! */
|
||||
}
|
||||
|
||||
/* 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 double now = ((double)SDL_GetTicks()) / 1000.0; /* convert from milliseconds to seconds. */
|
||||
/* choose the color for the frame we will draw. The sine wave trick makes it fade between colors smoothly. */
|
||||
const float red = (float) (0.5 + 0.5 * SDL_sin(now));
|
||||
const float green = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 2 / 3));
|
||||
const float blue = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 4 / 3));
|
||||
SDL_SetRenderDrawColorFloat(renderer, red, green, blue, SDL_ALPHA_OPAQUE_FLOAT); /* new color, full alpha. */
|
||||
|
||||
/* clear the window to the draw color. */
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
/* put the newly-cleared 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. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/01-clear/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/renderer/01-clear/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
7
thirdparty/SDL3-3.4.0/examples/renderer/02-primitives/README.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
This example creates an SDL window and renderer, and then draws some lines,
|
||||
rectangles and points to it every frame.
|
||||
|
||||
This is just a quick overview of simple drawing primitives; futher examples
|
||||
will explore them in more detail.
|
||||
|
||||
|
||||
96
thirdparty/SDL3-3.4.0/examples/renderer/02-primitives/primitives.c
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This example creates an SDL window and renderer, and then draws some lines,
|
||||
* rectangles and points to it 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_FPoint points[500];
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_SetAppMetadata("Example Renderer Primitives", "1.0", "com.example.renderer-primitives");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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++) {
|
||||
points[i].x = (SDL_randf() * 440.0f) + 100.0f;
|
||||
points[i].y = (SDL_randf() * 280.0f) + 100.0f;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SDL_FRect rect;
|
||||
|
||||
/* as you can see from this, rendering draws over whatever was drawn before it. */
|
||||
SDL_SetRenderDrawColor(renderer, 33, 33, 33, SDL_ALPHA_OPAQUE); /* dark gray, full alpha */
|
||||
SDL_RenderClear(renderer); /* start with a blank canvas. */
|
||||
|
||||
/* draw a filled rectangle in the middle of the canvas. */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 255, SDL_ALPHA_OPAQUE); /* blue, full alpha */
|
||||
rect.x = rect.y = 100;
|
||||
rect.w = 440;
|
||||
rect.h = 280;
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
|
||||
/* draw some points across the canvas. */
|
||||
SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE); /* red, full alpha */
|
||||
SDL_RenderPoints(renderer, points, SDL_arraysize(points));
|
||||
|
||||
/* draw a unfilled rectangle in-set a little bit. */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); /* green, full alpha */
|
||||
rect.x += 30;
|
||||
rect.y += 30;
|
||||
rect.w -= 60;
|
||||
rect.h -= 60;
|
||||
SDL_RenderRect(renderer, &rect);
|
||||
|
||||
/* draw two lines in an X across the whole canvas. */
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 0, SDL_ALPHA_OPAQUE); /* yellow, full alpha */
|
||||
SDL_RenderLine(renderer, 0, 0, 640, 480);
|
||||
SDL_RenderLine(renderer, 0, 480, 640, 0);
|
||||
|
||||
SDL_RenderPresent(renderer); /* put it all on the screen! */
|
||||
|
||||
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. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/02-primitives/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
3
thirdparty/SDL3-3.4.0/examples/renderer/03-lines/README.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
This example creates an SDL window and renderer, and then draws a something
|
||||
roughly like a Christmas tree with nothing but lines, every frame.
|
||||
|
||||
95
thirdparty/SDL3-3.4.0/examples/renderer/03-lines/lines.c
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This example creates an SDL window and renderer, and then draws some lines
|
||||
* to it 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;
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
SDL_SetAppMetadata("Example Renderer Lines", "1.0", "com.example.renderer-lines");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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! */
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Lines (line segments, really) are drawn in terms of points: a set of
|
||||
X and Y coordinates, one set for each end of the line.
|
||||
(0, 0) is the top left of the window, and larger numbers go down
|
||||
and to the right. This isn't how geometry works, but this is pretty
|
||||
standard in 2D graphics. */
|
||||
static const SDL_FPoint line_points[] = {
|
||||
{ 100, 354 }, { 220, 230 }, { 140, 230 }, { 320, 100 }, { 500, 230 },
|
||||
{ 420, 230 }, { 540, 354 }, { 400, 354 }, { 100, 354 }
|
||||
};
|
||||
|
||||
/* as you can see from this, rendering draws over whatever was drawn before it. */
|
||||
SDL_SetRenderDrawColor(renderer, 100, 100, 100, SDL_ALPHA_OPAQUE); /* grey, full alpha */
|
||||
SDL_RenderClear(renderer); /* start with a blank canvas. */
|
||||
|
||||
/* You can draw lines, one at a time, like these brown ones... */
|
||||
SDL_SetRenderDrawColor(renderer, 127, 49, 32, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderLine(renderer, 240, 450, 400, 450);
|
||||
SDL_RenderLine(renderer, 240, 356, 400, 356);
|
||||
SDL_RenderLine(renderer, 240, 356, 240, 450);
|
||||
SDL_RenderLine(renderer, 400, 356, 400, 450);
|
||||
|
||||
/* You can also draw a series of connected lines in a single batch... */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderLines(renderer, line_points, SDL_arraysize(line_points));
|
||||
|
||||
/* here's a bunch of lines drawn out from a center point in a circle. */
|
||||
/* we randomize the color of each line, so it functions as animation. */
|
||||
for (i = 0; i < 360; i++) {
|
||||
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_cosf(r) * size, y + SDL_sinf(r) * size);
|
||||
}
|
||||
|
||||
SDL_RenderPresent(renderer); /* put it all on the screen! */
|
||||
|
||||
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. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/03-lines/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
thirdparty/SDL3-3.4.0/examples/renderer/03-lines/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
3
thirdparty/SDL3-3.4.0/examples/renderer/04-points/README.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
This example creates an SDL window and renderer, and then draws a bunch of
|
||||
single points, moving across the screen.
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/04-points/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 152 KiB |
119
thirdparty/SDL3-3.4.0/examples/renderer/04-points/points.c
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* This example creates an SDL window and renderer, and then draws some points
|
||||
* to it 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 Uint64 last_time = 0;
|
||||
|
||||
#define WINDOW_WIDTH 640
|
||||
#define WINDOW_HEIGHT 480
|
||||
|
||||
#define NUM_POINTS 500
|
||||
#define MIN_PIXELS_PER_SECOND 30 /* move at least this many pixels per second. */
|
||||
#define MAX_PIXELS_PER_SECOND 60 /* move this many pixels per second at most. */
|
||||
|
||||
/* (track everything as parallel arrays instead of a array of structs,
|
||||
so we can pass the coordinates to the renderer in a single function call.) */
|
||||
|
||||
/* Points are plotted as a set of X and Y coordinates.
|
||||
(0, 0) is the top left of the window, and larger numbers go down
|
||||
and to the right. This isn't how geometry works, but this is pretty
|
||||
standard in 2D graphics. */
|
||||
static SDL_FPoint points[NUM_POINTS];
|
||||
static float point_speeds[NUM_POINTS];
|
||||
|
||||
/* This function runs once at startup. */
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_SetAppMetadata("Example Renderer Points", "1.0", "com.example.renderer-points");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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++) {
|
||||
points[i].x = SDL_randf() * ((float) WINDOW_WIDTH);
|
||||
points[i].y = SDL_randf() * ((float) WINDOW_HEIGHT);
|
||||
point_speeds[i] = MIN_PIXELS_PER_SECOND + (SDL_randf() * (MAX_PIXELS_PER_SECOND - MIN_PIXELS_PER_SECOND));
|
||||
}
|
||||
|
||||
last_time = SDL_GetTicks();
|
||||
|
||||
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 Uint64 now = SDL_GetTicks();
|
||||
const float elapsed = ((float) (now - last_time)) / 1000.0f; /* seconds since last iteration */
|
||||
int i;
|
||||
|
||||
/* let's move all our points a little for a new frame. */
|
||||
for (i = 0; i < SDL_arraysize(points); i++) {
|
||||
const float distance = elapsed * point_speeds[i];
|
||||
points[i].x += distance;
|
||||
points[i].y += distance;
|
||||
if ((points[i].x >= WINDOW_WIDTH) || (points[i].y >= WINDOW_HEIGHT)) {
|
||||
/* off the screen; restart it elsewhere! */
|
||||
if (SDL_rand(2)) {
|
||||
points[i].x = SDL_randf() * ((float) WINDOW_WIDTH);
|
||||
points[i].y = 0.0f;
|
||||
} else {
|
||||
points[i].x = 0.0f;
|
||||
points[i].y = SDL_randf() * ((float) WINDOW_HEIGHT);
|
||||
}
|
||||
point_speeds[i] = MIN_PIXELS_PER_SECOND + (SDL_randf() * (MAX_PIXELS_PER_SECOND - MIN_PIXELS_PER_SECOND));
|
||||
}
|
||||
}
|
||||
|
||||
last_time = now;
|
||||
|
||||
/* as you can see from this, rendering draws over whatever was drawn before it. */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
|
||||
SDL_RenderClear(renderer); /* start with a blank canvas. */
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */
|
||||
SDL_RenderPoints(renderer, points, SDL_arraysize(points)); /* draw all the points! */
|
||||
|
||||
/* You can also draw single points with SDL_RenderPoint(), but it's
|
||||
cheaper (sometimes significantly so) to do them all at once. */
|
||||
|
||||
SDL_RenderPresent(renderer); /* put it all on the screen! */
|
||||
|
||||
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. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/04-points/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
3
thirdparty/SDL3-3.4.0/examples/renderer/05-rectangles/README.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
This example creates an SDL window and renderer, and then draws a few
|
||||
rectangles that change size each frame.
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/05-rectangles/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 74 KiB |
113
thirdparty/SDL3-3.4.0/examples/renderer/05-rectangles/rectangles.c
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* This example creates an SDL window and renderer, and then draws some
|
||||
* rectangles to it 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;
|
||||
|
||||
#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_SetAppMetadata("Example Renderer Rectangles", "1.0", "com.example.renderer-rectangles");
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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! */
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
SDL_FRect rects[16];
|
||||
const Uint64 now = SDL_GetTicks();
|
||||
int i;
|
||||
|
||||
/* we'll have the rectangles grow and shrink over a few seconds. */
|
||||
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
|
||||
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
|
||||
|
||||
/* as you can see from this, rendering draws over whatever was drawn before it. */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
|
||||
SDL_RenderClear(renderer); /* start with a blank canvas. */
|
||||
|
||||
/* Rectangles are comprised of set of X and Y coordinates, plus width and
|
||||
height. (0, 0) is the top left of the window, and larger numbers go
|
||||
down and to the right. This isn't how geometry works, but this is
|
||||
pretty standard in 2D graphics. */
|
||||
|
||||
/* Let's draw a single rectangle (square, really). */
|
||||
rects[0].x = rects[0].y = 100;
|
||||
rects[0].w = rects[0].h = 100 + (100 * scale);
|
||||
SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE); /* red, full alpha */
|
||||
SDL_RenderRect(renderer, &rects[0]);
|
||||
|
||||
/* Now let's draw several rectangles with one function call. */
|
||||
for (i = 0; i < 3; i++) {
|
||||
const float size = (i+1) * 50.0f;
|
||||
rects[i].w = rects[i].h = size + (size * scale);
|
||||
rects[i].x = (WINDOW_WIDTH - rects[i].w) / 2; /* center it. */
|
||||
rects[i].y = (WINDOW_HEIGHT - rects[i].h) / 2; /* center it. */
|
||||
}
|
||||
SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); /* green, full alpha */
|
||||
SDL_RenderRects(renderer, rects, 3); /* draw three rectangles at once */
|
||||
|
||||
/* those were rectangle _outlines_, really. You can also draw _filled_ rectangles! */
|
||||
rects[0].x = 400;
|
||||
rects[0].y = 50;
|
||||
rects[0].w = 100 + (100 * scale);
|
||||
rects[0].h = 50 + (50 * scale);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 255, SDL_ALPHA_OPAQUE); /* blue, full alpha */
|
||||
SDL_RenderFillRect(renderer, &rects[0]);
|
||||
|
||||
/* ...and also fill a bunch of rectangles at once... */
|
||||
for (i = 0; i < SDL_arraysize(rects); i++) {
|
||||
const float w = (float) (WINDOW_WIDTH / SDL_arraysize(rects));
|
||||
const float h = i * 8.0f;
|
||||
rects[i].x = i * w;
|
||||
rects[i].y = WINDOW_HEIGHT - h;
|
||||
rects[i].w = w;
|
||||
rects[i].h = h;
|
||||
}
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */
|
||||
SDL_RenderFillRects(renderer, rects, SDL_arraysize(rects));
|
||||
|
||||
SDL_RenderPresent(renderer); /* put it all on the screen! */
|
||||
|
||||
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. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/05-rectangles/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
3
thirdparty/SDL3-3.4.0/examples/renderer/06-textures/README.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
This example creates an SDL window and renderer, loads a texture from a
|
||||
.png file, and then draws it a few times each frame.
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/06-textures/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 592 KiB |
128
thirdparty/SDL3-3.4.0/examples/renderer/06-textures/textures.c
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* This example creates an SDL window and renderer, and then draws some
|
||||
* textures to it 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 Textures", "1.0", "com.example.renderer-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/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)
|
||||
{
|
||||
SDL_FRect dst_rect;
|
||||
const Uint64 now = SDL_GetTicks();
|
||||
|
||||
/* we'll have some textures move around over a few seconds. */
|
||||
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
|
||||
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
|
||||
|
||||
/* as you can see from this, rendering draws over whatever was drawn before it. */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
|
||||
SDL_RenderClear(renderer); /* start with a blank canvas. */
|
||||
|
||||
/* Just draw the static texture a few times. You can think of it like a
|
||||
stamp, there isn't a limit to the number of times you can draw with it. */
|
||||
|
||||
/* top left */
|
||||
dst_rect.x = (100.0f * scale);
|
||||
dst_rect.y = 0.0f;
|
||||
dst_rect.w = (float) texture_width;
|
||||
dst_rect.h = (float) texture_height;
|
||||
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
|
||||
|
||||
/* center this one. */
|
||||
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f;
|
||||
dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f;
|
||||
dst_rect.w = (float) texture_width;
|
||||
dst_rect.h = (float) texture_height;
|
||||
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
|
||||
|
||||
/* bottom right. */
|
||||
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) - (100.0f * scale);
|
||||
dst_rect.y = (float) (WINDOW_HEIGHT - texture_height);
|
||||
dst_rect.w = (float) texture_width;
|
||||
dst_rect.h = (float) texture_height;
|
||||
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
|
||||
|
||||
SDL_RenderPresent(renderer); /* put it all on the screen! */
|
||||
|
||||
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 will clean up the window/renderer for us. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/06-textures/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 233 KiB |
3
thirdparty/SDL3-3.4.0/examples/renderer/07-streaming-textures/README.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
This example creates an SDL window and renderer, then a streaming texture that
|
||||
it will update every frame before drawing it to the screen.
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/07-streaming-textures/onmouseover.webp
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
110
thirdparty/SDL3-3.4.0/examples/renderer/07-streaming-textures/streaming-textures.c
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This example creates an SDL window and renderer, and then draws a streaming
|
||||
* texture to it 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;
|
||||
|
||||
#define TEXTURE_SIZE 150
|
||||
|
||||
#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_SetAppMetadata("Example Renderer Streaming Textures", "1.0", "com.example.renderer-streaming-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/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) {
|
||||
SDL_Log("Couldn't create streaming texture: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SDL_FRect dst_rect;
|
||||
const Uint64 now = SDL_GetTicks();
|
||||
SDL_Surface *surface = NULL;
|
||||
|
||||
/* we'll have some color move around over a few seconds. */
|
||||
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
|
||||
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
|
||||
|
||||
/* 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
|
||||
locked pixel! */
|
||||
|
||||
/* You can use SDL_LockTexture() to get an array of raw pixels, but we're going to use
|
||||
SDL_LockTextureToSurface() here, because it wraps that array in a temporary SDL_Surface,
|
||||
letting us use the surface drawing functions instead of lighting up individual pixels. */
|
||||
if (SDL_LockTextureToSurface(texture, NULL, &surface)) {
|
||||
SDL_Rect r;
|
||||
SDL_FillSurfaceRect(surface, NULL, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, 0, 0, 0)); /* make the whole surface black */
|
||||
r.w = TEXTURE_SIZE;
|
||||
r.h = TEXTURE_SIZE / 10;
|
||||
r.x = 0;
|
||||
r.y = (int) (((float) (TEXTURE_SIZE - r.h)) * ((scale + 1.0f) / 2.0f));
|
||||
SDL_FillSurfaceRect(surface, &r, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, 0, 255, 0)); /* make a strip of the surface green */
|
||||
SDL_UnlockTexture(texture); /* upload the changes (and frees the temporary surface)! */
|
||||
}
|
||||
|
||||
/* as you can see from this, rendering draws over whatever was drawn before it. */
|
||||
SDL_SetRenderDrawColor(renderer, 66, 66, 66, SDL_ALPHA_OPAQUE); /* grey, full alpha */
|
||||
SDL_RenderClear(renderer); /* start with a blank canvas. */
|
||||
|
||||
/* Just draw the static texture a few times. You can think of it like a
|
||||
stamp, there isn't a limit to the number of times you can draw with it. */
|
||||
|
||||
/* Center this one. It'll draw the latest version of the texture we drew while it was locked. */
|
||||
dst_rect.x = ((float) (WINDOW_WIDTH - TEXTURE_SIZE)) / 2.0f;
|
||||
dst_rect.y = ((float) (WINDOW_HEIGHT - TEXTURE_SIZE)) / 2.0f;
|
||||
dst_rect.w = dst_rect.h = (float) TEXTURE_SIZE;
|
||||
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
|
||||
|
||||
SDL_RenderPresent(renderer); /* put it all on the screen! */
|
||||
|
||||
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 will clean up the window/renderer for us. */
|
||||
}
|
||||
|
||||
BIN
thirdparty/SDL3-3.4.0/examples/renderer/07-streaming-textures/thumbnail.png
vendored
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
3
thirdparty/SDL3-3.4.0/examples/renderer/08-rotating-textures/README.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
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.
|
||||
|
||||